LIST * builtin_subst( PARSE *parse, LOL *args, int *jmp ) { LIST *liststring; LIST *result = 0; LIST *pattern = lol_get( args, 1 ); LIST *repl = lol_get( args, 2 ); LIST *nstr = lol_get( args, 3 ); int n = nstr ? atoi( nstr->string ) : -1; /* For each string */ for( liststring = lol_get( args, 0 ); liststring; liststring = liststring->next ) { BUFFER buff; buffer_init( &buff ); str_gsub (&buff, liststring->string, pattern->string, repl ? repl->string : "", n); result = list_new( result, buffer_ptr( &buff ), 0 ); buffer_free( &buff ); } return result; }
LIST *builtin_listsort( PARSE *parse, LOL *args, int *jmp ) { LIST *l = list_copy( L0, lol_get( args, 0 ) ); LIST *caseSensitiveList = lol_get( args, 1 ); int caseSensitive = 1; if ( caseSensitiveList ) caseSensitive = atoi( caseSensitiveList->string ); l = list_sort( l, caseSensitive ); return l; }
LIST * builtin_system_registry_names( FRAME * frame, int flags ) { char const* path = object_str( list_front( lol_get(frame->args, 0) ) ); char const* result_type = object_str( list_front( lol_get(frame->args, 1) ) ); HKEY key = get_key(&path); if ( !strcmp(result_type, "subkeys") ) return get_subkey_names(key, path); if ( !strcmp(result_type, "values") ) return get_value_names(key, path); return 0; }
/* local result = ; local element ; for element in $(B) { if ! ( $(element) in $(A) ) { result += $(element) ; } } return $(result) ; */ LIST *set_difference( PARSE *parse, FRAME *frame ) { LIST* b = lol_get( frame->args, 0 ); LIST* a = lol_get( frame->args, 1 ); LIST* result = 0; for(; b; b = b->next) { if (!list_in(a, b->string)) result = list_new(result, b->string); } return result; }
/* local result = ; local element ; for element in $(B) { if ! ( $(element) in $(A) ) { result += $(element) ; } } return $(result) ; */ LIST *set_difference( FRAME *frame, int flags ) { LIST* b = lol_get( frame->args, 0 ); LIST* a = lol_get( frame->args, 1 ); LIST* result = 0; for(; b; b = b->next) { if (!list_in(a, b->value)) result = list_new(result, object_copy(b->value)); } return result; }
LIST * builtin_match( PARSE *parse, LOL *args, int *jmp ) { LIST *l, *r; LIST *result = 0; /* For each pattern */ for( l = lol_get( args, 0 ); l; l = l->next ) { regexp *re = jam_regcomp( l->string ); /* For each string to match against */ for( r = lol_get( args, 1 ); r; r = r->next ) if( jam_regexec( re, r->string ) ) { int i, top; /* Find highest parameter */ for( top = NSUBEXP; top-- > 1; ) if( re->startp[top] ) break; /* And add all parameters up to highest onto list. */ /* Must have parameters to have results! */ for( i = 1; i <= top; i++ ) { BUFFER buff; size_t l; buffer_init( &buff ); l = re->endp[i] - re->startp[i]; buffer_addstring( &buff, re->startp[i], l ); buffer_addchar( &buff, 0 ); result = list_new( result, buffer_ptr( &buff ), 0 ); buffer_free( &buff ); } } free( (char *)re ); } return result; }
/* Based on code from ftjam by David Turner */ LIST * builtin_split( PARSE *parse, LOL *args, int *jmp ) { LIST* input = lol_get( args, 0 ); LIST* tokens = lol_get( args, 1 ); LIST* result = L0; char token[256]; BUFFER buff; buffer_init( &buff ); /* build token array */ memset( token, 0, sizeof( token ) ); for ( ; tokens; tokens = tokens->next ) { const char* s = tokens->string; for ( ; *s; s++ ) token[(unsigned char)*s] = 1; } /* now parse the input and split it */ for ( ; input; input = input->next ) { const char* ptr = input->string; const char* lastPtr = input->string; while ( *ptr ) { if ( token[(unsigned char) *ptr] ) { size_t count = ptr - lastPtr; if ( count > 0 ) { buffer_reset( &buff ); buffer_addstring( &buff, lastPtr, count ); buffer_addchar( &buff, 0 ); result = list_new( result, buffer_ptr( &buff ), 0 ); } lastPtr = ptr + 1; } ++ptr; } if ( ptr > lastPtr ) result = list_new( result, lastPtr, 0 ); } buffer_free( &buff ); return result; }
LIST * builtin_usemd5callback( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); LIST *l2 = lol_get( args, 1 ); for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->settings = addsettings( t->settings, VAR_SET, "MD5CALLBACK", list_copy( L0, l2 ) ); } return L0; }
LIST* builtin_system_registry_names( PARSE *parse, FRAME *frame ) { char const* path = lol_get(frame->args, 0)->string; char const* result_type = lol_get(frame->args, 1)->string; HKEY key = get_key(&path); if ( !strcmp(result_type, "subkeys") ) return get_subkey_names(key, path); if ( !strcmp(result_type, "values") ) return get_value_names(key, path); return 0; }
LIST *builtin_subst_literalize( PARSE *parse, LOL *args, int *jmp ) { LIST *pattern; LIST *result = L0; for( pattern = lol_get( args, 0 ); pattern; pattern = pattern->next ) { const char* patternString; BUFFER patternBuff; buffer_init( &patternBuff ); for ( patternString = pattern->string; *patternString; ++patternString ) { if ( *patternString == '(' || *patternString == ')' || *patternString == '.' || *patternString == '%' || *patternString == '+' || *patternString == '-' || *patternString == '*' || *patternString == '?' || *patternString == '[' || *patternString == ']' || *patternString == '^' || *patternString == '$' ) { buffer_addchar( &patternBuff, '%' ); } buffer_addchar( &patternBuff, *patternString ); } buffer_addchar( &patternBuff, 0 ); result = list_new( result, buffer_ptr( &patternBuff ), 0 ); } return result; }
void call_bind_rule( OBJECT * target_, OBJECT * boundname_ ) { LIST * const bind_rule = var_get( root_module(), constant_BINDRULE ); if ( !list_empty( bind_rule ) ) { OBJECT * target = object_copy( target_ ); OBJECT * boundname = object_copy( boundname_ ); if ( boundname && target ) { /* Prepare the argument list. */ FRAME frame[ 1 ]; frame_init( frame ); /* First argument is the target name. */ lol_add( frame->args, list_new( target ) ); lol_add( frame->args, list_new( boundname ) ); if ( lol_get( frame->args, 1 ) ) { OBJECT * rulename = list_front( bind_rule ); list_free( evaluate_rule( bindrule( rulename, root_module() ), rulename, frame ) ); } /* Clean up */ frame_free( frame ); } else { if ( boundname ) object_free( boundname ); if ( target ) object_free( target ); } } }
LIST * builtin_md5file( PARSE *parse, LOL *args, int *jmp ) { MD5_CTX context; unsigned char digest[16]; unsigned char digest_string[33]; unsigned char* p; int i; LIST *l; LIST *result; const size_t BUFFER_SIZE = 100 * 1024; unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE); MD5Init(&context); /* For each argument */ for (i = 0; i < args->count; ++i) { l = lol_get(args, i); if (l) { do { FILE* file; TARGET *t = bindtarget(l->string); pushsettings( t->settings ); t->boundname = search( t->name, &t->time ); popsettings( t->settings ); file = fopen(t->boundname, "rb"); if (file) { size_t readSize; do { readSize = fread(buffer, 1, BUFFER_SIZE, file); MD5Update(&context, buffer, readSize); } while (readSize != 0); fclose(file); } l = list_next(l); } while (l); } } free(buffer); MD5Final(digest, &context); p = digest_string; for (i = 0, p = digest_string; i < 16; i++, p += 2) { sprintf((char*)p, "%02x", digest[i]); } *p = 0; result = list_new(L0, (const char*)digest_string, 0); return result; }
void headers( TARGET *t ) { LIST *hdrscan; LIST *hdrrule; LIST *hdrcache; LOL lol; if( !( hdrscan = var_get( "HDRSCAN" ) ) || !( hdrrule = var_get( "HDRRULE" ) ) ) return; /* Doctor up call to HDRRULE rule */ /* Call headers1() to get LIST of included files. */ if( DEBUG_HEADER ) printf( "header scan %s\n", t->name ); lol_init( &lol ); lol_add( &lol, list_new( L0, t->name, 1 ) ); lol_add( &lol, headers1( t->boundname, hdrscan ) ); if( lol_get( &lol, 1 ) ) list_free( evaluate_rule( 0, hdrrule->string, &lol, L0 ) ); /* Clean up */ lol_free( &lol ); }
/* Look up the __TIMING_RULE__ variable on the given target, and if * non-empty, invoke the rule it names, passing the given * timing_info */ static void call_timing_rule(TARGET* target, timing_info* time) { LIST* timing_rule; pushsettings(target->settings); timing_rule = var_get( "__TIMING_RULE__" ); popsettings(target->settings); if (timing_rule) { /* We'll prepend $(__TIMING_RULE__[2-]) to the first argument */ LIST* initial_args = list_copy( L0, timing_rule->next ); /* Prepare the argument list */ FRAME frame[1]; frame_init( frame ); /* First argument is the name of the timed target */ lol_add( frame->args, list_new( initial_args, target->name ) ); append_double_string(frame->args, time->user); append_double_string(frame->args, time->system); if( lol_get( frame->args, 2 ) ) evaluate_rule( timing_rule->string, frame ); /* Clean up */ frame_free( frame ); } }
LIST * builtin_math( PARSE *parse, LOL *args, int *jmp ) { char buffer[100]; int num1; int num2; int result; LIST *expression = lol_get( args, 0 ); if ( !expression || !expression->next || !expression->next->next ) return NULL; num1 = atoi( expression->string ); num2 = atoi( expression->next->next->string ); result = 0; switch ( expression->next->string[0] ) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': result = num1 / num2; break; case '%': result = num1 % num2; break; default: printf( "jam: rule Math: Unknown operator [%s].\n", expression->next->string ); exit( EXITBAD ); } sprintf(buffer, "%d", result); return list_new(L0, buffer, 0); }
LIST * regex_split( FRAME * frame, int flags ) { LIST * args = lol_get( frame->args, 0 ); OBJECT * s; OBJECT * separator; regexp * re; const char * pos; LIST * result = L0; LISTITER iter = list_begin( args ); s = list_item( iter ); separator = list_item( list_next( iter ) ); re = regex_compile( separator ); pos = object_str( s ); while ( regexec( re, pos ) ) { result = list_push_back( result, object_new_range( pos, re->startp[ 0 ] - pos ) ); pos = re->endp[ 0 ]; } result = list_push_back( result, object_new( pos ) ); return result; }
LIST * builtin_depends( PARSE *parse, LOL *args, int *jmp ) { int curindex = 0; while ( 1 ) { LIST *targets = lol_get( args, curindex ); LIST *sources = lol_get( args, curindex + 1 ); LIST *l; if ( !sources ) break; for( l = targets; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); /* If doing INCLUDES, switch to the TARGET's include */ /* TARGET, creating it if needed. The internal include */ /* TARGET shares the name of its parent. */ #ifdef OPT_BUILTIN_NEEDS_EXT if( parse->num==1 ) #else if( parse->num ) #endif { if( !t->includes ) t->includes = copytarget( t ); t = t->includes; } #ifdef OPT_BUILTIN_NEEDS_EXT t->depends = targetlist( t->depends, sources, (char)(parse->num==2) ); #else t->depends = targetlist( t->depends, sources ); #endif } ++curindex; } return L0; }
LIST * order( FRAME * frame, int flags ) { LIST * arg = lol_get( frame->args, 0 ); LIST * result = L0; int src; LISTITER iter = list_begin( arg ); LISTITER const end = list_end( arg ); /* We need to create a graph of order dependencies between the passed * objects. We assume there are no duplicates passed to 'add_pair'. */ int length = list_length( arg ); int * * graph = ( int * * )BJAM_CALLOC( length, sizeof( int * ) ); int * order = ( int * )BJAM_MALLOC( ( length + 1 ) * sizeof( int ) ); for ( src = 0; iter != end; iter = list_next( iter ), ++src ) { /* For all objects this one depends upon, add elements to 'graph'. */ LIST * dependencies = var_get( frame->module, list_item( iter ) ); int index = 0; LISTITER dep_iter = list_begin( dependencies ); LISTITER const dep_end = list_end( dependencies ); graph[ src ] = ( int * )BJAM_CALLOC( list_length( dependencies ) + 1, sizeof( int ) ); for ( ; dep_iter != dep_end; dep_iter = list_next( dep_iter ) ) { int const dst = list_index( arg, list_item( dep_iter ) ); if ( dst != -1 ) graph[ src ][ index++ ] = dst; } graph[ src ][ index ] = -1; } topological_sort( graph, length, order ); { int index = length - 1; for ( ; index >= 0; --index ) { int i; LISTITER iter = list_begin( arg ); LISTITER const end = list_end( arg ); for ( i = 0; i < order[ index ]; ++i, iter = list_next( iter ) ); result = list_push_back( result, object_copy( list_item( iter ) ) ); } } /* Clean up */ { int i; for ( i = 0; i < length; ++i ) BJAM_FREE( graph[ i ] ); BJAM_FREE( graph ); BJAM_FREE( order ); } return result; }
LIST* builtin_subst( PARSE *parse, FRAME *frame ) { LIST* result = L0; LIST* arg1 = lol_get( frame->args, 0 ); if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) ) { const char* source = arg1->string; const char* pattern = list_next(arg1)->string; regexp* repat = regex_compile( pattern ); if ( regexec( repat, (char*)source) ) { LIST* subst = list_next(arg1); while ((subst = list_next(subst)) != L0) { # define BUFLEN 4096 char buf[BUFLEN + 1]; const char* in = subst->string; char* out = buf; for ( in = subst->string; *in && out < buf + BUFLEN; ++in ) { if ( *in == '\\' || *in == '$' ) { ++in; if ( *in == 0 ) { break; } else if ( *in >= '0' && *in <= '9' ) { unsigned n = *in - '0'; const size_t srclen = repat->endp[n] - repat->startp[n]; const size_t remaining = buf + BUFLEN - out; const size_t len = srclen < remaining ? srclen : remaining; memcpy( out, repat->startp[n], len ); out += len; continue; } /* fall through and copy the next character */ } *out++ = *in; } *out = 0; result = list_new( result, newstr( buf ) ); #undef BUFLEN } } } return result; }
/* * builtin_w32_getreg64() - W32_GETREG64 rule, returns a 64bit registry entry * given a list of keys. * * Usage: result = [ W32_GETREG64 list ] ; */ static LIST* builtin_w32_getreg64( PARSE *parse, LOL *args, int *jmp ) { const char* result = w32_getreg64(lol_get(args, 0)); if (result) return list_new(L0, result, 0); return L0; }
/* Use quite klugy approach: when we add order dependency from 'a' to 'b', just append 'b' to of value of variable 'a'. */ LIST *add_pair( FRAME *frame, int flags ) { LIST* arg = lol_get( frame->args, 0 ); var_set(arg->value, list_copy(0, arg->next), VAR_APPEND); return L0; }
LIST * builtin_usecommandline( PARSE *parse, LOL *args, int *jmp ) { LIST *l = lol_get( args, 0 ); LIST *l2 = lol_get( args, 1 ); for( ; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->settings = addsettings( t->settings, VAR_SET, "COMMANDLINE", list_copy( L0, l2 ) ); t->flags |= parse->num; } return L0; }
LIST * builtin_rebuilds( PARSE *parse, FRAME *frame ) { LIST *targets = lol_get( frame->args, 0 ); LIST *rebuilds = lol_get( frame->args, 1 ); LIST *l; for( l = targets; l; l = list_next( l ) ) { TARGET *t = bindtarget( l->string ); t->rebuilds = targetlist( t->rebuilds, rebuilds ); } return L0; }
LIST * builtin_exit( PARSE *parse, FRAME *frame ) { list_print( lol_get( frame->args, 0 ) ); printf( "\n" ); if ( lol_get( frame->args, 1 ) ) { exit ( atoi( lol_get( frame->args, 1 )->string ) ); } else { exit( EXITBAD ); /* yeech */ } return L0; }
/* * builtin_w32_shortname() - W32_SHORTNAME rule, returns the short path * (no spaces) of the given path * * Usage: result = [ W32_SHORTNAME list ] ; */ static LIST* builtin_w32_shortname( PARSE *parse, LOL *args, int *jmp ) { LIST* arg = lol_get(args, 0); if (arg) return list_new(L0, w32_shortname(arg), 0); return L0; }
/* Use quite klugy approach: when we add order dependency from 'a' to 'b', just append 'b' to of value of variable 'a'. */ LIST *add_pair( PARSE *parse, FRAME *frame ) { LIST* arg = lol_get( frame->args, 0 ); var_set(arg->string, list_copy(0, arg->next), VAR_APPEND); return L0; }
LIST * builtin_glob( PARSE *parse, FRAME *frame ) { LIST *l = lol_get( frame->args, 0 ); LIST *r = lol_get( frame->args, 1 ); struct globbing globbing; globbing.results = L0; globbing.patterns = r; globbing.case_insensitive # if defined( OS_NT ) || defined( OS_CYGWIN ) = l; /* always case-insensitive if any files can be found */ # else = lol_get( frame->args, 2 );
LIST * builtin_echo( PARSE *parse, FRAME *frame ) { list_print( lol_get( frame->args, 0 ) ); printf( "\n" ); return L0; }
LIST *property_set_create( PARSE *parse, FRAME *frame ) { LIST* properties = lol_get( frame->args, 0 ); LIST* sorted = 0; LIST* order_sensitive = 0; LIST* unique; LIST* tmp; LIST* val; string var[1]; #if 0 /* Sort all properties which are not order sensitive */ for(tmp = properties; tmp; tmp = tmp->next) { LIST* g = get_grist(tmp->string); LIST* att = call_rule("feature.attributes", frame, g, 0); if (list_in(att, "order-sensitive")) { order_sensitive = list_new( order_sensitive, tmp->string); } else { sorted = list_new( sorted, tmp->string); } list_free(att); } sorted = list_sort(sorted); sorted = list_append(sorted, order_sensitive); unique = list_unique(sorted); #endif sorted = list_sort(properties); unique = list_unique(sorted); string_new(var); string_append(var, ".ps."); for(tmp = unique; tmp; tmp = tmp->next) { string_append(var, tmp->string); string_push_back(var, '-'); } val = var_get(var->value); if (val == 0) { val = call_rule("new", frame, list_append(list_new(0, "property-set"), unique), 0); var_set(newstr(var->value), list_copy(0, val), VAR_SET); } else { val = list_copy(0, val); } string_free(var); /* The 'unique' variable is freed in 'call_rule'. */ list_free(sorted); return val; }
/* Use quite klugy approach: when we add order dependency from 'a' to 'b', just * append 'b' to of value of variable 'a'. */ LIST * add_pair( FRAME * frame, int flags ) { LIST * arg = lol_get( frame->args, 0 ); LISTITER iter = list_begin( arg ); LISTITER const end = list_end( arg ); var_set( frame->module, list_item( iter ), list_copy_range( arg, list_next( iter ), end ), VAR_APPEND ); return L0; }