2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * compile.c - compile parsed jam statements
12 * compile_append() - append list results of two statements
13 * compile_break() - compile 'break/continue/return' rule
14 * compile_eval() - evaluate if to determine which leg to compile
15 * compile_foreach() - compile the "for x in y" statement
16 * compile_if() - compile 'if' rule
17 * compile_include() - support for 'include' - call include() on file
18 * compile_list() - expand and return a list
19 * compile_local() - declare (and set) local variables
20 * compile_null() - do nothing -- a stub for parsing
21 * compile_on() - run rule under influence of on-target variables
22 * compile_rule() - compile a single user defined rule
23 * compile_rules() - compile a chain of rules
24 * compile_set() - compile the "set variable" statement
25 * compile_setcomp() - support for `rule` - save parse tree
26 * compile_setexec() - support for `actions` - save execution string
27 * compile_settings() - compile the "on =" (set variable on exec) statement
28 * compile_switch() - compile 'switch' rule
32 * debug_compile() - printf with indent to show rule expansion.
33 * evaluate_rule() - execute a rule invocation
35 * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of
36 * the awkward sounding "settings".
37 * 04/12/94 (seiwald) - Combined build_depends() with build_includes().
38 * 04/12/94 (seiwald) - actionlist() now just appends a single action.
39 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
40 * 05/13/94 (seiwald) - include files are now bound as targets, and thus
41 * can make use of $(SEARCH)
42 * 06/01/94 (seiwald) - new 'actions existing' does existing sources
43 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
44 * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
45 * 01/22/95 (seiwald) - Exit rule.
46 * 02/02/95 (seiwald) - Always rule; LEAVES rule.
47 * 02/14/95 (seiwald) - NoUpdate rule.
48 * 01/20/00 (seiwald) - Upgraded from K&R to ANSI C
49 * 09/07/00 (seiwald) - stop crashing when a rule redefines itself
50 * 09/11/00 (seiwald) - new evaluate_rule() for headers().
51 * 09/11/00 (seiwald) - rules now return values, accessed via [ rule arg ... ]
52 * 09/12/00 (seiwald) - don't complain about rules invoked without targets
53 * 01/13/01 (seiwald) - fix case where rule is defined within another
54 * 01/10/01 (seiwald) - built-ins split out to builtin.c.
55 * 01/11/01 (seiwald) - optimize compile_rules() for tail recursion
56 * 01/21/01 (seiwald) - replace evaluate_if() with compile_eval()
57 * 01/24/01 (seiwald) - 'while' statement
58 * 03/23/01 (seiwald) - "[ on target rule ]" support
59 * 02/28/02 (seiwald) - merge EXEC_xxx flags in with RULE_xxx
60 * 03/02/02 (seiwald) - rules can be invoked via variable names
61 * 03/12/02 (seiwald) - &&,&,||,|,in now short-circuit again
62 * 03/25/02 (seiwald) - if ( "" a b ) one again returns true
63 * 06/21/02 (seiwald) - support for named parameters
64 * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
65 * 10/22/02 (seiwald) - working return/break/continue statements
66 * 11/04/02 (seiwald) - const-ing for string literals
67 * 11/18/02 (seiwald) - remove bogus search() in 'on' statement.
68 * 12/17/02 (seiwald) - new copysettings() to protect target-specific vars
83 static const char *set_names
[] = { "=", "+=", "?=" };
84 static void debug_compile (int which
, const char *s
);
85 int glob (const char *s
, const char *c
);
89 * compile_append() - append list results of two statements
91 * parse->left more compile_append() by left-recursion
92 * parse->right single rule
94 LIST
*compile_append (PARSE
*parse
, LOL
*args
, int *jmp
) {
95 /* Append right to left. */
97 (*parse
->left
->func
)(parse
->left
, args
, jmp
),
98 (*parse
->right
->func
)(parse
->right
, args
, jmp
));
103 * compile_break() - compile 'break/continue/return' rule
105 * parse->left results
106 * parse->num JMP_BREAK/CONTINUE/RETURN
108 LIST
*compile_break (PARSE
*parse
, LOL
*args
, int *jmp
) {
109 LIST
*lv
= (*parse
->left
->func
)(parse
->left
, args
, jmp
);
117 * compile_eval() - evaluate if to determine which leg to compile
120 * list if expression true - compile 'then' clause
121 * L0 if expression false - compile 'else' clause
123 static int lcmp(LIST
*t
, LIST
*s
) {
126 while (!status
&& (t
|| s
)) {
127 const char *st
= t
?t
->string
:"";
128 const char *ss
= s
?s
->string
:"";
130 status
= strcmp(st
, ss
);
131 t
= t
?list_next(t
):t
;
132 s
= s
?list_next(s
):s
;
139 LIST
*compile_eval (PARSE
*parse
, LOL
*args
, int *jmp
) {
140 LIST
*ll
, *lr
, *s
, *t
;
143 /* Short circuit lr eval for &&, ||, and 'in' */
144 ll
= (*parse
->left
->func
)(parse
->left
, args
, jmp
);
147 switch (parse
->num
) {
148 case EXPR_AND
: case EXPR_IN
:
156 lr
= (*parse
->right
->func
)(parse
->right
, args
, jmp
);
160 switch ( parse
->num
) {
165 if (ll
&& lr
) status
= 1;
168 if (ll
|| lr
) status
= 1;
171 /* "a in b": make sure each of */
172 /* ll is equal to something in lr. */
173 for (t
= ll
; t
; t
= list_next(t
)) {
174 for (s
= lr
; s
; s
= list_next(s
)) if (!strcmp(t
->string
, s
->string
)) break;
177 /* No more ll? Success */
181 if (lcmp(ll
, L0
) != 0) status
= 1;
184 if (lcmp(ll
, lr
) == 0) status
= 1;
187 if (lcmp(ll
, lr
) != 0) status
= 1;
190 if (lcmp(ll
, lr
) < 0) status
= 1;
193 if (lcmp(ll
, lr
) <= 0) status
= 1;
196 if (lcmp(ll
, lr
) > 0) status
= 1;
199 if (lcmp(ll
, lr
) >= 0) status
= 1;
204 debug_compile(0, "if");
206 printf("(%d) ", status
);
211 /* Find something to return. */
212 /* In odd circumstances (like "" = "") */
213 /* we'll have to return a new string. */
215 else if (ll
) t
= ll
, ll
= 0;
216 else if (lr
) t
= lr
, lr
= 0;
217 else t
= list_new(L0
, "1", 0);
219 if (ll
) list_free(ll
);
220 if (lr
) list_free(lr
);
227 * compile_foreach() - compile the "for x in y" statement
229 * Compile_foreach() resets the given variable name to each specified
230 * value, executing the commands enclosed in braces for each iteration.
232 * parse->string index variable
233 * parse->left variable values
234 * parse->right rule to compile
236 LIST
*compile_foreach (PARSE
*p
,
240 LIST
*nv
= (*p
->left
->func
)( p
->left
, args
, jmp
);
244 /* for each value for var */
246 for( l
= nv
; l
&& *jmp
== JMP_NONE
; l
= list_next( l
) )
248 /* Reset $(p->string) for each val. */
250 var_set( p
->string
, list_new( L0
, l
->string
, 1 ), VAR_SET
);
252 /* Keep only last result. */
255 result
= (*p
->right
->func
)( p
->right
, args
, jmp
);
259 if( *jmp
== JMP_CONTINUE
)
263 /* Here by break/continue? */
265 if( *jmp
== JMP_BREAK
|| *jmp
== JMP_CONTINUE
)
270 /* Returns result of last loop */
276 * compile_if() - compile 'if' rule
278 * parse->left condition tree
279 * parse->right then tree
280 * parse->third else tree
289 LIST
*l
= (*p
->left
->func
)( p
->left
, args
, jmp
);
291 p
= l
? p
->right
: p
->third
;
295 return (*p
->func
)( p
, args
, jmp
);
299 * compile_include() - support for 'include' - call include() on file
301 * parse->left list of files to include (can only do 1)
310 LIST
*nt
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
314 debug_compile( 0, "include" );
321 TARGET
*t
= bindtarget( nt
->string
);
323 /* Bind the include file under the influence of */
324 /* "on-target" variables. Though they are targets, */
325 /* include files are not built with make(). */
326 /* Needn't copysettings(), as search sets no vars. */
328 pushsettings( t
->settings
);
329 t
->boundname
= search( t
->name
, &t
->time
);
330 popsettings( t
->settings
);
332 /* Don't parse missing file if NOCARE set */
334 if( t
->time
|| !( t
->flags
& T_FLAG_NOCARE
) )
335 parse_file( t
->boundname
);
344 * compile_list() - expand and return a list
346 * parse->string - character string to expand
355 /* voodoo 1 means: s is a copyable string */
356 const char *s
= parse
->string
;
357 return var_expand( L0
, s
, s
+ strlen( s
), args
, 1 );
361 * compile_local() - declare (and set) local variables
363 * parse->left list of variables
364 * parse->right list of values
365 * parse->third rules to execute
376 LIST
*nt
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
377 LIST
*ns
= (*parse
->right
->func
)( parse
->right
, args
, jmp
);
382 debug_compile( 0, "local" );
389 /* Initial value is ns */
391 for( l
= nt
; l
; l
= list_next( l
) )
392 s
= addsettings( s
, 0, l
->string
, list_copy( (LIST
*)0, ns
) );
397 /* Note that callees of the current context get this "local" */
398 /* variable, making it not so much local as layered. */
401 result
= (*parse
->third
->func
)( parse
->third
, args
, jmp
);
409 * compile_null() - do nothing -- a stub for parsing
422 * compile_on() - run rule under influence of on-target variables
424 * parse->left target list; only first used
425 * parse->right rule to run
434 LIST
*nt
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
439 debug_compile( 0, "on" );
445 * Copy settings, so that 'on target var on target = val'
446 * doesn't set var globally.
451 TARGET
*t
= bindtarget( nt
->string
);
452 SETTINGS
*s
= copysettings( t
->settings
);
455 result
= (*parse
->right
->func
)( parse
->right
, args
, jmp
);
466 * compile_rule() - compile a single user defined rule
468 * parse->left list of rules to run
469 * parse->right parameters (list of lists) to rule, recursing left
471 * Wrapped around evaluate_rule() so that headers() can share it.
485 /* list of rules to run -- normally 1! */
487 ll
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
489 /* Build up the list of arg lists */
493 for( p
= parse
->right
; p
; p
= p
->left
)
494 lol_add( nargs
, (*p
->right
->func
)( p
->right
, args
, jmp
) );
496 /* Run rules, appending results from each */
498 for( l
= ll
; l
; l
= list_next( l
) )
499 result
= evaluate_rule( l
->string
, nargs
, result
);
508 * evaluate_rule() - execute a rule invocation
513 const char *rulename
,
517 RULE
*rule
= bindrule( rulename
);
521 debug_compile( 1, rulename
);
526 /* Check traditional targets $(<) and sources $(>) */
528 if( !rule
->actions
&& !rule
->procedure
)
529 printf( "warning: unknown rule %s\n", rule
->name
);
531 /* If this rule will be executed for updating the targets */
532 /* then construct the action for make(). */
539 /* The action is associated with this instance of this rule */
541 action
= (ACTION
*)malloc( sizeof( ACTION
) );
542 memset( (char *)action
, '\0', sizeof( *action
) );
545 action
->targets
= targetlist( (TARGETS
*)0, lol_get( args
, 0 ) );
546 action
->sources
= targetlist( (TARGETS
*)0, lol_get( args
, 1 ) );
548 /* Append this action to the actions of each target */
550 for( t
= action
->targets
; t
; t
= t
->next
)
551 t
->target
->actions
= actionlist( t
->target
->actions
, action
);
554 /* Now recursively compile any parse tree associated with this rule */
556 if( rule
->procedure
)
558 PARSE
*parse
= rule
->procedure
;
564 /* build parameters as local vars */
566 for( l
= rule
->params
, i
= 0; l
; l
= l
->next
, i
++ )
567 s
= addsettings( s
, 0, l
->string
,
568 list_copy( L0
, lol_get( args
, i
) ) );
571 /* Bring in local params. */
572 /* refer/free to ensure rule not freed during use. */
574 parse_refer( parse
);
577 result
= list_append( result
, (*parse
->func
)( parse
, args
, &jmp
) );
585 debug_compile( -1, 0 );
591 * compile_rules() - compile a chain of rules
593 * parse->left single rule
594 * parse->right more compile_rules() by right-recursion
603 /* Ignore result from first statement; return the 2nd. */
604 /* Optimize recursion on the right by looping. */
608 while( *jmp
== JMP_NONE
&& parse
->func
== compile_rules
)
611 result
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
612 parse
= parse
->right
;
615 if( *jmp
== JMP_NONE
)
618 result
= (*parse
->func
)( parse
, args
, jmp
);
625 * compile_set() - compile the "set variable" statement
627 * parse->left variable names
628 * parse->right variable values
629 * parse->num VAR_SET/APPEND/DEFAULT
638 LIST
*nt
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
639 LIST
*ns
= (*parse
->right
->func
)( parse
->right
, args
, jmp
);
644 debug_compile( 0, "set" );
646 printf( " %s ", set_names
[ parse
->num
] );
651 /* Call var_set to set variable */
652 /* var_set keeps ns, so need to copy it */
654 for( l
= nt
; l
; l
= list_next( l
) )
655 var_set( l
->string
, list_copy( L0
, ns
), parse
->num
);
663 * compile_setcomp() - support for `rule` - save parse tree
665 * parse->string rule name
666 * parse->left list of argument names
667 * parse->right rules for rule
676 RULE
*rule
= bindrule( parse
->string
);
680 /* Build param list */
682 for( p
= parse
->left
; p
; p
= p
->left
)
683 params
= list_new( params
, p
->string
, 1 );
687 debug_compile( 0, "rule" );
688 printf( "%s ", parse
->string
);
689 list_print( params
);
693 /* Free old one, if present */
695 if( rule
->procedure
)
696 parse_free( rule
->procedure
);
699 list_free( rule
->params
);
701 rule
->procedure
= parse
->right
;
702 rule
->params
= params
;
704 /* we now own this parse tree */
705 /* don't let parse_free() release it */
707 parse_refer( parse
->right
);
713 * compile_setexec() - support for `actions` - save execution string
715 * parse->string rule name
716 * parse->string1 OS command string
718 * parse->left `bind` variables
720 * Note that the parse flags (as defined in compile.h) are transfered
721 * directly to the rule flags (as defined in rules.h).
730 RULE
*rule
= bindrule( parse
->string
);
731 LIST
*bindlist
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
733 /* Free old one, if present */
737 freestr( rule
->actions
);
738 list_free( rule
->bindlist
);
741 rule
->actions
= copystr( parse
->string1
);
742 rule
->bindlist
= bindlist
;
743 rule
->flags
= parse
->num
;
749 * compile_settings() - compile the "on =" (set variable on exec) statement
751 * parse->left variable names
752 * parse->right target name
753 * parse->third variable value
754 * parse->num VAR_SET/APPEND/DEFAULT
763 LIST
*nt
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
764 LIST
*ns
= (*parse
->third
->func
)( parse
->third
, args
, jmp
);
765 LIST
*targets
= (*parse
->right
->func
)( parse
->right
, args
, jmp
);
770 debug_compile( 0, "set" );
773 list_print( targets
);
774 printf( " %s ", set_names
[ parse
->num
] );
779 /* Call addsettings to save variable setting */
780 /* addsettings keeps ns, so need to copy it */
781 /* Pass append flag to addsettings() */
783 for( ts
= targets
; ts
; ts
= list_next( ts
) )
785 TARGET
*t
= bindtarget( ts
->string
);
788 for( l
= nt
; l
; l
= list_next( l
) )
789 t
->settings
= addsettings( t
->settings
, parse
->num
,
790 l
->string
, list_copy( (LIST
*)0, ns
) );
794 list_free( targets
);
800 * compile_switch() - compile 'switch' rule
802 * parse->left switch value (only 1st used)
805 * cases->left 1st case
806 * cases->right next cases
808 * case->string argument to match
809 * case->left parse tree to execute
818 LIST
*nt
= (*parse
->left
->func
)( parse
->left
, args
, jmp
);
823 debug_compile( 0, "switch" );
828 /* Step through cases */
830 for( parse
= parse
->right
; parse
; parse
= parse
->right
)
832 if( !glob( parse
->left
->string
, nt
? nt
->string
: "" ) )
834 /* Get & exec parse tree for this case */
835 parse
= parse
->left
->left
;
836 result
= (*parse
->func
)( parse
, args
, jmp
);
847 * compile_while() - compile 'while' rule
849 * parse->left condition tree
850 * parse->right execution tree
862 /* Returns the value from the last execution of the block */
864 while( ( *jmp
== JMP_NONE
) &&
865 ( l
= (*p
->left
->func
)( p
->left
, args
, jmp
) ) )
867 /* Always toss while's expression */
871 /* Keep only last result. */
874 result
= (*p
->right
->func
)( p
->right
, args
, jmp
);
878 if( *jmp
== JMP_CONTINUE
)
882 /* Here by break/continue? */
884 if( *jmp
== JMP_BREAK
|| *jmp
== JMP_CONTINUE
)
887 /* Returns result of last loop */
893 * debug_compile() - printf with indent to show rule expansion.
897 debug_compile( int which
, const char *s
)
899 static int level
= 0;
900 static char indent
[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|";
901 int i
= ((1+level
) * 2) % 35;
904 printf( "%*.*s ", i
, i
, indent
);