1 /*
2  * Copyright 2011 Steven Watanabe
3  * Copyright 2016 Rene Rivera
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  */
8 
9 #include "jam.h"
10 #include "function.h"
11 
12 #include "class.h"
13 #include "compile.h"
14 #include "constants.h"
15 #include "debugger.h"
16 #include "filesys.h"
17 #include "frames.h"
18 #include "lists.h"
19 #include "mem.h"
20 #include "pathsys.h"
21 #include "rules.h"
22 #include "search.h"
23 #include "variable.h"
24 #include "output.h"
25 
26 #include <assert.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 /*
33 #define FUNCTION_DEBUG_PROFILE
34 */
35 
36 #ifndef FUNCTION_DEBUG_PROFILE
37 #undef PROFILE_ENTER_LOCAL
38 #define PROFILE_ENTER_LOCAL(x) while (false)
39 #undef PROFILE_EXIT_LOCAL
40 #define PROFILE_EXIT_LOCAL(x)
41 #endif
42 
43 int glob( char const * s, char const * c );
44 void backtrace( FRAME * );
45 void backtrace_line( FRAME * );
46 
47 #define INSTR_PUSH_EMPTY                   0
48 #define INSTR_PUSH_CONSTANT                1
49 #define INSTR_PUSH_ARG                     2
50 #define INSTR_PUSH_VAR                     3
51 #define INSTR_PUSH_VAR_FIXED               57
52 #define INSTR_PUSH_GROUP                   4
53 #define INSTR_PUSH_RESULT                  5
54 #define INSTR_PUSH_APPEND                  6
55 #define INSTR_SWAP                         7
56 
57 #define INSTR_JUMP_EMPTY                   8
58 #define INSTR_JUMP_NOT_EMPTY               9
59 
60 #define INSTR_JUMP                         10
61 #define INSTR_JUMP_LT                      11
62 #define INSTR_JUMP_LE                      12
63 #define INSTR_JUMP_GT                      13
64 #define INSTR_JUMP_GE                      14
65 #define INSTR_JUMP_EQ                      15
66 #define INSTR_JUMP_NE                      16
67 #define INSTR_JUMP_IN                      17
68 #define INSTR_JUMP_NOT_IN                  18
69 
70 #define INSTR_JUMP_NOT_GLOB                19
71 
72 #define INSTR_FOR_INIT                     56
73 #define INSTR_FOR_LOOP                     20
74 
75 #define INSTR_SET_RESULT                   21
76 #define INSTR_RETURN                       22
77 #define INSTR_POP                          23
78 
79 #define INSTR_PUSH_LOCAL                   24
80 #define INSTR_POP_LOCAL                    25
81 #define INSTR_SET                          26
82 #define INSTR_APPEND                       27
83 #define INSTR_DEFAULT                      28
84 
85 #define INSTR_PUSH_LOCAL_FIXED             58
86 #define INSTR_POP_LOCAL_FIXED              59
87 #define INSTR_SET_FIXED                    60
88 #define INSTR_APPEND_FIXED                 61
89 #define INSTR_DEFAULT_FIXED                62
90 
91 #define INSTR_PUSH_LOCAL_GROUP             29
92 #define INSTR_POP_LOCAL_GROUP              30
93 #define INSTR_SET_GROUP                    31
94 #define INSTR_APPEND_GROUP                 32
95 #define INSTR_DEFAULT_GROUP                33
96 
97 #define INSTR_PUSH_ON                      34
98 #define INSTR_POP_ON                       35
99 #define INSTR_SET_ON                       36
100 #define INSTR_APPEND_ON                    37
101 #define INSTR_DEFAULT_ON                   38
102 #define INSTR_GET_ON                       65
103 
104 #define INSTR_CALL_RULE                    39
105 #define INSTR_CALL_MEMBER_RULE             66
106 
107 #define INSTR_APPLY_MODIFIERS              40
108 #define INSTR_APPLY_INDEX                  41
109 #define INSTR_APPLY_INDEX_MODIFIERS        42
110 #define INSTR_APPLY_MODIFIERS_GROUP        43
111 #define INSTR_APPLY_INDEX_GROUP            44
112 #define INSTR_APPLY_INDEX_MODIFIERS_GROUP  45
113 #define INSTR_COMBINE_STRINGS              46
114 #define INSTR_GET_GRIST                    64
115 
116 #define INSTR_INCLUDE                      47
117 #define INSTR_RULE                         48
118 #define INSTR_ACTIONS                      49
119 #define INSTR_PUSH_MODULE                  50
120 #define INSTR_POP_MODULE                   51
121 #define INSTR_CLASS                        52
122 #define INSTR_BIND_MODULE_VARIABLES        63
123 
124 #define INSTR_APPEND_STRINGS               53
125 #define INSTR_WRITE_FILE                   54
126 #define INSTR_OUTPUT_STRINGS               55
127 
128 #define INSTR_DEBUG_LINE                   67
129 #define INSTR_FOR_POP                      70
130 
131 typedef struct instruction
132 {
133     unsigned int op_code;
134     int arg;
135 } instruction;
136 
137 typedef struct _subfunction
138 {
139     OBJECT * name;
140     FUNCTION * code;
141     int local;
142 } SUBFUNCTION;
143 
144 typedef struct _subaction
145 {
146     OBJECT * name;
147     FUNCTION * command;
148     int flags;
149 } SUBACTION;
150 
151 #define FUNCTION_BUILTIN    0
152 #define FUNCTION_JAM        1
153 
154 struct argument
155 {
156     int flags;
157 #define ARG_ONE 0
158 #define ARG_OPTIONAL 1
159 #define ARG_PLUS 2
160 #define ARG_STAR 3
161 #define ARG_VARIADIC 4
162     OBJECT * type_name;
163     OBJECT * arg_name;
164     int index;
165 };
166 
167 struct arg_list
168 {
169     int size;
170     struct argument * args;
171 };
172 
173 struct _function
174 {
175     int type;
176     int reference_count;
177     OBJECT * rulename;
178     struct arg_list * formal_arguments;
179     int num_formal_arguments;
180 };
181 
182 typedef struct _builtin_function
183 {
184     FUNCTION base;
185     LIST * ( * func )( FRAME *, int flags );
186     int flags;
187 } BUILTIN_FUNCTION;
188 
189 typedef struct _jam_function
190 {
191     FUNCTION base;
192     int code_size;
193     instruction * code;
194     int num_constants;
195     OBJECT * * constants;
196     int num_subfunctions;
197     SUBFUNCTION * functions;
198     int num_subactions;
199     SUBACTION * actions;
200     FUNCTION * generic;
201     OBJECT * file;
202     int line;
203 } JAM_FUNCTION;
204 
205 
206 #ifdef HAVE_PYTHON
207 
208 #define FUNCTION_PYTHON     2
209 
210 typedef struct _python_function
211 {
212     FUNCTION base;
213     PyObject * python_function;
214 } PYTHON_FUNCTION;
215 
216 static LIST * call_python_function( PYTHON_FUNCTION *, FRAME * );
217 
218 #endif
219 
220 
221 struct _stack
222 {
223     void * data;
224 };
225 
226 static void * stack;
227 
stack_global()228 STACK * stack_global()
229 {
230     static STACK result;
231     if ( !stack )
232     {
233         int const size = 1 << 21;
234         stack = BJAM_MALLOC( size );
235         result.data = (char *)stack + size;
236     }
237     return &result;
238 }
239 
240 struct list_alignment_helper
241 {
242     char ch;
243     LIST * l;
244 };
245 
246 #define LISTPTR_ALIGN_BASE ( sizeof( struct list_alignment_helper ) - sizeof( LIST * ) )
247 #define LISTPTR_ALIGN ( ( LISTPTR_ALIGN_BASE > sizeof( LIST * ) ) ? sizeof( LIST * ) : LISTPTR_ALIGN_BASE )
248 
check_alignment(STACK * s)249 static void check_alignment( STACK * s )
250 {
251     assert( (size_t)s->data % LISTPTR_ALIGN == 0 );
252 }
253 
stack_allocate(STACK * s,int size)254 void * stack_allocate( STACK * s, int size )
255 {
256     check_alignment( s );
257     s->data = (char *)s->data - size;
258     check_alignment( s );
259     return s->data;
260 }
261 
stack_deallocate(STACK * s,int size)262 void stack_deallocate( STACK * s, int size )
263 {
264     check_alignment( s );
265     s->data = (char *)s->data + size;
266     check_alignment( s );
267 }
268 
stack_push(STACK * s,LIST * l)269 void stack_push( STACK * s, LIST * l )
270 {
271     *(LIST * *)stack_allocate( s, sizeof( LIST * ) ) = l;
272 }
273 
stack_pop(STACK * s)274 LIST * stack_pop( STACK * s )
275 {
276     LIST * const result = *(LIST * *)s->data;
277     stack_deallocate( s, sizeof( LIST * ) );
278     return result;
279 }
280 
stack_top(STACK * s)281 LIST * stack_top( STACK * s )
282 {
283     check_alignment( s );
284     return *(LIST * *)s->data;
285 }
286 
stack_at(STACK * s,int n)287 LIST * stack_at( STACK * s, int n )
288 {
289     check_alignment( s );
290     return *( (LIST * *)s->data + n );
291 }
292 
stack_set(STACK * s,int n,LIST * value)293 void stack_set( STACK * s, int n, LIST * value )
294 {
295     check_alignment( s );
296     *((LIST * *)s->data + n) = value;
297 }
298 
stack_get(STACK * s)299 void * stack_get( STACK * s )
300 {
301     check_alignment( s );
302     return s->data;
303 }
304 
frame_get_local(FRAME * frame,int idx)305 LIST * frame_get_local( FRAME * frame, int idx )
306 {
307     /* The only local variables are the arguments. */
308     return list_copy( lol_get( frame->args, idx ) );
309 }
310 
function_get_constant(JAM_FUNCTION * function,int idx)311 static OBJECT * function_get_constant( JAM_FUNCTION * function, int idx )
312 {
313     return function->constants[ idx ];
314 }
315 
function_get_variable(JAM_FUNCTION * function,FRAME * frame,int idx)316 static LIST * function_get_variable( JAM_FUNCTION * function, FRAME * frame,
317     int idx )
318 {
319     return list_copy( var_get( frame->module, function->constants[ idx ] ) );
320 }
321 
function_set_variable(JAM_FUNCTION * function,FRAME * frame,int idx,LIST * value)322 static void function_set_variable( JAM_FUNCTION * function, FRAME * frame,
323     int idx, LIST * value )
324 {
325     var_set( frame->module, function->constants[ idx ], value, VAR_SET );
326 }
327 
function_swap_variable(JAM_FUNCTION * function,FRAME * frame,int idx,LIST * value)328 static LIST * function_swap_variable( JAM_FUNCTION * function, FRAME * frame,
329     int idx, LIST * value )
330 {
331     return var_swap( frame->module, function->constants[ idx ], value );
332 }
333 
function_append_variable(JAM_FUNCTION * function,FRAME * frame,int idx,LIST * value)334 static void function_append_variable( JAM_FUNCTION * function, FRAME * frame,
335     int idx, LIST * value )
336 {
337     var_set( frame->module, function->constants[ idx ], value, VAR_APPEND );
338 }
339 
function_default_variable(JAM_FUNCTION * function,FRAME * frame,int idx,LIST * value)340 static void function_default_variable( JAM_FUNCTION * function, FRAME * frame,
341     int idx, LIST * value )
342 {
343     var_set( frame->module, function->constants[ idx ], value, VAR_DEFAULT );
344 }
345 
function_set_rule(JAM_FUNCTION * function,FRAME * frame,STACK * s,int idx)346 static void function_set_rule( JAM_FUNCTION * function, FRAME * frame,
347     STACK * s, int idx )
348 {
349     SUBFUNCTION * sub = function->functions + idx;
350     new_rule_body( frame->module, sub->name, sub->code, !sub->local );
351 }
352 
function_set_actions(JAM_FUNCTION * function,FRAME * frame,STACK * s,int idx)353 static void function_set_actions( JAM_FUNCTION * function, FRAME * frame,
354     STACK * s, int idx )
355 {
356     SUBACTION * sub = function->actions + idx;
357     LIST * bindlist = stack_pop( s );
358     new_rule_actions( frame->module, sub->name, sub->command, bindlist,
359         sub->flags );
360 }
361 
362 
363 /*
364  * Returns the index if name is "<", ">", "1", "2", ... or "19" otherwise
365  * returns -1.
366  */
367 
get_argument_index(char const * s)368 static int get_argument_index( char const * s )
369 {
370     if ( s[ 0 ] != '\0')
371     {
372         if ( s[ 1 ] == '\0' )
373         {
374             switch ( s[ 0 ] )
375             {
376                 case '<': return 0;
377                 case '>': return 1;
378 
379                 case '1':
380                 case '2':
381                 case '3':
382                 case '4':
383                 case '5':
384                 case '6':
385                 case '7':
386                 case '8':
387                 case '9':
388                     return s[ 0 ] - '1';
389             }
390         }
391         else if ( s[ 0 ] == '1' && s[ 2 ] == '\0' )
392         {
393             switch( s[ 1 ] )
394             {
395             case '0':
396             case '1':
397             case '2':
398             case '3':
399             case '4':
400             case '5':
401             case '6':
402             case '7':
403             case '8':
404             case '9':
405                 return s[ 1 ] - '0' + 10 - 1;
406             }
407         }
408     }
409     return -1;
410 }
411 
function_get_named_variable(JAM_FUNCTION * function,FRAME * frame,OBJECT * name)412 static LIST * function_get_named_variable( JAM_FUNCTION * function,
413     FRAME * frame, OBJECT * name )
414 {
415     int const idx = get_argument_index( object_str( name ) );
416     return idx == -1
417         ? list_copy( var_get( frame->module, name ) )
418         : list_copy( lol_get( frame->args, idx ) );
419 }
420 
function_set_named_variable(JAM_FUNCTION * function,FRAME * frame,OBJECT * name,LIST * value)421 static void function_set_named_variable( JAM_FUNCTION * function, FRAME * frame,
422     OBJECT * name, LIST * value)
423 {
424     var_set( frame->module, name, value, VAR_SET );
425 }
426 
function_swap_named_variable(JAM_FUNCTION * function,FRAME * frame,OBJECT * name,LIST * value)427 static LIST * function_swap_named_variable( JAM_FUNCTION * function,
428     FRAME * frame, OBJECT * name, LIST * value )
429 {
430     return var_swap( frame->module, name, value );
431 }
432 
function_append_named_variable(JAM_FUNCTION * function,FRAME * frame,OBJECT * name,LIST * value)433 static void function_append_named_variable( JAM_FUNCTION * function,
434     FRAME * frame, OBJECT * name, LIST * value)
435 {
436     var_set( frame->module, name, value, VAR_APPEND );
437 }
438 
function_default_named_variable(JAM_FUNCTION * function,FRAME * frame,OBJECT * name,LIST * value)439 static void function_default_named_variable( JAM_FUNCTION * function,
440     FRAME * frame, OBJECT * name, LIST * value )
441 {
442     var_set( frame->module, name, value, VAR_DEFAULT );
443 }
444 
function_call_rule(JAM_FUNCTION * function,FRAME * frame,STACK * s,int n_args,char const * unexpanded,OBJECT * file,int line)445 static LIST * function_call_rule( JAM_FUNCTION * function, FRAME * frame,
446     STACK * s, int n_args, char const * unexpanded, OBJECT * file, int line )
447 {
448     FRAME inner[ 1 ];
449     int i;
450     LIST * first = stack_pop( s );
451     LIST * result = L0;
452     OBJECT * rulename;
453     LIST * trailing;
454 
455     frame->file = file;
456     frame->line = line;
457 
458     if ( list_empty( first ) )
459     {
460         backtrace_line( frame );
461         out_printf( "warning: rulename %s expands to empty string\n", unexpanded );
462         backtrace( frame );
463         list_free( first );
464         for ( i = 0; i < n_args; ++i )
465             list_free( stack_pop( s ) );
466         return result;
467     }
468 
469     rulename = object_copy( list_front( first ) );
470 
471     frame_init( inner );
472     inner->prev = frame;
473     inner->prev_user = frame->module->user_module ? frame : frame->prev_user;
474     inner->module = frame->module;  /* This gets fixed up in evaluate_rule(). */
475 
476     for ( i = 0; i < n_args; ++i )
477         lol_add( inner->args, stack_at( s, n_args - i - 1 ) );
478 
479     for ( i = 0; i < n_args; ++i )
480         stack_pop( s );
481 
482     trailing = list_pop_front( first );
483     if ( trailing )
484     {
485         if ( inner->args->count == 0 )
486             lol_add( inner->args, trailing );
487         else
488         {
489             LIST * * const l = &inner->args->list[ 0 ];
490             *l = list_append( trailing, *l );
491         }
492     }
493 
494     result = evaluate_rule( bindrule( rulename, inner->module ), rulename, inner );
495     frame_free( inner );
496     object_free( rulename );
497     return result;
498 }
499 
function_call_member_rule(JAM_FUNCTION * function,FRAME * frame,STACK * s,int n_args,OBJECT * rulename,OBJECT * file,int line)500 static LIST * function_call_member_rule( JAM_FUNCTION * function, FRAME * frame, STACK * s, int n_args, OBJECT * rulename, OBJECT * file, int line )
501 {
502     FRAME   inner[ 1 ];
503     int i;
504     LIST * first = stack_pop( s );
505     LIST * result = L0;
506     RULE * rule;
507     module_t * module;
508     OBJECT * real_rulename = 0;
509 
510     frame->file = file;
511     frame->line = line;
512 
513     if ( list_empty( first ) )
514     {
515         backtrace_line( frame );
516         out_printf( "warning: object is empty\n" );
517         backtrace( frame );
518 
519         list_free( first );
520 
521         for( i = 0; i < n_args; ++i )
522         {
523             list_free( stack_pop( s ) );
524         }
525 
526         return result;
527     }
528 
529     /* FIXME: handle generic case */
530     assert( list_length( first ) == 1 );
531 
532     module = bindmodule( list_front( first ) );
533     if ( module->class_module )
534     {
535         rule = bindrule( rulename, module );
536         if ( rule->procedure )
537         {
538             real_rulename = object_copy( function_rulename( rule->procedure ) );
539         }
540         else
541         {
542             string buf[ 1 ];
543             string_new( buf );
544             string_append( buf, object_str( module->name ) );
545             string_push_back( buf, '.' );
546             string_append( buf, object_str( rulename ) );
547             real_rulename = object_new( buf->value );
548             string_free( buf );
549         }
550     }
551     else
552     {
553         string buf[ 1 ];
554         string_new( buf );
555         string_append( buf, object_str( list_front( first ) ) );
556         string_push_back( buf, '.' );
557         string_append( buf, object_str( rulename ) );
558         real_rulename = object_new( buf->value );
559         string_free( buf );
560         rule = bindrule( real_rulename, frame->module );
561     }
562 
563     frame_init( inner );
564 
565     inner->prev = frame;
566     inner->prev_user = frame->module->user_module ? frame : frame->prev_user;
567     inner->module = frame->module;  /* This gets fixed up in evaluate_rule(), below. */
568 
569     for( i = 0; i < n_args; ++i )
570     {
571         lol_add( inner->args, stack_at( s, n_args - i - 1 ) );
572     }
573 
574     for( i = 0; i < n_args; ++i )
575     {
576         stack_pop( s );
577     }
578 
579     if ( list_length( first ) > 1 )
580     {
581         string buf[ 1 ];
582         LIST * trailing = L0;
583         LISTITER iter = list_begin( first ), end = list_end( first );
584         iter = list_next( iter );
585         string_new( buf );
586         for ( ; iter != end; iter = list_next( iter ) )
587         {
588             string_append( buf, object_str( list_item( iter ) ) );
589             string_push_back( buf, '.' );
590             string_append( buf, object_str( rulename ) );
591             trailing = list_push_back( trailing, object_new( buf->value ) );
592             string_truncate( buf, 0 );
593         }
594         string_free( buf );
595         if ( inner->args->count == 0 )
596             lol_add( inner->args, trailing );
597         else
598         {
599             LIST * * const l = &inner->args->list[ 0 ];
600             *l = list_append( trailing, *l );
601         }
602     }
603 
604     list_free( first );
605     result = evaluate_rule( rule, real_rulename, inner );
606     frame_free( inner );
607     object_free( real_rulename );
608     return result;
609 }
610 
611 
612 /* Variable expansion */
613 
614 typedef struct
615 {
616     int sub1;
617     int sub2;
618 } subscript_t;
619 
620 typedef struct
621 {
622     PATHNAME f;           /* :GDBSMR -- pieces */
623     char     parent;      /* :P -- go to parent directory */
624     char     filemods;    /* one of the above applied */
625     char     downshift;   /* :L -- downshift result */
626     char     upshift;     /* :U -- upshift result */
627     char     to_slashes;  /* :T -- convert "\" to "/" */
628     char     to_windows;  /* :W -- convert cygwin to native paths */
629     PATHPART empty;       /* :E -- default for empties */
630     PATHPART join;        /* :J -- join list with char */
631 } VAR_EDITS;
632 
633 static LIST * apply_modifiers_impl( LIST * result, string * buf,
634     VAR_EDITS * edits, int n, LISTITER iter, LISTITER end );
635 static void get_iters( subscript_t const subscript, LISTITER * const first,
636     LISTITER * const last, int const length );
637 
638 
639 /*
640  * var_edit_parse() - parse : modifiers into PATHNAME structure
641  *
642  * The : modifiers in a $(varname:modifier) currently support replacing or
643  * omitting elements of a filename, and so they are parsed into a PATHNAME
644  * structure (which contains pointers into the original string).
645  *
646  * Modifiers of the form "X=value" replace the component X with the given value.
647  * Modifiers without the "=value" cause everything but the component X to be
648  * omitted. X is one of:
649  *
650  *  G <grist>
651  *  D directory name
652  *  B base name
653  *  S .suffix
654  *  M (member)
655  *  R root directory - prepended to whole path
656  *
657  * This routine sets:
658  *
659  *  f->f_xxx.ptr = 0
660  *  f->f_xxx.len = 0
661  *      -> leave the original component xxx
662  *
663  *  f->f_xxx.ptr = string
664  *  f->f_xxx.len = strlen( string )
665  *      -> replace component xxx with string
666  *
667  *  f->f_xxx.ptr = ""
668  *  f->f_xxx.len = 0
669  *      -> omit component xxx
670  *
671  * var_edit_file() below and path_build() obligingly follow this convention.
672  */
673 
var_edit_parse(char const * mods,VAR_EDITS * edits,int havezeroed)674 static int var_edit_parse( char const * mods, VAR_EDITS * edits, int havezeroed
675     )
676 {
677     while ( *mods )
678     {
679         PATHPART * fp;
680 
681         switch ( *mods++ )
682         {
683             case 'L': edits->downshift = 1; continue;
684             case 'U': edits->upshift = 1; continue;
685             case 'P': edits->parent = edits->filemods = 1; continue;
686             case 'E': fp = &edits->empty; goto strval;
687             case 'J': fp = &edits->join; goto strval;
688             case 'G': fp = &edits->f.f_grist; goto fileval;
689             case 'R': fp = &edits->f.f_root; goto fileval;
690             case 'D': fp = &edits->f.f_dir; goto fileval;
691             case 'B': fp = &edits->f.f_base; goto fileval;
692             case 'S': fp = &edits->f.f_suffix; goto fileval;
693             case 'M': fp = &edits->f.f_member; goto fileval;
694             case 'T': edits->to_slashes = 1; continue;
695             case 'W': edits->to_windows = 1; continue;
696             default:
697                 continue;  /* Should complain, but so what... */
698         }
699 
700     fileval:
701         /* Handle :CHARS, where each char (without a following =) selects a
702          * particular file path element. On the first such char, we deselect all
703          * others (by setting ptr = "", len = 0) and for each char we select
704          * that element (by setting ptr = 0).
705          */
706         edits->filemods = 1;
707 
708         if ( *mods != '=' )
709         {
710             if ( !havezeroed++ )
711             {
712                 int i;
713                 for ( i = 0; i < 6; ++i )
714                 {
715                     edits->f.part[ i ].len = 0;
716                     edits->f.part[ i ].ptr = "";
717                 }
718             }
719 
720             fp->ptr = 0;
721             continue;
722         }
723 
724     strval:
725         /* Handle :X=value, or :X */
726         if ( *mods != '=' )
727         {
728             fp->ptr = "";
729             fp->len = 0;
730         }
731         else
732         {
733             fp->ptr = ++mods;
734             fp->len = strlen( mods );
735             mods += fp->len;
736         }
737     }
738 
739     return havezeroed;
740 }
741 
742 
743 /*
744  * var_edit_file() - copy input target name to output, modifying filename.
745  */
746 
var_edit_file(char const * in,string * out,VAR_EDITS * edits)747 static void var_edit_file( char const * in, string * out, VAR_EDITS * edits )
748 {
749     if ( edits->filemods )
750     {
751         PATHNAME pathname;
752 
753         /* Parse apart original filename, putting parts into "pathname". */
754         path_parse( in, &pathname );
755 
756         /* Replace any pathname with edits->f */
757         if ( edits->f.f_grist .ptr ) pathname.f_grist  = edits->f.f_grist;
758         if ( edits->f.f_root  .ptr ) pathname.f_root   = edits->f.f_root;
759         if ( edits->f.f_dir   .ptr ) pathname.f_dir    = edits->f.f_dir;
760         if ( edits->f.f_base  .ptr ) pathname.f_base   = edits->f.f_base;
761         if ( edits->f.f_suffix.ptr ) pathname.f_suffix = edits->f.f_suffix;
762         if ( edits->f.f_member.ptr ) pathname.f_member = edits->f.f_member;
763 
764         /* If requested, modify pathname to point to parent. */
765         if ( edits->parent )
766             path_parent( &pathname );
767 
768         /* Put filename back together. */
769         path_build( &pathname, out );
770     }
771     else
772         string_append( out, in );
773 }
774 
775 
776 #if defined( OS_CYGWIN ) || defined( OS_VMS )
777 
778 /*
779  * var_edit_translate_path() - translate path to os native format.
780  */
781 
var_edit_translate_path(string * out,size_t pos,VAR_EDITS * edits)782 static void var_edit_translate_path( string * out, size_t pos, VAR_EDITS * edits )
783 {
784     if ( edits->to_windows )
785     {
786         string result[ 1 ];
787         int translated;
788 
789         /* Translate path to os native format. */
790         translated = path_translate_to_os( out->value + pos, result );
791         if ( translated )
792         {
793             string_truncate( out, pos );
794             string_append( out, result->value );
795             edits->to_slashes = 0;
796         }
797 
798         string_free( result );
799     }
800 }
801 
802 #endif
803 
804 
805 /*
806  * var_edit_shift() - do upshift/downshift & other mods.
807  */
808 
var_edit_shift(string * out,size_t pos,VAR_EDITS * edits)809 static void var_edit_shift( string * out, size_t pos, VAR_EDITS * edits )
810 {
811 #if defined( OS_CYGWIN ) || defined( OS_VMS )
812     var_edit_translate_path( out, pos, edits );
813 #endif
814 
815     if ( edits->upshift || edits->downshift || edits->to_slashes )
816     {
817         /* Handle upshifting, downshifting and slash translation now. */
818         char * p;
819         for ( p = out->value + pos; *p; ++p )
820         {
821             if ( edits->upshift )
822                 *p = toupper( *p );
823             else if ( edits->downshift )
824                 *p = tolower( *p );
825             if ( edits->to_slashes && ( *p == '\\' ) )
826                 *p = '/';
827         }
828     }
829 }
830 
831 
832 /*
833  * Reads n LISTs from the top of the STACK and combines them to form VAR_EDITS.
834  * Returns the number of VAR_EDITS pushed onto the STACK.
835  */
836 
expand_modifiers(STACK * s,int n)837 static int expand_modifiers( STACK * s, int n )
838 {
839     int i;
840     int total = 1;
841     LIST * * args = (LIST**)stack_get( s );
842     for ( i = 0; i < n; ++i )
843         total *= list_length( args[ i ] );
844 
845     if ( total != 0 )
846     {
847         VAR_EDITS * out = (VAR_EDITS*)stack_allocate( s, total * sizeof( VAR_EDITS ) );
848         LISTITER * iter = (LISTITER*)stack_allocate( s, n * sizeof( LIST * ) );
849         for ( i = 0; i < n; ++i )
850             iter[ i ] = list_begin( args[ i ] );
851         i = 0;
852         {
853             int havezeroed;
854         loop:
855             memset( out, 0, sizeof( *out ) );
856             havezeroed = 0;
857             for ( i = 0; i < n; ++i )
858                 havezeroed = var_edit_parse( object_str( list_item( iter[ i ] )
859                     ), out, havezeroed );
860             ++out;
861             while ( --i >= 0 )
862             {
863                 if ( list_next( iter[ i ] ) != list_end( args[ i ] ) )
864                 {
865                     iter[ i ] = list_next( iter[ i ] );
866                     goto loop;
867                 }
868                 iter[ i ] = list_begin( args[ i ] );
869             }
870         }
871         stack_deallocate( s, n * sizeof( LIST * ) );
872     }
873     return total;
874 }
875 
apply_modifiers(STACK * s,int n)876 static LIST * apply_modifiers( STACK * s, int n )
877 {
878     LIST * value = stack_top( s );
879     LIST * result = L0;
880     VAR_EDITS * const edits = (VAR_EDITS *)( (LIST * *)stack_get( s ) + 1 );
881     string buf[ 1 ];
882     string_new( buf );
883     result = apply_modifiers_impl( result, buf, edits, n, list_begin( value ),
884         list_end( value ) );
885     string_free( buf );
886     return result;
887 }
888 
889 
890 /*
891  * Parse a string of the form "1-2", "-2--1", "2-" and return the two
892  * subscripts.
893  */
894 
parse_subscript(char const * s)895 subscript_t parse_subscript( char const * s )
896 {
897     subscript_t result;
898     result.sub1 = 0;
899     result.sub2 = 0;
900     do  /* so we can use "break" */
901     {
902         /* Allow negative subscripts. */
903         if ( !isdigit( *s ) && ( *s != '-' ) )
904         {
905             result.sub2 = 0;
906             break;
907         }
908         result.sub1 = atoi( s );
909 
910         /* Skip over the first symbol, which is either a digit or dash. */
911         ++s;
912         while ( isdigit( *s ) ) ++s;
913 
914         if ( *s == '\0' )
915         {
916             result.sub2 = result.sub1;
917             break;
918         }
919 
920         if ( *s != '-' )
921         {
922             result.sub2 = 0;
923             break;
924         }
925 
926         ++s;
927 
928         if ( *s == '\0' )
929         {
930             result.sub2 = -1;
931             break;
932         }
933 
934         if ( !isdigit( *s ) && ( *s != '-' ) )
935         {
936             result.sub2 = 0;
937             break;
938         }
939 
940         /* First, compute the index of the last element. */
941         result.sub2 = atoi( s );
942         while ( isdigit( *++s ) );
943 
944         if ( *s != '\0' )
945             result.sub2 = 0;
946 
947     } while ( 0 );
948     return result;
949 }
950 
apply_subscript(STACK * s)951 static LIST * apply_subscript( STACK * s )
952 {
953     LIST * value = stack_top( s );
954     LIST * indices = stack_at( s, 1 );
955     LIST * result = L0;
956     int length = list_length( value );
957     string buf[ 1 ];
958     LISTITER indices_iter = list_begin( indices );
959     LISTITER const indices_end = list_end( indices );
960     string_new( buf );
961     for ( ; indices_iter != indices_end; indices_iter = list_next( indices_iter
962         ) )
963     {
964         LISTITER iter = list_begin( value );
965         LISTITER end = list_end( value );
966         subscript_t const subscript = parse_subscript( object_str( list_item(
967             indices_iter ) ) );
968         get_iters( subscript, &iter, &end, length );
969         for ( ; iter != end; iter = list_next( iter ) )
970             result = list_push_back( result, object_copy( list_item( iter ) ) );
971     }
972     string_free( buf );
973     return result;
974 }
975 
976 
977 /*
978  * Reads the LIST from first and applies subscript to it. The results are
979  * written to *first and *last.
980  */
981 
get_iters(subscript_t const subscript,LISTITER * const first,LISTITER * const last,int const length)982 static void get_iters( subscript_t const subscript, LISTITER * const first,
983     LISTITER * const last, int const length )
984 {
985     int start;
986     int size;
987     LISTITER iter;
988     LISTITER end;
989     {
990 
991         if ( subscript.sub1 < 0 )
992             start = length + subscript.sub1;
993         else if ( subscript.sub1 > length )
994             start = length;
995         else
996             start = subscript.sub1 - 1;
997 
998         size = subscript.sub2 < 0
999             ? length + 1 + subscript.sub2 - start
1000             : subscript.sub2 - start;
1001 
1002         /*
1003          * HACK: When the first subscript is before the start of the list, it
1004          * magically becomes the beginning of the list. This is inconsistent,
1005          * but needed for backwards compatibility.
1006          */
1007         if ( start < 0 )
1008             start = 0;
1009 
1010         /* The "sub2 < 0" test handles the semantic error of sub2 < sub1. */
1011         if ( size < 0 )
1012             size = 0;
1013 
1014         if ( start + size > length )
1015             size = length - start;
1016     }
1017 
1018     iter = *first;
1019     while ( start-- > 0 )
1020         iter = list_next( iter );
1021 
1022     end = iter;
1023     while ( size-- > 0 )
1024         end = list_next( end );
1025 
1026     *first = iter;
1027     *last = end;
1028 }
1029 
apply_modifiers_empty(LIST * result,string * buf,VAR_EDITS * edits,int n)1030 static LIST * apply_modifiers_empty( LIST * result, string * buf,
1031     VAR_EDITS * edits, int n )
1032 {
1033     int i;
1034     for ( i = 0; i < n; ++i )
1035     {
1036         if ( edits[ i ].empty.ptr )
1037         {
1038             /** FIXME: is empty.ptr always null-terminated? */
1039             var_edit_file( edits[ i ].empty.ptr, buf, edits + i );
1040             var_edit_shift( buf, 0, edits + i );
1041             result = list_push_back( result, object_new( buf->value ) );
1042             string_truncate( buf, 0 );
1043         }
1044     }
1045     return result;
1046 }
1047 
apply_modifiers_non_empty(LIST * result,string * buf,VAR_EDITS * edits,int n,LISTITER begin,LISTITER end)1048 static LIST * apply_modifiers_non_empty( LIST * result, string * buf,
1049     VAR_EDITS * edits, int n, LISTITER begin, LISTITER end )
1050 {
1051     int i;
1052     LISTITER iter;
1053     for ( i = 0; i < n; ++i )
1054     {
1055         if ( edits[ i ].join.ptr )
1056         {
1057             var_edit_file( object_str( list_item( begin ) ), buf, edits + i );
1058             var_edit_shift( buf, 0, edits + i );
1059             for ( iter = list_next( begin ); iter != end; iter = list_next( iter
1060                 ) )
1061             {
1062                 size_t size;
1063                 string_append( buf, edits[ i ].join.ptr );
1064                 size = buf->size;
1065                 var_edit_file( object_str( list_item( iter ) ), buf, edits + i
1066                     );
1067                 var_edit_shift( buf, size, edits + i );
1068             }
1069             result = list_push_back( result, object_new( buf->value ) );
1070             string_truncate( buf, 0 );
1071         }
1072         else
1073         {
1074             for ( iter = begin; iter != end; iter = list_next( iter ) )
1075             {
1076                 var_edit_file( object_str( list_item( iter ) ), buf, edits + i );
1077                 var_edit_shift( buf, 0, edits + i );
1078                 result = list_push_back( result, object_new( buf->value ) );
1079                 string_truncate( buf, 0 );
1080             }
1081         }
1082     }
1083     return result;
1084 }
1085 
apply_modifiers_impl(LIST * result,string * buf,VAR_EDITS * edits,int n,LISTITER iter,LISTITER end)1086 static LIST * apply_modifiers_impl( LIST * result, string * buf,
1087     VAR_EDITS * edits, int n, LISTITER iter, LISTITER end )
1088 {
1089     return iter == end
1090         ? apply_modifiers_empty( result, buf, edits, n )
1091         : apply_modifiers_non_empty( result, buf, edits, n, iter, end );
1092 }
1093 
apply_subscript_and_modifiers(STACK * s,int n)1094 static LIST * apply_subscript_and_modifiers( STACK * s, int n )
1095 {
1096     LIST * const value = stack_top( s );
1097     LIST * const indices = stack_at( s, 1 );
1098     LIST * result = L0;
1099     VAR_EDITS * const edits = (VAR_EDITS *)((LIST * *)stack_get( s ) + 2);
1100     int const length = list_length( value );
1101     string buf[ 1 ];
1102     LISTITER indices_iter = list_begin( indices );
1103     LISTITER const indices_end = list_end( indices );
1104     string_new( buf );
1105     for ( ; indices_iter != indices_end; indices_iter = list_next( indices_iter
1106         ) )
1107     {
1108         LISTITER iter = list_begin( value );
1109         LISTITER end = list_end( value );
1110         subscript_t const sub = parse_subscript( object_str( list_item(
1111             indices_iter ) ) );
1112         get_iters( sub, &iter, &end, length );
1113         result = apply_modifiers_impl( result, buf, edits, n, iter, end );
1114     }
1115     string_free( buf );
1116     return result;
1117 }
1118 
1119 
1120 /*
1121  * expand() - expands a list of concatenated strings and variable references
1122  *
1123  * Takes a list of expansion items - each representing one element to be
1124  * concatenated and each containing a list of its values. Returns a list of all
1125  * possible values constructed by selecting a single value from each of the
1126  * elements and concatenating them together.
1127  *
1128  * For example, in the following code:
1129  *
1130  *     local a = one two three four ;
1131  *     local b = foo bar ;
1132  *     ECHO /$(a)/$(b)/$(a)/ ;
1133  *
1134  *   When constructing the result of /$(a)/$(b)/ this function would get called
1135  * with the following 7 expansion items:
1136  *     1. /
1137  *     2. one two three four
1138  *     3. /
1139  *     4. foo bar
1140  *     5. /
1141  *     6. one two three four
1142  *     7. /
1143  *
1144  *   And would result in a list containing 32 values:
1145  *     1. /one/foo/one/
1146  *     2. /one/foo/two/
1147  *     3. /one/foo/three/
1148  *     4. /one/foo/four/
1149  *     5. /one/bar/one/
1150  *     ...
1151  *
1152  */
1153 
1154 typedef struct expansion_item
1155 {
1156     /* Item's value list initialized prior to calling expand(). */
1157     LIST * values;
1158 
1159     /* Internal data initialized and used inside expand(). */
1160     LISTITER current;  /* Currently used value. */
1161     int size;          /* Concatenated string length prior to concatenating the
1162                         * item's current value.
1163                         */
1164 } expansion_item;
1165 
expand(expansion_item * items,int const length)1166 static LIST * expand( expansion_item * items, int const length )
1167 {
1168     LIST * result = L0;
1169     string buf[ 1 ];
1170     int size = 0;
1171     int i;
1172 
1173     assert( length > 0 );
1174     for ( i = 0; i < length; ++i )
1175     {
1176         LISTITER iter = list_begin( items[ i ].values );
1177         LISTITER const end = list_end( items[ i ].values );
1178 
1179         /* If any of the items has no values - the result is an empty list. */
1180         if ( iter == end ) return L0;
1181 
1182         /* Set each item's 'current' to its first listed value. This indicates
1183          * each item's next value to be used when constructing the list of all
1184          * possible concatenated values.
1185          */
1186         items[ i ].current = iter;
1187 
1188         /* Calculate the longest concatenated string length - to know how much
1189          * memory we need to allocate as a buffer for holding the concatenated
1190          * strings.
1191          */
1192         {
1193             int max = 0;
1194             for ( ; iter != end; iter = list_next( iter ) )
1195             {
1196                 int const len = strlen( object_str( list_item( iter ) ) );
1197                 if ( len > max ) max = len;
1198             }
1199             size += max;
1200         }
1201     }
1202 
1203     string_new( buf );
1204     string_reserve( buf, size );
1205 
1206     i = 0;
1207     while ( i >= 0 )
1208     {
1209         for ( ; i < length; ++i )
1210         {
1211             items[ i ].size = buf->size;
1212             string_append( buf, object_str( list_item( items[ i ].current ) ) );
1213         }
1214         result = list_push_back( result, object_new( buf->value ) );
1215         while ( --i >= 0 )
1216         {
1217             if ( list_next( items[ i ].current ) != list_end( items[ i ].values
1218                 ) )
1219             {
1220                 items[ i ].current = list_next( items[ i ].current );
1221                 string_truncate( buf, items[ i ].size );
1222                 break;
1223             }
1224             else
1225                 items[ i ].current = list_begin( items[ i ].values );
1226         }
1227     }
1228 
1229     string_free( buf );
1230     return result;
1231 }
1232 
combine_strings(STACK * s,int n,string * out)1233 static void combine_strings( STACK * s, int n, string * out )
1234 {
1235     int i;
1236     for ( i = 0; i < n; ++i )
1237     {
1238         LIST * const values = stack_pop( s );
1239         LISTITER iter = list_begin( values );
1240         LISTITER const end = list_end( values );
1241         if ( iter != end )
1242         {
1243             string_append( out, object_str( list_item( iter ) ) );
1244             for ( iter = list_next( iter ); iter != end; iter = list_next( iter
1245                 ) )
1246             {
1247                 string_push_back( out, ' ' );
1248                 string_append( out, object_str( list_item( iter ) ) );
1249             }
1250             list_free( values );
1251         }
1252     }
1253 }
1254 
1255 struct dynamic_array
1256 {
1257     int size;
1258     int capacity;
1259     void * data;
1260 };
1261 
dynamic_array_init(struct dynamic_array * array)1262 static void dynamic_array_init( struct dynamic_array * array )
1263 {
1264     array->size = 0;
1265     array->capacity = 0;
1266     array->data = 0;
1267 }
1268 
dynamic_array_free(struct dynamic_array * array)1269 static void dynamic_array_free( struct dynamic_array * array )
1270 {
1271     BJAM_FREE( array->data );
1272 }
1273 
dynamic_array_push_impl(struct dynamic_array * const array,void const * const value,int const unit_size)1274 static void dynamic_array_push_impl( struct dynamic_array * const array,
1275     void const * const value, int const unit_size )
1276 {
1277     if ( array->capacity == 0 )
1278     {
1279         array->capacity = 2;
1280         array->data = BJAM_MALLOC( array->capacity * unit_size );
1281     }
1282     else if ( array->capacity == array->size )
1283     {
1284         void * new_data;
1285         array->capacity *= 2;
1286         new_data = BJAM_MALLOC( array->capacity * unit_size );
1287         memcpy( new_data, array->data, array->size * unit_size  );
1288         BJAM_FREE( array->data );
1289         array->data = new_data;
1290     }
1291     memcpy( (char *)array->data + array->size * unit_size, value, unit_size );
1292     ++array->size;
1293 }
1294 
1295 #define dynamic_array_push( array, value ) (dynamic_array_push_impl(array, &value, sizeof(value)))
1296 #define dynamic_array_at( type, array, idx ) (((type *)(array)->data)[idx])
1297 #define dynamic_array_pop( array ) (--(array)->size)
1298 
1299 /*
1300  * struct compiler
1301  */
1302 
1303 struct label_info
1304 {
1305     int absolute_position;
1306     struct dynamic_array uses[ 1 ];
1307 };
1308 
1309 #define LOOP_INFO_BREAK 0
1310 #define LOOP_INFO_CONTINUE 1
1311 
1312 struct loop_info
1313 {
1314     int type;
1315     int label;
1316     int cleanup_depth;
1317 };
1318 
1319 struct stored_rule
1320 {
1321     OBJECT * name;
1322     PARSE * parse;
1323     int num_arguments;
1324     struct arg_list * arguments;
1325     int local;
1326 };
1327 
1328 typedef struct compiler
1329 {
1330     struct dynamic_array code[ 1 ];
1331     struct dynamic_array constants[ 1 ];
1332     struct dynamic_array labels[ 1 ];
1333     struct dynamic_array rules[ 1 ];
1334     struct dynamic_array actions[ 1 ];
1335     struct dynamic_array cleanups[ 1 ];
1336     struct dynamic_array loop_scopes[ 1 ];
1337 } compiler;
1338 
compiler_init(compiler * c)1339 static void compiler_init( compiler * c )
1340 {
1341     dynamic_array_init( c->code );
1342     dynamic_array_init( c->constants );
1343     dynamic_array_init( c->labels );
1344     dynamic_array_init( c->rules );
1345     dynamic_array_init( c->actions );
1346     dynamic_array_init( c->cleanups );
1347     dynamic_array_init( c->loop_scopes );
1348 }
1349 
compiler_free(compiler * c)1350 static void compiler_free( compiler * c )
1351 {
1352     int i;
1353     dynamic_array_free( c->actions );
1354     dynamic_array_free( c->rules );
1355     for ( i = 0; i < c->labels->size; ++i )
1356         dynamic_array_free( dynamic_array_at( struct label_info, c->labels, i
1357             ).uses );
1358     dynamic_array_free( c->labels );
1359     dynamic_array_free( c->constants );
1360     dynamic_array_free( c->code );
1361     dynamic_array_free( c->cleanups );
1362     dynamic_array_free( c->loop_scopes );
1363 }
1364 
compile_emit_instruction(compiler * c,instruction instr)1365 static void compile_emit_instruction( compiler * c, instruction instr )
1366 {
1367     dynamic_array_push( c->code, instr );
1368 }
1369 
compile_new_label(compiler * c)1370 static int compile_new_label( compiler * c )
1371 {
1372     int result = c->labels->size;
1373     struct label_info info;
1374     info.absolute_position = -1;
1375     dynamic_array_init( info.uses );
1376     dynamic_array_push( c->labels, info );
1377     return result;
1378 }
1379 
compile_set_label(compiler * c,int label)1380 static void compile_set_label( compiler * c, int label )
1381 {
1382     struct label_info * const l = &dynamic_array_at( struct label_info,
1383         c->labels, label );
1384     int const pos = c->code->size;
1385     int i;
1386     assert( l->absolute_position == -1 );
1387     l->absolute_position = pos;
1388     for ( i = 0; i < l->uses->size; ++i )
1389     {
1390         int id = dynamic_array_at( int, l->uses, i );
1391         int offset = (int)( pos - id - 1 );
1392         dynamic_array_at( instruction, c->code, id ).arg = offset;
1393     }
1394 }
1395 
compile_emit(compiler * c,unsigned int op_code,int arg)1396 static void compile_emit( compiler * c, unsigned int op_code, int arg )
1397 {
1398     instruction instr;
1399     instr.op_code = op_code;
1400     instr.arg = arg;
1401     compile_emit_instruction( c, instr );
1402 }
1403 
compile_emit_branch(compiler * c,unsigned int op_code,int label)1404 static void compile_emit_branch( compiler * c, unsigned int op_code, int label )
1405 {
1406     struct label_info * const l = &dynamic_array_at( struct label_info,
1407         c->labels, label );
1408     int const pos = c->code->size;
1409     instruction instr;
1410     instr.op_code = op_code;
1411     if ( l->absolute_position == -1 )
1412     {
1413         instr.arg = 0;
1414         dynamic_array_push( l->uses, pos );
1415     }
1416     else
1417         instr.arg = (int)( l->absolute_position - pos - 1 );
1418     compile_emit_instruction( c, instr );
1419 }
1420 
compile_emit_constant(compiler * c,OBJECT * value)1421 static int compile_emit_constant( compiler * c, OBJECT * value )
1422 {
1423     OBJECT * copy = object_copy( value );
1424     dynamic_array_push( c->constants, copy );
1425     return c->constants->size - 1;
1426 }
1427 
compile_push_cleanup(compiler * c,unsigned int op_code,int arg)1428 static void compile_push_cleanup( compiler * c, unsigned int op_code, int arg )
1429 {
1430     instruction instr;
1431     instr.op_code = op_code;
1432     instr.arg = arg;
1433     dynamic_array_push( c->cleanups, instr );
1434 }
1435 
compile_pop_cleanup(compiler * c)1436 static void compile_pop_cleanup( compiler * c )
1437 {
1438     dynamic_array_pop( c->cleanups );
1439 }
1440 
compile_emit_cleanups(compiler * c,int end)1441 static void compile_emit_cleanups( compiler * c, int end )
1442 {
1443     int i;
1444     for ( i = c->cleanups->size; --i >= end; )
1445     {
1446         compile_emit_instruction( c, dynamic_array_at( instruction, c->cleanups, i ) );
1447     }
1448 }
1449 
compile_emit_loop_jump(compiler * c,int type)1450 static void compile_emit_loop_jump( compiler * c, int type )
1451 {
1452     struct loop_info * info = NULL;
1453     int i;
1454     for ( i = c->loop_scopes->size; --i >= 0; )
1455     {
1456         struct loop_info * elem = &dynamic_array_at( struct loop_info, c->loop_scopes, i );
1457         if ( elem->type == type )
1458         {
1459             info = elem;
1460             break;
1461         }
1462     }
1463     if ( info == NULL )
1464     {
1465         printf( "warning: ignoring break statement used outside of loop\n" );
1466         return;
1467     }
1468     compile_emit_cleanups( c, info->cleanup_depth );
1469     compile_emit_branch( c, INSTR_JUMP, info->label );
1470 }
1471 
compile_push_break_scope(compiler * c,int label)1472 static void compile_push_break_scope( compiler * c, int label )
1473 {
1474     struct loop_info info;
1475     info.type = LOOP_INFO_BREAK;
1476     info.label = label;
1477     info.cleanup_depth = c->cleanups->size;
1478     dynamic_array_push( c->loop_scopes, info );
1479 }
1480 
compile_push_continue_scope(compiler * c,int label)1481 static void compile_push_continue_scope( compiler * c, int label )
1482 {
1483     struct loop_info info;
1484     info.type = LOOP_INFO_CONTINUE;
1485     info.label = label;
1486     info.cleanup_depth = c->cleanups->size;
1487     dynamic_array_push( c->loop_scopes, info );
1488 }
1489 
compile_pop_break_scope(compiler * c)1490 static void compile_pop_break_scope( compiler * c )
1491 {
1492     assert( c->loop_scopes->size > 0 );
1493     assert( dynamic_array_at( struct loop_info, c->loop_scopes, c->loop_scopes->size - 1 ).type == LOOP_INFO_BREAK );
1494     dynamic_array_pop( c->loop_scopes );
1495 }
1496 
compile_pop_continue_scope(compiler * c)1497 static void compile_pop_continue_scope( compiler * c )
1498 {
1499     assert( c->loop_scopes->size > 0 );
1500     assert( dynamic_array_at( struct loop_info, c->loop_scopes, c->loop_scopes->size - 1 ).type == LOOP_INFO_CONTINUE );
1501     dynamic_array_pop( c->loop_scopes );
1502 }
1503 
compile_emit_rule(compiler * c,OBJECT * name,PARSE * parse,int num_arguments,struct arg_list * arguments,int local)1504 static int compile_emit_rule( compiler * c, OBJECT * name, PARSE * parse,
1505     int num_arguments, struct arg_list * arguments, int local )
1506 {
1507     struct stored_rule rule;
1508     rule.name = object_copy( name );
1509     rule.parse = parse;
1510     rule.num_arguments = num_arguments;
1511     rule.arguments = arguments;
1512     rule.local = local;
1513     dynamic_array_push( c->rules, rule );
1514     return (int)( c->rules->size - 1 );
1515 }
1516 
compile_emit_actions(compiler * c,PARSE * parse)1517 static int compile_emit_actions( compiler * c, PARSE * parse )
1518 {
1519     SUBACTION a;
1520     a.name = object_copy( parse->string );
1521     a.command = function_compile_actions( object_str( parse->string1 ),
1522         parse->file, parse->line );
1523     a.flags = parse->num;
1524     dynamic_array_push( c->actions, a );
1525     return (int)( c->actions->size - 1 );
1526 }
1527 
compile_to_function(compiler * c)1528 static JAM_FUNCTION * compile_to_function( compiler * c )
1529 {
1530     JAM_FUNCTION * const result = (JAM_FUNCTION*)BJAM_MALLOC( sizeof( JAM_FUNCTION ) );
1531     int i;
1532     result->base.type = FUNCTION_JAM;
1533     result->base.reference_count = 1;
1534     result->base.formal_arguments = 0;
1535     result->base.num_formal_arguments = 0;
1536 
1537     result->base.rulename = 0;
1538 
1539     result->code_size = c->code->size;
1540     result->code = (instruction*)BJAM_MALLOC( c->code->size * sizeof( instruction ) );
1541     memcpy( result->code, c->code->data, c->code->size * sizeof( instruction ) );
1542 
1543     result->constants = (OBJECT**)BJAM_MALLOC( c->constants->size * sizeof( OBJECT * ) );
1544     if ( c->constants->size != 0 )
1545         memcpy( result->constants, c->constants->data,
1546                 c->constants->size * sizeof( OBJECT * ) );
1547     result->num_constants = c->constants->size;
1548 
1549     result->num_subfunctions = c->rules->size;
1550     result->functions = (SUBFUNCTION*)BJAM_MALLOC( c->rules->size * sizeof( SUBFUNCTION ) );
1551     for ( i = 0; i < c->rules->size; ++i )
1552     {
1553         struct stored_rule * const rule = &dynamic_array_at( struct stored_rule,
1554             c->rules, i );
1555         result->functions[ i ].name = rule->name;
1556         result->functions[ i ].code = function_compile( rule->parse );
1557         result->functions[ i ].code->num_formal_arguments = rule->num_arguments;
1558         result->functions[ i ].code->formal_arguments = rule->arguments;
1559         result->functions[ i ].local = rule->local;
1560     }
1561 
1562     result->actions = (SUBACTION*)BJAM_MALLOC( c->actions->size * sizeof( SUBACTION ) );
1563     if ( c->actions->size != 0 )
1564         memcpy( result->actions, c->actions->data,
1565                 c->actions->size * sizeof( SUBACTION ) );
1566     result->num_subactions = c->actions->size;
1567 
1568     result->generic = 0;
1569 
1570     result->file = 0;
1571     result->line = -1;
1572 
1573     return result;
1574 }
1575 
1576 
1577 /*
1578  * Parsing of variable expansions
1579  */
1580 
1581 typedef struct VAR_PARSE_GROUP
1582 {
1583     struct dynamic_array elems[ 1 ];
1584 } VAR_PARSE_GROUP;
1585 
1586 typedef struct VAR_PARSE_ACTIONS
1587 {
1588     struct dynamic_array elems[ 1 ];
1589 } VAR_PARSE_ACTIONS;
1590 
1591 #define VAR_PARSE_TYPE_VAR      0
1592 #define VAR_PARSE_TYPE_STRING   1
1593 #define VAR_PARSE_TYPE_FILE     2
1594 
1595 typedef struct _var_parse
1596 {
1597     int type;  /* string, variable or file */
1598 } VAR_PARSE;
1599 
1600 typedef struct
1601 {
1602     VAR_PARSE base;
1603     VAR_PARSE_GROUP * name;
1604     VAR_PARSE_GROUP * subscript;
1605     struct dynamic_array modifiers[ 1 ];
1606 } VAR_PARSE_VAR;
1607 
1608 typedef struct
1609 {
1610     VAR_PARSE base;
1611     OBJECT * s;
1612 } VAR_PARSE_STRING;
1613 
1614 typedef struct
1615 {
1616     VAR_PARSE base;
1617     struct dynamic_array filename[ 1 ];
1618     struct dynamic_array contents[ 1 ];
1619 } VAR_PARSE_FILE;
1620 
1621 static void var_parse_free( VAR_PARSE * );
1622 
1623 
1624 /*
1625  * VAR_PARSE_GROUP
1626  */
1627 
var_parse_group_new()1628 static VAR_PARSE_GROUP * var_parse_group_new()
1629 {
1630     VAR_PARSE_GROUP * const result = (VAR_PARSE_GROUP*)BJAM_MALLOC( sizeof( VAR_PARSE_GROUP ) );
1631     dynamic_array_init( result->elems );
1632     return result;
1633 }
1634 
var_parse_group_free(VAR_PARSE_GROUP * group)1635 static void var_parse_group_free( VAR_PARSE_GROUP * group )
1636 {
1637     int i;
1638     for ( i = 0; i < group->elems->size; ++i )
1639         var_parse_free( dynamic_array_at( VAR_PARSE *, group->elems, i ) );
1640     dynamic_array_free( group->elems );
1641     BJAM_FREE( group );
1642 }
1643 
var_parse_group_add(VAR_PARSE_GROUP * group,VAR_PARSE * elem)1644 static void var_parse_group_add( VAR_PARSE_GROUP * group, VAR_PARSE * elem )
1645 {
1646     dynamic_array_push( group->elems, elem );
1647 }
1648 
var_parse_group_maybe_add_constant(VAR_PARSE_GROUP * group,char const * start,char const * end)1649 static void var_parse_group_maybe_add_constant( VAR_PARSE_GROUP * group,
1650     char const * start, char const * end )
1651 {
1652     if ( start != end )
1653     {
1654         string buf[ 1 ];
1655         VAR_PARSE_STRING * const value = (VAR_PARSE_STRING *)BJAM_MALLOC(
1656             sizeof(VAR_PARSE_STRING) );
1657         value->base.type = VAR_PARSE_TYPE_STRING;
1658         string_new( buf );
1659         string_append_range( buf, start, end );
1660         value->s = object_new( buf->value );
1661         string_free( buf );
1662         var_parse_group_add( group, (VAR_PARSE *)value );
1663     }
1664 }
1665 
var_parse_group_as_literal(VAR_PARSE_GROUP * group)1666 VAR_PARSE_STRING * var_parse_group_as_literal( VAR_PARSE_GROUP * group )
1667 {
1668     if ( group->elems->size == 1  )
1669     {
1670         VAR_PARSE * result = dynamic_array_at( VAR_PARSE *, group->elems, 0 );
1671         if ( result->type == VAR_PARSE_TYPE_STRING )
1672             return (VAR_PARSE_STRING *)result;
1673     }
1674     return 0;
1675 }
1676 
1677 
1678 /*
1679  * VAR_PARSE_ACTIONS
1680  */
1681 
var_parse_actions_new()1682 static VAR_PARSE_ACTIONS * var_parse_actions_new()
1683 {
1684     VAR_PARSE_ACTIONS * const result = (VAR_PARSE_ACTIONS *)BJAM_MALLOC(
1685         sizeof(VAR_PARSE_ACTIONS) );
1686     dynamic_array_init( result->elems );
1687     return result;
1688 }
1689 
var_parse_actions_free(VAR_PARSE_ACTIONS * actions)1690 static void var_parse_actions_free( VAR_PARSE_ACTIONS * actions )
1691 {
1692     int i;
1693     for ( i = 0; i < actions->elems->size; ++i )
1694         var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *,
1695             actions->elems, i ) );
1696     dynamic_array_free( actions->elems );
1697     BJAM_FREE( actions );
1698 }
1699 
1700 
1701 /*
1702  * VAR_PARSE_VAR
1703  */
1704 
var_parse_var_new()1705 static VAR_PARSE_VAR * var_parse_var_new()
1706 {
1707     VAR_PARSE_VAR * result = (VAR_PARSE_VAR*)BJAM_MALLOC( sizeof( VAR_PARSE_VAR ) );
1708     result->base.type = VAR_PARSE_TYPE_VAR;
1709     result->name = var_parse_group_new();
1710     result->subscript = 0;
1711     dynamic_array_init( result->modifiers );
1712     return result;
1713 }
1714 
var_parse_var_free(VAR_PARSE_VAR * var)1715 static void var_parse_var_free( VAR_PARSE_VAR * var )
1716 {
1717     int i;
1718     var_parse_group_free( var->name );
1719     if ( var->subscript )
1720         var_parse_group_free( var->subscript );
1721     for ( i = 0; i < var->modifiers->size; ++i )
1722         var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *,
1723             var->modifiers, i ) );
1724     dynamic_array_free( var->modifiers );
1725     BJAM_FREE( var );
1726 }
1727 
var_parse_var_new_modifier(VAR_PARSE_VAR * var)1728 static VAR_PARSE_GROUP * var_parse_var_new_modifier( VAR_PARSE_VAR * var )
1729 {
1730     VAR_PARSE_GROUP * result = var_parse_group_new();
1731     dynamic_array_push( var->modifiers, result );
1732     return result;
1733 }
1734 
1735 
1736 /*
1737  * VAR_PARSE_STRING
1738  */
1739 
var_parse_string_free(VAR_PARSE_STRING * string)1740 static void var_parse_string_free( VAR_PARSE_STRING * string )
1741 {
1742     object_free( string->s );
1743     BJAM_FREE( string );
1744 }
1745 
1746 
1747 /*
1748  * VAR_PARSE_FILE
1749  */
1750 
var_parse_file_new(void)1751 static VAR_PARSE_FILE * var_parse_file_new( void )
1752 {
1753     VAR_PARSE_FILE * const result = (VAR_PARSE_FILE *)BJAM_MALLOC( sizeof(
1754         VAR_PARSE_FILE ) );
1755     result->base.type = VAR_PARSE_TYPE_FILE;
1756     dynamic_array_init( result->filename );
1757     dynamic_array_init( result->contents );
1758     return result;
1759 }
1760 
var_parse_file_free(VAR_PARSE_FILE * file)1761 static void var_parse_file_free( VAR_PARSE_FILE * file )
1762 {
1763     int i;
1764     for ( i = 0; i < file->filename->size; ++i )
1765         var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *,
1766             file->filename, i ) );
1767     dynamic_array_free( file->filename );
1768     for ( i = 0; i < file->contents->size; ++i )
1769         var_parse_group_free( dynamic_array_at( VAR_PARSE_GROUP *,
1770             file->contents, i ) );
1771     dynamic_array_free( file->contents );
1772     BJAM_FREE( file );
1773 }
1774 
1775 
1776 /*
1777  * VAR_PARSE
1778  */
1779 
var_parse_free(VAR_PARSE * parse)1780 static void var_parse_free( VAR_PARSE * parse )
1781 {
1782     switch ( parse->type )
1783     {
1784         case VAR_PARSE_TYPE_VAR:
1785             var_parse_var_free( (VAR_PARSE_VAR *)parse );
1786             break;
1787 
1788         case VAR_PARSE_TYPE_STRING:
1789             var_parse_string_free( (VAR_PARSE_STRING *)parse );
1790             break;
1791 
1792         case VAR_PARSE_TYPE_FILE:
1793             var_parse_file_free( (VAR_PARSE_FILE *)parse );
1794             break;
1795 
1796         default:
1797             assert( !"Invalid type" );
1798     }
1799 }
1800 
1801 
1802 /*
1803  * Compile VAR_PARSE
1804  */
1805 
1806 static void var_parse_group_compile( VAR_PARSE_GROUP const * parse,
1807     compiler * c );
1808 
var_parse_var_compile(VAR_PARSE_VAR const * parse,compiler * c)1809 static void var_parse_var_compile( VAR_PARSE_VAR const * parse, compiler * c )
1810 {
1811     int expand_name = 0;
1812     int is_get_grist = 0;
1813     int has_modifiers = 0;
1814     /* Special case common modifiers */
1815     if ( parse->modifiers->size == 1 )
1816     {
1817         VAR_PARSE_GROUP * mod = dynamic_array_at( VAR_PARSE_GROUP *, parse->modifiers, 0 );
1818         if ( mod->elems->size == 1 )
1819         {
1820             VAR_PARSE * mod1 = dynamic_array_at( VAR_PARSE *, mod->elems, 0 );
1821             if ( mod1->type == VAR_PARSE_TYPE_STRING )
1822             {
1823                 OBJECT * s = ( (VAR_PARSE_STRING *)mod1 )->s;
1824                 if ( ! strcmp ( object_str( s ), "G" ) )
1825                 {
1826                     is_get_grist = 1;
1827                 }
1828             }
1829         }
1830     }
1831     /* If there are modifiers, emit them in reverse order. */
1832     if ( parse->modifiers->size > 0 && !is_get_grist )
1833     {
1834         int i;
1835         has_modifiers = 1;
1836         for ( i = 0; i < parse->modifiers->size; ++i )
1837             var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *,
1838                 parse->modifiers, parse->modifiers->size - i - 1 ), c );
1839     }
1840 
1841     /* If there is a subscript, emit it. */
1842     if ( parse->subscript )
1843         var_parse_group_compile( parse->subscript, c );
1844 
1845     /* If the variable name is empty, look it up. */
1846     if ( parse->name->elems->size == 0 )
1847         compile_emit( c, INSTR_PUSH_VAR, compile_emit_constant( c,
1848             constant_empty ) );
1849     /* If the variable name does not need to be expanded, look it up. */
1850     else if ( parse->name->elems->size == 1 && dynamic_array_at( VAR_PARSE *,
1851         parse->name->elems, 0 )->type == VAR_PARSE_TYPE_STRING )
1852     {
1853         OBJECT * const name = ( (VAR_PARSE_STRING *)dynamic_array_at(
1854             VAR_PARSE *, parse->name->elems, 0 ) )->s;
1855         int const idx = get_argument_index( object_str( name ) );
1856         if ( idx != -1 )
1857             compile_emit( c, INSTR_PUSH_ARG, idx );
1858         else
1859             compile_emit( c, INSTR_PUSH_VAR, compile_emit_constant( c, name ) );
1860     }
1861     /* Otherwise, push the var names and use the group instruction. */
1862     else
1863     {
1864         var_parse_group_compile( parse->name, c );
1865         expand_name = 1;
1866     }
1867 
1868     /** Select the instruction for expanding the variable. */
1869     if ( !has_modifiers && !parse->subscript && !expand_name )
1870         ;
1871     else if ( !has_modifiers && !parse->subscript && expand_name )
1872         compile_emit( c, INSTR_PUSH_GROUP, 0 );
1873     else if ( !has_modifiers && parse->subscript && !expand_name )
1874         compile_emit( c, INSTR_APPLY_INDEX, 0 );
1875     else if ( !has_modifiers && parse->subscript && expand_name )
1876         compile_emit( c, INSTR_APPLY_INDEX_GROUP, 0 );
1877     else if ( has_modifiers && !parse->subscript && !expand_name )
1878         compile_emit( c, INSTR_APPLY_MODIFIERS, parse->modifiers->size );
1879     else if ( has_modifiers && !parse->subscript && expand_name )
1880         compile_emit( c, INSTR_APPLY_MODIFIERS_GROUP, parse->modifiers->size );
1881     else if ( has_modifiers && parse->subscript && !expand_name )
1882         compile_emit( c, INSTR_APPLY_INDEX_MODIFIERS, parse->modifiers->size );
1883     else if ( has_modifiers && parse->subscript && expand_name )
1884         compile_emit( c, INSTR_APPLY_INDEX_MODIFIERS_GROUP,
1885             parse->modifiers->size );
1886 
1887     /* Now apply any special modifiers */
1888     if ( is_get_grist )
1889     {
1890         compile_emit( c, INSTR_GET_GRIST, 0 );
1891     }
1892 }
1893 
var_parse_string_compile(VAR_PARSE_STRING const * parse,compiler * c)1894 static void var_parse_string_compile( VAR_PARSE_STRING const * parse,
1895     compiler * c )
1896 {
1897     compile_emit( c, INSTR_PUSH_CONSTANT, compile_emit_constant( c, parse->s )
1898         );
1899 }
1900 
var_parse_file_compile(VAR_PARSE_FILE const * parse,compiler * c)1901 static void var_parse_file_compile( VAR_PARSE_FILE const * parse, compiler * c )
1902 {
1903     int i;
1904     for ( i = 0; i < parse->filename->size; ++i )
1905         var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *,
1906             parse->filename, parse->filename->size - i - 1 ), c );
1907     compile_emit( c, INSTR_APPEND_STRINGS, parse->filename->size );
1908     for ( i = 0; i < parse->contents->size; ++i )
1909         var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *,
1910             parse->contents, parse->contents->size - i - 1 ), c );
1911     compile_emit( c, INSTR_WRITE_FILE, parse->contents->size );
1912 }
1913 
var_parse_compile(VAR_PARSE const * parse,compiler * c)1914 static void var_parse_compile( VAR_PARSE const * parse, compiler * c )
1915 {
1916     switch ( parse->type )
1917     {
1918         case VAR_PARSE_TYPE_VAR:
1919             var_parse_var_compile( (VAR_PARSE_VAR const *)parse, c );
1920             break;
1921 
1922         case VAR_PARSE_TYPE_STRING:
1923             var_parse_string_compile( (VAR_PARSE_STRING const *)parse, c );
1924             break;
1925 
1926         case VAR_PARSE_TYPE_FILE:
1927             var_parse_file_compile( (VAR_PARSE_FILE const *)parse, c );
1928             break;
1929 
1930         default:
1931             assert( !"Unknown var parse type." );
1932     }
1933 }
1934 
var_parse_group_compile(VAR_PARSE_GROUP const * parse,compiler * c)1935 static void var_parse_group_compile( VAR_PARSE_GROUP const * parse, compiler * c
1936     )
1937 {
1938     /* Emit the elements in reverse order. */
1939     int i;
1940     for ( i = 0; i < parse->elems->size; ++i )
1941         var_parse_compile( dynamic_array_at( VAR_PARSE *, parse->elems,
1942             parse->elems->size - i - 1 ), c );
1943     /* If there are no elements, emit an empty string. */
1944     if ( parse->elems->size == 0 )
1945         compile_emit( c, INSTR_PUSH_CONSTANT, compile_emit_constant( c,
1946             constant_empty ) );
1947     /* If there is more than one element, combine them. */
1948     if ( parse->elems->size > 1 )
1949         compile_emit( c, INSTR_COMBINE_STRINGS, parse->elems->size );
1950 }
1951 
var_parse_actions_compile(VAR_PARSE_ACTIONS const * actions,compiler * c)1952 static void var_parse_actions_compile( VAR_PARSE_ACTIONS const * actions,
1953     compiler * c )
1954 {
1955     int i;
1956     for ( i = 0; i < actions->elems->size; ++i )
1957         var_parse_group_compile( dynamic_array_at( VAR_PARSE_GROUP *,
1958             actions->elems, actions->elems->size - i - 1 ), c );
1959     compile_emit( c, INSTR_OUTPUT_STRINGS, actions->elems->size );
1960 }
1961 
1962 
1963 /*
1964  * Parse VAR_PARSE_VAR
1965  */
1966 
1967 static VAR_PARSE * parse_at_file( char const * start, char const * mid,
1968     char const * end );
1969 static VAR_PARSE * parse_variable( char const * * string );
1970 static int try_parse_variable( char const * * s_, char const * * string,
1971     VAR_PARSE_GROUP * out );
1972 static void balance_parentheses( char const * * s_, char const * * string,
1973     VAR_PARSE_GROUP * out );
1974 static void parse_var_string( char const * first, char const * last,
1975     struct dynamic_array * out );
1976 
1977 
1978 /*
1979  * Parses a string that can contain variables to expand.
1980  */
1981 
parse_expansion(char const ** string)1982 static VAR_PARSE_GROUP * parse_expansion( char const * * string )
1983 {
1984     VAR_PARSE_GROUP * result = var_parse_group_new();
1985     char const * s = *string;
1986     for ( ; ; )
1987     {
1988         if ( try_parse_variable( &s, string, result ) ) {}
1989         else if ( s[ 0 ] == '\0' )
1990         {
1991             var_parse_group_maybe_add_constant( result, *string, s );
1992             return result;
1993         }
1994         else
1995             ++s;
1996     }
1997 }
1998 
parse_actions(char const * string)1999 static VAR_PARSE_ACTIONS * parse_actions( char const * string )
2000 {
2001     VAR_PARSE_ACTIONS * const result = var_parse_actions_new();
2002     parse_var_string( string, string + strlen( string ), result->elems );
2003     return result;
2004 }
2005 
2006 /*
2007  * Checks whether the string a *s_ starts with a variable expansion "$(".
2008  * *string should point to the first unemitted character before *s. If *s_
2009  * starts with variable expansion, appends elements to out up to the closing
2010  * ")", and adjusts *s_ and *string to point to next character. Returns 1 if s_
2011  * starts with a variable, 0 otherwise.
2012  */
2013 
try_parse_variable(char const ** s_,char const ** string,VAR_PARSE_GROUP * out)2014 static int try_parse_variable( char const * * s_, char const * * string,
2015     VAR_PARSE_GROUP * out )
2016 {
2017     char const * s = *s_;
2018     if ( s[ 0 ] == '$' && s[ 1 ] == '(' )
2019     {
2020         var_parse_group_maybe_add_constant( out, *string, s );
2021         s += 2;
2022         var_parse_group_add( out, parse_variable( &s ) );
2023         *string = s;
2024         *s_ = s;
2025         return 1;
2026     }
2027     if ( s[ 0 ] == '@' && s[ 1 ] == '(' )
2028     {
2029         int depth = 1;
2030         char const * ine;
2031         char const * split = 0;
2032         var_parse_group_maybe_add_constant( out, *string, s );
2033         s += 2;
2034         ine = s;
2035 
2036         /* Scan the content of the response file @() section. */
2037         while ( *ine && ( depth > 0 ) )
2038         {
2039             switch ( *ine )
2040             {
2041             case '(': ++depth; break;
2042             case ')': --depth; break;
2043             case ':':
2044                 if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '='
2045                     ) )
2046                     split = ine;
2047                 break;
2048             }
2049             ++ine;
2050         }
2051 
2052         if ( !split || depth )
2053             return 0;
2054 
2055         var_parse_group_add( out, parse_at_file( s, split, ine - 1 ) );
2056         *string = ine;
2057         *s_ = ine;
2058         return 1;
2059     }
2060     return 0;
2061 }
2062 
2063 
2064 static char const * current_file = "";
2065 static int current_line;
2066 
parse_error(char const * message)2067 static void parse_error( char const * message )
2068 {
2069     out_printf( "%s:%d: %s\n", current_file, current_line, message );
2070 }
2071 
2072 
2073 /*
2074  * Parses a single variable up to the closing ")" and adjusts *string to point
2075  * to the next character. *string should point to the character immediately
2076  * after the initial "$(".
2077  */
2078 
parse_variable(char const ** string)2079 static VAR_PARSE * parse_variable( char const * * string )
2080 {
2081     VAR_PARSE_VAR * const result = var_parse_var_new();
2082     VAR_PARSE_GROUP * const name = result->name;
2083     char const * s = *string;
2084     for ( ; ; )
2085     {
2086         if ( try_parse_variable( &s, string, name ) ) {}
2087         else if ( s[ 0 ] == ':' )
2088         {
2089             VAR_PARSE_GROUP * mod;
2090             var_parse_group_maybe_add_constant( name, *string, s );
2091             ++s;
2092             *string = s;
2093             mod = var_parse_var_new_modifier( result );
2094             for ( ; ; )
2095             {
2096                 if ( try_parse_variable( &s, string, mod ) ) {}
2097                 else if ( s[ 0 ] == ')' )
2098                 {
2099                     var_parse_group_maybe_add_constant( mod, *string, s );
2100                     *string = ++s;
2101                     return (VAR_PARSE *)result;
2102                 }
2103                 else if ( s[ 0 ] == '(' )
2104                 {
2105                     ++s;
2106                     balance_parentheses( &s, string, mod );
2107                 }
2108                 else if ( s[ 0 ] == ':' )
2109                 {
2110                     var_parse_group_maybe_add_constant( mod, *string, s );
2111                     *string = ++s;
2112                     mod = var_parse_var_new_modifier( result );
2113                 }
2114                 else if ( s[ 0 ] == '[' )
2115                 {
2116                     parse_error("unexpected subscript");
2117                     ++s;
2118                 }
2119                 else if ( s[ 0 ] == '\0' )
2120                 {
2121                     parse_error( "unbalanced parentheses" );
2122                     var_parse_group_maybe_add_constant( mod, *string, s );
2123                     *string = s;
2124                     return (VAR_PARSE *)result;
2125                 }
2126                 else
2127                     ++s;
2128             }
2129         }
2130         else if ( s[ 0 ] == '[' )
2131         {
2132             VAR_PARSE_GROUP * subscript = var_parse_group_new();
2133             result->subscript = subscript;
2134             var_parse_group_maybe_add_constant( name, *string, s );
2135             *string = ++s;
2136             for ( ; ; )
2137             {
2138                 if ( try_parse_variable( &s, string, subscript ) ) {}
2139                 else if ( s[ 0 ] == ']' )
2140                 {
2141                     var_parse_group_maybe_add_constant( subscript, *string, s );
2142                     *string = ++s;
2143                     if ( s[ 0 ] != ')' && s[ 0 ] != ':' && s[ 0 ] != '\0' )
2144                         parse_error( "unexpected text following []" );
2145                     break;
2146                 }
2147                 else if ( isdigit( s[ 0 ] ) || s[ 0 ] == '-' )
2148                 {
2149                     ++s;
2150                 }
2151                 else if ( s[ 0 ] == '\0' )
2152                 {
2153                     parse_error( "malformed subscript" );
2154                     break;
2155                 }
2156                 else
2157                 {
2158                     parse_error( "malformed subscript" );
2159                     ++s;
2160                 }
2161             }
2162         }
2163         else if ( s[ 0 ] == ')' )
2164         {
2165             var_parse_group_maybe_add_constant( name, *string, s );
2166             *string = ++s;
2167             return (VAR_PARSE *)result;
2168         }
2169         else if ( s[ 0 ] == '(' )
2170         {
2171             ++s;
2172             balance_parentheses( &s, string, name );
2173         }
2174         else if ( s[ 0 ] == '\0' )
2175         {
2176             parse_error( "unbalanced parentheses" );
2177             var_parse_group_maybe_add_constant( name, *string, s );
2178             *string = s;
2179             return (VAR_PARSE *)result;
2180         }
2181         else
2182             ++s;
2183     }
2184 }
2185 
parse_var_string(char const * first,char const * last,struct dynamic_array * out)2186 static void parse_var_string( char const * first, char const * last,
2187     struct dynamic_array * out )
2188 {
2189     char const * saved = first;
2190     while ( first != last )
2191     {
2192         /* Handle whitespace. */
2193         while ( first != last && isspace( *first ) ) ++first;
2194         if ( saved != first )
2195         {
2196             VAR_PARSE_GROUP * const group = var_parse_group_new();
2197             var_parse_group_maybe_add_constant( group, saved, first );
2198             saved = first;
2199             dynamic_array_push( out, group );
2200         }
2201         if ( first == last ) break;
2202 
2203         /* Handle non-whitespace */
2204         {
2205             VAR_PARSE_GROUP * group = var_parse_group_new();
2206             for ( ; ; )
2207             {
2208                 if ( first == last || isspace( *first ) )
2209                 {
2210                     var_parse_group_maybe_add_constant( group, saved, first );
2211                     saved = first;
2212                     break;
2213                 }
2214                 if ( try_parse_variable( &first, &saved, group ) )
2215                     assert( first <= last );
2216                 else
2217                     ++first;
2218             }
2219             dynamic_array_push( out, group );
2220         }
2221     }
2222 }
2223 
2224 /*
2225  * start should point to the character immediately following the opening "@(",
2226  * mid should point to the ":E=", and end should point to the closing ")".
2227  */
2228 
parse_at_file(char const * start,char const * mid,char const * end)2229 static VAR_PARSE * parse_at_file( char const * start, char const * mid,
2230     char const * end )
2231 {
2232     VAR_PARSE_FILE * result = var_parse_file_new();
2233     parse_var_string( start, mid, result->filename );
2234     parse_var_string( mid + 3, end, result->contents );
2235     return (VAR_PARSE *)result;
2236 }
2237 
2238 /*
2239  * Given that *s_ points to the character after a "(", parses up to the matching
2240  * ")". *string should point to the first unemitted character before *s_.
2241  *
2242  * When the function returns, *s_ will point to the character after the ")", and
2243  * *string will point to the first unemitted character before *s_. The range
2244  * from *string to *s_ does not contain any variables that need to be expanded.
2245  */
2246 
balance_parentheses(char const ** s_,char const ** string,VAR_PARSE_GROUP * out)2247 void balance_parentheses( char const * * s_, char const * * string,
2248     VAR_PARSE_GROUP * out)
2249 {
2250     int depth = 1;
2251     char const * s = *s_;
2252     for ( ; ; )
2253     {
2254         if ( try_parse_variable( &s, string, out ) ) { }
2255         else if ( s[ 0 ] == ':' || s[ 0 ] == '[' )
2256         {
2257             parse_error( "unbalanced parentheses" );
2258             ++s;
2259         }
2260         else if ( s[ 0 ] == '\0' )
2261         {
2262             parse_error( "unbalanced parentheses" );
2263             break;
2264         }
2265         else if ( s[ 0 ] == ')' )
2266         {
2267             ++s;
2268             if ( --depth == 0 ) break;
2269         }
2270         else if ( s[ 0 ] == '(' )
2271         {
2272             ++depth;
2273             ++s;
2274         }
2275         else
2276             ++s;
2277     }
2278     *s_ = s;
2279 }
2280 
2281 
2282 /*
2283  * Main compile.
2284  */
2285 
2286 #define RESULT_STACK 0
2287 #define RESULT_RETURN 1
2288 #define RESULT_NONE 2
2289 
2290 static void compile_parse( PARSE * parse, compiler * c, int result_location );
2291 static struct arg_list * arg_list_compile( PARSE * parse, int * num_arguments );
2292 
compile_condition(PARSE * parse,compiler * c,int branch_true,int label)2293 static void compile_condition( PARSE * parse, compiler * c, int branch_true, int label )
2294 {
2295     assert( parse->type == PARSE_EVAL );
2296     switch ( parse->num )
2297     {
2298         case EXPR_EXISTS:
2299             compile_parse( parse->left, c, RESULT_STACK );
2300             if ( branch_true )
2301                 compile_emit_branch( c, INSTR_JUMP_NOT_EMPTY, label );
2302             else
2303                 compile_emit_branch( c, INSTR_JUMP_EMPTY, label );
2304             break;
2305 
2306         case EXPR_EQUALS:
2307             compile_parse( parse->left, c, RESULT_STACK );
2308             compile_parse( parse->right, c, RESULT_STACK );
2309             if ( branch_true )
2310                 compile_emit_branch( c, INSTR_JUMP_EQ, label );
2311             else
2312                 compile_emit_branch( c, INSTR_JUMP_NE, label );
2313             break;
2314 
2315         case EXPR_NOTEQ:
2316             compile_parse( parse->left, c, RESULT_STACK );
2317             compile_parse( parse->right, c, RESULT_STACK );
2318             if ( branch_true )
2319                 compile_emit_branch( c, INSTR_JUMP_NE, label );
2320             else
2321                 compile_emit_branch( c, INSTR_JUMP_EQ, label );
2322             break;
2323 
2324         case EXPR_LESS:
2325             compile_parse( parse->left, c, RESULT_STACK );
2326             compile_parse( parse->right, c, RESULT_STACK );
2327             if ( branch_true )
2328                 compile_emit_branch( c, INSTR_JUMP_LT, label );
2329             else
2330                 compile_emit_branch( c, INSTR_JUMP_GE, label );
2331             break;
2332 
2333         case EXPR_LESSEQ:
2334             compile_parse( parse->left, c, RESULT_STACK );
2335             compile_parse( parse->right, c, RESULT_STACK );
2336             if ( branch_true )
2337                 compile_emit_branch( c, INSTR_JUMP_LE, label );
2338             else
2339                 compile_emit_branch( c, INSTR_JUMP_GT, label );
2340             break;
2341 
2342         case EXPR_MORE:
2343             compile_parse( parse->left, c, RESULT_STACK );
2344             compile_parse( parse->right, c, RESULT_STACK );
2345             if ( branch_true )
2346                 compile_emit_branch( c, INSTR_JUMP_GT, label );
2347             else
2348                 compile_emit_branch( c, INSTR_JUMP_LE, label );
2349             break;
2350 
2351         case EXPR_MOREEQ:
2352             compile_parse( parse->left, c, RESULT_STACK );
2353             compile_parse( parse->right, c, RESULT_STACK );
2354             if ( branch_true )
2355                 compile_emit_branch( c, INSTR_JUMP_GE, label );
2356             else
2357                 compile_emit_branch( c, INSTR_JUMP_LT, label );
2358             break;
2359 
2360         case EXPR_IN:
2361             compile_parse( parse->left, c, RESULT_STACK );
2362             compile_parse( parse->right, c, RESULT_STACK );
2363             if ( branch_true )
2364                 compile_emit_branch( c, INSTR_JUMP_IN, label );
2365             else
2366                 compile_emit_branch( c, INSTR_JUMP_NOT_IN, label );
2367             break;
2368 
2369         case EXPR_AND:
2370             if ( branch_true )
2371             {
2372                 int f = compile_new_label( c );
2373                 compile_condition( parse->left, c, 0, f );
2374                 compile_condition( parse->right, c, 1, label );
2375                 compile_set_label( c, f );
2376             }
2377             else
2378             {
2379                 compile_condition( parse->left, c, 0, label );
2380                 compile_condition( parse->right, c, 0, label );
2381             }
2382             break;
2383 
2384         case EXPR_OR:
2385             if ( branch_true )
2386             {
2387                 compile_condition( parse->left, c, 1, label );
2388                 compile_condition( parse->right, c, 1, label );
2389             }
2390             else
2391             {
2392                 int t = compile_new_label( c );
2393                 compile_condition( parse->left, c, 1, t );
2394                 compile_condition( parse->right, c, 0, label );
2395                 compile_set_label( c, t );
2396             }
2397             break;
2398 
2399         case EXPR_NOT:
2400             compile_condition( parse->left, c, !branch_true, label );
2401             break;
2402     }
2403 }
2404 
adjust_result(compiler * c,int actual_location,int desired_location)2405 static void adjust_result( compiler * c, int actual_location,
2406     int desired_location )
2407 {
2408     if ( actual_location == desired_location )
2409         ;
2410     else if ( actual_location == RESULT_STACK && desired_location == RESULT_RETURN )
2411         compile_emit( c, INSTR_SET_RESULT, 0 );
2412     else if ( actual_location == RESULT_STACK && desired_location == RESULT_NONE )
2413         compile_emit( c, INSTR_POP, 0 );
2414     else if ( actual_location == RESULT_RETURN && desired_location == RESULT_STACK )
2415         compile_emit( c, INSTR_PUSH_RESULT, 0 );
2416     else if ( actual_location == RESULT_RETURN && desired_location == RESULT_NONE )
2417         ;
2418     else if ( actual_location == RESULT_NONE && desired_location == RESULT_STACK )
2419         compile_emit( c, INSTR_PUSH_EMPTY, 0 );
2420     else if ( actual_location == RESULT_NONE && desired_location == RESULT_RETURN )
2421     {
2422         compile_emit( c, INSTR_PUSH_EMPTY, 0 );
2423         compile_emit( c, INSTR_SET_RESULT, 0 );
2424     }
2425     else
2426         assert( !"invalid result location" );
2427 }
2428 
compile_append_chain(PARSE * parse,compiler * c)2429 static void compile_append_chain( PARSE * parse, compiler * c )
2430 {
2431     assert( parse->type == PARSE_APPEND );
2432     if ( parse->left->type == PARSE_NULL )
2433         compile_parse( parse->right, c, RESULT_STACK );
2434     else
2435     {
2436         if ( parse->left->type == PARSE_APPEND )
2437             compile_append_chain( parse->left, c );
2438         else
2439             compile_parse( parse->left, c, RESULT_STACK );
2440         compile_parse( parse->right, c, RESULT_STACK );
2441         compile_emit( c, INSTR_PUSH_APPEND, 0 );
2442     }
2443 }
2444 
compile_emit_debug(compiler * c,int line)2445 static void compile_emit_debug(compiler * c, int line)
2446 {
2447 #ifdef JAM_DEBUGGER
2448     if ( debug_is_debugging() )
2449         compile_emit( c, INSTR_DEBUG_LINE, line );
2450 #endif
2451 }
2452 
compile_parse(PARSE * parse,compiler * c,int result_location)2453 static void compile_parse( PARSE * parse, compiler * c, int result_location )
2454 {
2455     compile_emit_debug(c, parse->line);
2456     if ( parse->type == PARSE_APPEND )
2457     {
2458         compile_append_chain( parse, c );
2459         adjust_result( c, RESULT_STACK, result_location );
2460     }
2461     else if ( parse->type == PARSE_EVAL )
2462     {
2463         /* FIXME: This is only needed because of the bizarre parsing of
2464          * conditions.
2465          */
2466         if ( parse->num == EXPR_EXISTS )
2467             compile_parse( parse->left, c, result_location );
2468         else
2469         {
2470             int f = compile_new_label( c );
2471             int end = compile_new_label( c );
2472 
2473             out_printf( "%s:%d: Conditional used as list (check operator "
2474                 "precedence).\n", object_str( parse->file ), parse->line );
2475 
2476             /* Emit the condition */
2477             compile_condition( parse, c, 0, f );
2478             compile_emit( c, INSTR_PUSH_CONSTANT, compile_emit_constant( c,
2479                 constant_true ) );
2480             compile_emit_branch( c, INSTR_JUMP, end );
2481             compile_set_label( c, f );
2482             compile_emit( c, INSTR_PUSH_EMPTY, 0 );
2483             compile_set_label( c, end );
2484             adjust_result( c, RESULT_STACK, result_location );
2485         }
2486     }
2487     else if ( parse->type == PARSE_FOREACH )
2488     {
2489         int var = compile_emit_constant( c, parse->string );
2490         int top = compile_new_label( c );
2491         int end = compile_new_label( c );
2492         int continue_ = compile_new_label( c );
2493 
2494         /*
2495          * Evaluate the list.
2496          */
2497         compile_parse( parse->left, c, RESULT_STACK );
2498 
2499         /* Localize the loop variable */
2500         if ( parse->num )
2501         {
2502             compile_emit( c, INSTR_PUSH_EMPTY, 0 );
2503             compile_emit( c, INSTR_PUSH_LOCAL, var );
2504             compile_emit( c, INSTR_SWAP, 1 );
2505             compile_push_cleanup( c, INSTR_POP_LOCAL, var );
2506         }
2507 
2508         compile_emit( c, INSTR_FOR_INIT, 0 );
2509         compile_set_label( c, top );
2510         compile_emit_branch( c, INSTR_FOR_LOOP, end );
2511         compile_emit_debug( c, parse->line );
2512         compile_emit( c, INSTR_SET, var );
2513 
2514         compile_push_break_scope( c, end );
2515         compile_push_cleanup( c, INSTR_FOR_POP, 0 );
2516         compile_push_continue_scope( c, continue_ );
2517 
2518         /* Run the loop body */
2519         compile_parse( parse->right, c, RESULT_NONE );
2520 
2521         compile_pop_continue_scope( c );
2522         compile_pop_cleanup( c );
2523         compile_pop_break_scope( c );
2524 
2525         compile_set_label( c, continue_ );
2526         compile_emit_branch( c, INSTR_JUMP, top );
2527         compile_set_label( c, end );
2528 
2529         if ( parse->num )
2530         {
2531             compile_pop_cleanup( c );
2532             compile_emit( c, INSTR_POP_LOCAL, var );
2533         }
2534 
2535         adjust_result( c, RESULT_NONE, result_location);
2536     }
2537     else if ( parse->type == PARSE_IF )
2538     {
2539         int f = compile_new_label( c );
2540         /* Emit the condition */
2541         compile_condition( parse->left, c, 0, f );
2542         /* Emit the if block */
2543         compile_parse( parse->right, c, result_location );
2544         if ( parse->third->type != PARSE_NULL || result_location != RESULT_NONE )
2545         {
2546             /* Emit the else block */
2547             int end = compile_new_label( c );
2548             compile_emit_branch( c, INSTR_JUMP, end );
2549             compile_set_label( c, f );
2550             compile_parse( parse->third, c, result_location );
2551             compile_set_label( c, end );
2552         }
2553         else
2554             compile_set_label( c, f );
2555 
2556     }
2557     else if ( parse->type == PARSE_WHILE )
2558     {
2559         int nested_result = result_location == RESULT_NONE
2560             ? RESULT_NONE
2561             : RESULT_RETURN;
2562         int test = compile_new_label( c );
2563         int top = compile_new_label( c );
2564         int end = compile_new_label( c );
2565         /* Make sure that we return an empty list if the loop runs zero times.
2566          */
2567         adjust_result( c, RESULT_NONE, nested_result );
2568         /* Jump to the loop test. */
2569         compile_emit_branch( c, INSTR_JUMP, test );
2570         compile_set_label( c, top );
2571         /* Emit the loop body. */
2572         compile_push_break_scope( c, end );
2573         compile_push_continue_scope( c, test );
2574         compile_parse( parse->right, c, nested_result );
2575         compile_pop_continue_scope( c );
2576         compile_pop_break_scope( c );
2577         /* Emit the condition. */
2578         compile_set_label( c, test );
2579         compile_condition( parse->left, c, 1, top );
2580         compile_set_label( c, end );
2581 
2582         adjust_result( c, nested_result, result_location );
2583     }
2584     else if ( parse->type == PARSE_INCLUDE )
2585     {
2586         compile_parse( parse->left, c, RESULT_STACK );
2587         compile_emit( c, INSTR_INCLUDE, 0 );
2588         compile_emit( c, INSTR_BIND_MODULE_VARIABLES, 0 );
2589         adjust_result( c, RESULT_NONE, result_location );
2590     }
2591     else if ( parse->type == PARSE_MODULE )
2592     {
2593         int const nested_result = result_location == RESULT_NONE
2594             ? RESULT_NONE
2595             : RESULT_RETURN;
2596         compile_parse( parse->left, c, RESULT_STACK );
2597         compile_emit( c, INSTR_PUSH_MODULE, 0 );
2598         compile_push_cleanup( c, INSTR_POP_MODULE, 0 );
2599         compile_parse( parse->right, c, nested_result );
2600         compile_pop_cleanup( c );
2601         compile_emit( c, INSTR_POP_MODULE, 0 );
2602         adjust_result( c, nested_result, result_location );
2603     }
2604     else if ( parse->type == PARSE_CLASS )
2605     {
2606         /* Evaluate the class name. */
2607         compile_parse( parse->left->right, c, RESULT_STACK );
2608         /* Evaluate the base classes. */
2609         if ( parse->left->left )
2610             compile_parse( parse->left->left->right, c, RESULT_STACK );
2611         else
2612             compile_emit( c, INSTR_PUSH_EMPTY, 0 );
2613         compile_emit( c, INSTR_CLASS, 0 );
2614         compile_push_cleanup( c, INSTR_POP_MODULE, 0 );
2615         compile_parse( parse->right, c, RESULT_NONE );
2616         compile_emit( c, INSTR_BIND_MODULE_VARIABLES, 0 );
2617         compile_pop_cleanup( c );
2618         compile_emit( c, INSTR_POP_MODULE, 0 );
2619 
2620         adjust_result( c, RESULT_NONE, result_location );
2621     }
2622     else if ( parse->type == PARSE_LIST )
2623     {
2624         OBJECT * const o = parse->string;
2625         char const * s = object_str( o );
2626         VAR_PARSE_GROUP * group;
2627         current_file = object_str( parse->file );
2628         current_line = parse->line;
2629         group = parse_expansion( &s );
2630         var_parse_group_compile( group, c );
2631         var_parse_group_free( group );
2632         adjust_result( c, RESULT_STACK, result_location );
2633     }
2634     else if ( parse->type == PARSE_LOCAL )
2635     {
2636         int nested_result = result_location == RESULT_NONE
2637             ? RESULT_NONE
2638             : RESULT_RETURN;
2639         /* This should be left recursive group of compile_appends. */
2640         PARSE * vars = parse->left;
2641 
2642         /* Special case an empty list of vars */
2643         if ( vars->type == PARSE_NULL )
2644         {
2645             compile_parse( parse->right, c, RESULT_NONE );
2646             compile_parse( parse->third, c, result_location );
2647             nested_result = result_location;
2648         }
2649         /* Check whether there is exactly one variable with a constant name. */
2650         else if ( vars->left->type == PARSE_NULL &&
2651             vars->right->type == PARSE_LIST )
2652         {
2653             char const * s = object_str( vars->right->string );
2654             VAR_PARSE_GROUP * group;
2655             current_file = object_str( parse->file );
2656             current_line = parse->line;
2657             group = parse_expansion( &s );
2658             if ( group->elems->size == 1 && dynamic_array_at( VAR_PARSE *,
2659                 group->elems, 0 )->type == VAR_PARSE_TYPE_STRING )
2660             {
2661                 int const name = compile_emit_constant( c, (
2662                     (VAR_PARSE_STRING *)dynamic_array_at( VAR_PARSE *,
2663                     group->elems, 0 ) )->s );
2664                 var_parse_group_free( group );
2665                 compile_parse( parse->right, c, RESULT_STACK );
2666                 compile_emit_debug(c, parse->line);
2667                 compile_emit( c, INSTR_PUSH_LOCAL, name );
2668                 compile_push_cleanup( c, INSTR_POP_LOCAL, name );
2669                 compile_parse( parse->third, c, nested_result );
2670                 compile_pop_cleanup( c );
2671                 compile_emit( c, INSTR_POP_LOCAL, name );
2672             }
2673             else
2674             {
2675                 var_parse_group_compile( group, c );
2676                 var_parse_group_free( group );
2677                 compile_parse( parse->right, c, RESULT_STACK );
2678                 compile_emit_debug(c, parse->line);
2679                 compile_emit( c, INSTR_PUSH_LOCAL_GROUP, 0 );
2680                 compile_push_cleanup( c, INSTR_POP_LOCAL_GROUP, 0 );
2681                 compile_parse( parse->third, c, nested_result );
2682                 compile_pop_cleanup( c );
2683                 compile_emit( c, INSTR_POP_LOCAL_GROUP, 0 );
2684             }
2685         }
2686         else
2687         {
2688             compile_parse( parse->left, c, RESULT_STACK );
2689             compile_parse( parse->right, c, RESULT_STACK );
2690             compile_emit_debug(c, parse->line);
2691             compile_emit( c, INSTR_PUSH_LOCAL_GROUP, 0 );
2692             compile_push_cleanup( c, INSTR_POP_LOCAL_GROUP, 0 );
2693             compile_parse( parse->third, c, nested_result );
2694             compile_pop_cleanup( c );
2695             compile_emit( c, INSTR_POP_LOCAL_GROUP, 0 );
2696         }
2697         adjust_result( c, nested_result, result_location );
2698     }
2699     else if ( parse->type == PARSE_ON )
2700     {
2701         if ( parse->right->type == PARSE_APPEND &&
2702             parse->right->left->type == PARSE_NULL &&
2703             parse->right->right->type == PARSE_LIST )
2704         {
2705             /* [ on $(target) return $(variable) ] */
2706             PARSE * value = parse->right->right;
2707             OBJECT * const o = value->string;
2708             char const * s = object_str( o );
2709             VAR_PARSE_GROUP * group;
2710             OBJECT * varname = 0;
2711             current_file = object_str( value->file );
2712             current_line = value->line;
2713             group = parse_expansion( &s );
2714             if ( group->elems->size == 1 )
2715             {
2716                 VAR_PARSE * one = dynamic_array_at( VAR_PARSE *, group->elems, 0 );
2717                 if ( one->type == VAR_PARSE_TYPE_VAR )
2718                 {
2719                     VAR_PARSE_VAR * var = ( VAR_PARSE_VAR * )one;
2720                     if ( var->modifiers->size == 0 && !var->subscript && var->name->elems->size == 1 )
2721                     {
2722                         VAR_PARSE * name = dynamic_array_at( VAR_PARSE *, var->name->elems, 0 );
2723                         if ( name->type == VAR_PARSE_TYPE_STRING )
2724                         {
2725                             varname = ( ( VAR_PARSE_STRING * )name )->s;
2726                         }
2727                     }
2728                 }
2729             }
2730             if ( varname )
2731             {
2732                 /* We have one variable with a fixed name and no modifiers. */
2733                 compile_parse( parse->left, c, RESULT_STACK );
2734                 compile_emit( c, INSTR_GET_ON, compile_emit_constant( c, varname ) );
2735             }
2736             else
2737             {
2738                 /* Too complex.  Fall back on push/pop. */
2739                 int end = compile_new_label( c );
2740                 compile_parse( parse->left, c, RESULT_STACK );
2741                 compile_emit_branch( c, INSTR_PUSH_ON, end );
2742                 compile_push_cleanup( c, INSTR_POP_ON, 0 );
2743                 var_parse_group_compile( group, c );
2744                 compile_pop_cleanup( c );
2745                 compile_emit( c, INSTR_POP_ON, 0 );
2746                 compile_set_label( c, end );
2747             }
2748             var_parse_group_free( group );
2749         }
2750         else
2751         {
2752             int end = compile_new_label( c );
2753             compile_parse( parse->left, c, RESULT_STACK );
2754             compile_emit_branch( c, INSTR_PUSH_ON, end );
2755             compile_push_cleanup( c, INSTR_POP_ON, 0 );
2756             compile_parse( parse->right, c, RESULT_STACK );
2757             compile_pop_cleanup( c );
2758             compile_emit( c, INSTR_POP_ON, 0 );
2759             compile_set_label( c, end );
2760         }
2761         adjust_result( c, RESULT_STACK, result_location );
2762     }
2763     else if ( parse->type == PARSE_RULE )
2764     {
2765         PARSE * p;
2766         int n = 0;
2767         VAR_PARSE_GROUP * group;
2768         char const * s = object_str( parse->string );
2769 
2770         if ( parse->left->left || parse->left->right->type != PARSE_NULL )
2771             for ( p = parse->left; p; p = p->left )
2772             {
2773                 compile_parse( p->right, c, RESULT_STACK );
2774                 ++n;
2775             }
2776 
2777         current_file = object_str( parse->file );
2778         current_line = parse->line;
2779         group = parse_expansion( &s );
2780 
2781         if ( group->elems->size == 2 &&
2782             dynamic_array_at( VAR_PARSE *, group->elems, 0 )->type == VAR_PARSE_TYPE_VAR &&
2783             dynamic_array_at( VAR_PARSE *, group->elems, 1 )->type == VAR_PARSE_TYPE_STRING &&
2784             ( object_str( ( (VAR_PARSE_STRING *)dynamic_array_at( VAR_PARSE *, group->elems, 1 ) )->s )[ 0 ] == '.' ) )
2785         {
2786             VAR_PARSE_STRING * access = (VAR_PARSE_STRING *)dynamic_array_at( VAR_PARSE *, group->elems, 1 );
2787             OBJECT * member = object_new( object_str( access->s ) + 1 );
2788             /* Emit the object */
2789             var_parse_var_compile( (VAR_PARSE_VAR *)dynamic_array_at( VAR_PARSE *, group->elems, 0 ), c );
2790             var_parse_group_free( group );
2791             compile_emit( c, INSTR_CALL_MEMBER_RULE, n );
2792             compile_emit( c, compile_emit_constant( c, member ), parse->line );
2793             object_free( member );
2794         }
2795         else
2796         {
2797             var_parse_group_compile( group, c );
2798             var_parse_group_free( group );
2799             compile_emit( c, INSTR_CALL_RULE, n );
2800             compile_emit( c, compile_emit_constant( c, parse->string ), parse->line );
2801         }
2802 
2803         adjust_result( c, RESULT_STACK, result_location );
2804     }
2805     else if ( parse->type == PARSE_RULES )
2806     {
2807         do compile_parse( parse->left, c, RESULT_NONE );
2808         while ( ( parse = parse->right )->type == PARSE_RULES );
2809         compile_parse( parse, c, result_location );
2810     }
2811     else if ( parse->type == PARSE_SET )
2812     {
2813         PARSE * vars = parse->left;
2814         unsigned int op_code;
2815         unsigned int op_code_group;
2816 
2817         switch ( parse->num )
2818         {
2819         case ASSIGN_APPEND: op_code = INSTR_APPEND; op_code_group = INSTR_APPEND_GROUP; break;
2820         case ASSIGN_DEFAULT: op_code = INSTR_DEFAULT; op_code_group = INSTR_DEFAULT_GROUP; break;
2821         default: op_code = INSTR_SET; op_code_group = INSTR_SET_GROUP; break;
2822         }
2823 
2824         /* Check whether there is exactly one variable with a constant name. */
2825         if ( vars->type == PARSE_LIST )
2826         {
2827             char const * s = object_str( vars->string );
2828             VAR_PARSE_GROUP * group;
2829             current_file = object_str( parse->file );
2830             current_line = parse->line;
2831             group = parse_expansion( &s );
2832             if ( group->elems->size == 1 && dynamic_array_at( VAR_PARSE *,
2833                 group->elems, 0 )->type == VAR_PARSE_TYPE_STRING )
2834             {
2835                 int const name = compile_emit_constant( c, (
2836                     (VAR_PARSE_STRING *)dynamic_array_at( VAR_PARSE *,
2837                     group->elems, 0 ) )->s );
2838                 var_parse_group_free( group );
2839                 compile_parse( parse->right, c, RESULT_STACK );
2840                 compile_emit_debug(c, parse->line);
2841                 if ( result_location != RESULT_NONE )
2842                 {
2843                     compile_emit( c, INSTR_SET_RESULT, 1 );
2844                 }
2845                 compile_emit( c, op_code, name );
2846             }
2847             else
2848             {
2849                 var_parse_group_compile( group, c );
2850                 var_parse_group_free( group );
2851                 compile_parse( parse->right, c, RESULT_STACK );
2852                 compile_emit_debug(c, parse->line);
2853                 if ( result_location != RESULT_NONE )
2854                 {
2855                     compile_emit( c, INSTR_SET_RESULT, 1 );
2856                 }
2857                 compile_emit( c, op_code_group, 0 );
2858             }
2859         }
2860         else
2861         {
2862             compile_parse( parse->left, c, RESULT_STACK );
2863             compile_parse( parse->right, c, RESULT_STACK );
2864             compile_emit_debug(c, parse->line);
2865             if ( result_location != RESULT_NONE )
2866             {
2867                 compile_emit( c, INSTR_SET_RESULT, 1 );
2868             }
2869             compile_emit( c, op_code_group, 0 );
2870         }
2871         if ( result_location != RESULT_NONE )
2872         {
2873             adjust_result( c, RESULT_RETURN, result_location );
2874         }
2875     }
2876     else if ( parse->type == PARSE_SETCOMP )
2877     {
2878         int n_args;
2879         struct arg_list * args = arg_list_compile( parse->right, &n_args );
2880         int const rule_id = compile_emit_rule( c, parse->string, parse->left,
2881             n_args, args, parse->num );
2882         compile_emit( c, INSTR_RULE, rule_id );
2883         adjust_result( c, RESULT_NONE, result_location );
2884     }
2885     else if ( parse->type == PARSE_SETEXEC )
2886     {
2887         int const actions_id = compile_emit_actions( c, parse );
2888         compile_parse( parse->left, c, RESULT_STACK );
2889         compile_emit( c, INSTR_ACTIONS, actions_id );
2890         adjust_result( c, RESULT_NONE, result_location );
2891     }
2892     else if ( parse->type == PARSE_SETTINGS )
2893     {
2894         compile_parse( parse->left, c, RESULT_STACK );
2895         compile_parse( parse->third, c, RESULT_STACK );
2896         compile_parse( parse->right, c, RESULT_STACK );
2897 
2898         compile_emit_debug(c, parse->line);
2899         switch ( parse->num )
2900         {
2901             case ASSIGN_APPEND: compile_emit( c, INSTR_APPEND_ON, 0 ); break;
2902             case ASSIGN_DEFAULT: compile_emit( c, INSTR_DEFAULT_ON, 0 ); break;
2903             default: compile_emit( c, INSTR_SET_ON, 0 ); break;
2904         }
2905 
2906         adjust_result( c, RESULT_STACK, result_location );
2907     }
2908     else if ( parse->type == PARSE_SWITCH )
2909     {
2910         int const switch_end = compile_new_label( c );
2911         compile_parse( parse->left, c, RESULT_STACK );
2912 
2913         for ( parse = parse->right; parse; parse = parse->right )
2914         {
2915             int const id = compile_emit_constant( c, parse->left->string );
2916             int const next_case = compile_new_label( c );
2917             compile_emit( c, INSTR_PUSH_CONSTANT, id );
2918             compile_emit_branch( c, INSTR_JUMP_NOT_GLOB, next_case );
2919             compile_parse( parse->left->left, c, result_location );
2920             compile_emit_branch( c, INSTR_JUMP, switch_end );
2921             compile_set_label( c, next_case );
2922         }
2923         compile_emit( c, INSTR_POP, 0 );
2924         adjust_result( c, RESULT_NONE, result_location );
2925         compile_set_label( c, switch_end );
2926     }
2927     else if ( parse->type == PARSE_RETURN )
2928     {
2929         compile_parse( parse->left, c, RESULT_RETURN );
2930         compile_emit_cleanups( c, 0 );
2931         compile_emit( c, INSTR_RETURN, 0 ); /* 0 for return in the middle of a function. */
2932     }
2933     else if ( parse->type == PARSE_BREAK )
2934     {
2935         compile_emit_loop_jump( c, LOOP_INFO_BREAK );
2936     }
2937     else if ( parse->type == PARSE_CONTINUE )
2938     {
2939         compile_emit_loop_jump( c, LOOP_INFO_CONTINUE );
2940     }
2941     else if ( parse->type == PARSE_NULL )
2942         adjust_result( c, RESULT_NONE, result_location );
2943     else
2944         assert( !"unknown PARSE type." );
2945 }
2946 
function_rulename(FUNCTION * function)2947 OBJECT * function_rulename( FUNCTION * function )
2948 {
2949     return function->rulename;
2950 }
2951 
function_set_rulename(FUNCTION * function,OBJECT * rulename)2952 void function_set_rulename( FUNCTION * function, OBJECT * rulename )
2953 {
2954     function->rulename = rulename;
2955 }
2956 
function_location(FUNCTION * function_,OBJECT ** file,int * line)2957 void function_location( FUNCTION * function_, OBJECT * * file, int * line )
2958 {
2959     if ( function_->type == FUNCTION_BUILTIN )
2960     {
2961         *file = constant_builtin;
2962         *line = -1;
2963     }
2964 #ifdef HAVE_PYTHON
2965     if ( function_->type == FUNCTION_PYTHON )
2966     {
2967         *file = constant_builtin;
2968         *line = -1;
2969     }
2970 #endif
2971     else
2972     {
2973         JAM_FUNCTION * function = (JAM_FUNCTION *)function_;
2974         assert( function_->type == FUNCTION_JAM );
2975         *file = function->file;
2976         *line = function->line;
2977     }
2978 }
2979 
2980 static struct arg_list * arg_list_compile_builtin( char const * * args,
2981     int * num_arguments );
2982 
function_builtin(LIST * (* func)(FRAME * frame,int flags),int flags,char const ** args)2983 FUNCTION * function_builtin( LIST * ( * func )( FRAME * frame, int flags ),
2984     int flags, char const * * args )
2985 {
2986     BUILTIN_FUNCTION * result = (BUILTIN_FUNCTION*)BJAM_MALLOC( sizeof( BUILTIN_FUNCTION ) );
2987     result->base.type = FUNCTION_BUILTIN;
2988     result->base.reference_count = 1;
2989     result->base.rulename = 0;
2990     result->base.formal_arguments = arg_list_compile_builtin( args,
2991         &result->base.num_formal_arguments );
2992     result->func = func;
2993     result->flags = flags;
2994     return (FUNCTION *)result;
2995 }
2996 
function_compile(PARSE * parse)2997 FUNCTION * function_compile( PARSE * parse )
2998 {
2999     compiler c[ 1 ];
3000     JAM_FUNCTION * result;
3001     compiler_init( c );
3002     compile_parse( parse, c, RESULT_RETURN );
3003     compile_emit( c, INSTR_RETURN, 1 );
3004     result = compile_to_function( c );
3005     compiler_free( c );
3006     result->file = object_copy( parse->file );
3007     result->line = parse->line;
3008     return (FUNCTION *)result;
3009 }
3010 
function_compile_actions(char const * actions,OBJECT * file,int line)3011 FUNCTION * function_compile_actions( char const * actions, OBJECT * file,
3012     int line )
3013 {
3014     compiler c[ 1 ];
3015     JAM_FUNCTION * result;
3016     VAR_PARSE_ACTIONS * parse;
3017     current_file = object_str( file );
3018     current_line = line;
3019     parse = parse_actions( actions );
3020     compiler_init( c );
3021     var_parse_actions_compile( parse, c );
3022     var_parse_actions_free( parse );
3023     compile_emit( c, INSTR_RETURN, 1 );
3024     result = compile_to_function( c );
3025     compiler_free( c );
3026     result->file = object_copy( file );
3027     result->line = line;
3028     return (FUNCTION *)result;
3029 }
3030 
3031 static void argument_list_print( struct arg_list * args, int num_args );
3032 
3033 
3034 /* Define delimiters for type check elements in argument lists (and return type
3035  * specifications, eventually).
3036  */
3037 # define TYPE_OPEN_DELIM '['
3038 # define TYPE_CLOSE_DELIM ']'
3039 
3040 /*
3041  * is_type_name() - true iff the given string represents a type check
3042  * specification.
3043  */
3044 
is_type_name(char const * s)3045 int is_type_name( char const * s )
3046 {
3047     return s[ 0 ] == TYPE_OPEN_DELIM && s[ strlen( s ) - 1 ] ==
3048         TYPE_CLOSE_DELIM;
3049 }
3050 
argument_error(char const * message,FUNCTION * procedure,FRAME * frame,OBJECT * arg)3051 static void argument_error( char const * message, FUNCTION * procedure,
3052     FRAME * frame, OBJECT * arg )
3053 {
3054     extern void print_source_line( FRAME * );
3055     LOL * actual = frame->args;
3056     backtrace_line( frame->prev );
3057     out_printf( "*** argument error\n* rule %s ( ", frame->rulename );
3058     argument_list_print( procedure->formal_arguments,
3059         procedure->num_formal_arguments );
3060     out_printf( " )\n* called with: ( " );
3061     lol_print( actual );
3062     out_printf( " )\n* %s %s\n", message, arg ? object_str ( arg ) : "" );
3063     function_location( procedure, &frame->file, &frame->line );
3064     print_source_line( frame );
3065     out_printf( "see definition of rule '%s' being called\n", frame->rulename );
3066     backtrace( frame->prev );
3067     exit( EXITBAD );
3068 }
3069 
type_check_range(OBJECT * type_name,LISTITER iter,LISTITER end,FRAME * caller,FUNCTION * called,OBJECT * arg_name)3070 static void type_check_range( OBJECT * type_name, LISTITER iter, LISTITER end,
3071     FRAME * caller, FUNCTION * called, OBJECT * arg_name )
3072 {
3073     static module_t * typecheck = 0;
3074 
3075     /* If nothing to check, bail now. */
3076     if ( iter == end || !type_name )
3077         return;
3078 
3079     if ( !typecheck )
3080         typecheck = bindmodule( constant_typecheck );
3081 
3082     /* If the checking rule can not be found, also bail. */
3083     if ( !typecheck->rules || !hash_find( typecheck->rules, type_name ) )
3084         return;
3085 
3086     for ( ; iter != end; iter = list_next( iter ) )
3087     {
3088         LIST * error;
3089         FRAME frame[ 1 ];
3090         frame_init( frame );
3091         frame->module = typecheck;
3092         frame->prev = caller;
3093         frame->prev_user = caller->module->user_module
3094             ? caller
3095             : caller->prev_user;
3096 
3097         /* Prepare the argument list */
3098         lol_add( frame->args, list_new( object_copy( list_item( iter ) ) ) );
3099         error = evaluate_rule( bindrule( type_name, frame->module ), type_name, frame );
3100 
3101         if ( !list_empty( error ) )
3102             argument_error( object_str( list_front( error ) ), called, caller,
3103                 arg_name );
3104 
3105         frame_free( frame );
3106     }
3107 }
3108 
type_check(OBJECT * type_name,LIST * values,FRAME * caller,FUNCTION * called,OBJECT * arg_name)3109 static void type_check( OBJECT * type_name, LIST * values, FRAME * caller,
3110     FUNCTION * called, OBJECT * arg_name )
3111 {
3112     type_check_range( type_name, list_begin( values ), list_end( values ),
3113         caller, called, arg_name );
3114 }
3115 
argument_list_check(struct arg_list * formal,int formal_count,FUNCTION * function,FRAME * frame)3116 void argument_list_check( struct arg_list * formal, int formal_count,
3117     FUNCTION * function, FRAME * frame )
3118 {
3119     LOL * all_actual = frame->args;
3120     int i;
3121 
3122     for ( i = 0; i < formal_count; ++i )
3123     {
3124         LIST * actual = lol_get( all_actual, i );
3125         LISTITER actual_iter = list_begin( actual );
3126         LISTITER const actual_end = list_end( actual );
3127         int j;
3128         for ( j = 0; j < formal[ i ].size; ++j )
3129         {
3130             struct argument * formal_arg = &formal[ i ].args[ j ];
3131 
3132             switch ( formal_arg->flags )
3133             {
3134             case ARG_ONE:
3135                 if ( actual_iter == actual_end )
3136                     argument_error( "missing argument", function, frame,
3137                         formal_arg->arg_name );
3138                 type_check_range( formal_arg->type_name, actual_iter,
3139                     list_next( actual_iter ), frame, function,
3140                     formal_arg->arg_name );
3141                 actual_iter = list_next( actual_iter );
3142                 break;
3143             case ARG_OPTIONAL:
3144                 if ( actual_iter != actual_end )
3145                 {
3146                     type_check_range( formal_arg->type_name, actual_iter,
3147                         list_next( actual_iter ), frame, function,
3148                         formal_arg->arg_name );
3149                     actual_iter = list_next( actual_iter );
3150                 }
3151                 break;
3152             case ARG_PLUS:
3153                 if ( actual_iter == actual_end )
3154                     argument_error( "missing argument", function, frame,
3155                         formal_arg->arg_name );
3156                 /* fallthrough */
3157             case ARG_STAR:
3158                 type_check_range( formal_arg->type_name, actual_iter,
3159                     actual_end, frame, function, formal_arg->arg_name );
3160                 actual_iter = actual_end;
3161                 break;
3162             case ARG_VARIADIC:
3163                 return;
3164             }
3165         }
3166 
3167         if ( actual_iter != actual_end )
3168             argument_error( "extra argument", function, frame, list_item(
3169                 actual_iter ) );
3170     }
3171 
3172     for ( ; i < all_actual->count; ++i )
3173     {
3174         LIST * actual = lol_get( all_actual, i );
3175         if ( !list_empty( actual ) )
3176             argument_error( "extra argument", function, frame, list_front(
3177                 actual ) );
3178     }
3179 }
3180 
argument_list_push(struct arg_list * formal,int formal_count,FUNCTION * function,FRAME * frame,STACK * s)3181 void argument_list_push( struct arg_list * formal, int formal_count,
3182     FUNCTION * function, FRAME * frame, STACK * s )
3183 {
3184     LOL * all_actual = frame->args;
3185     int i;
3186 
3187     for ( i = 0; i < formal_count; ++i )
3188     {
3189         LIST * actual = lol_get( all_actual, i );
3190         LISTITER actual_iter = list_begin( actual );
3191         LISTITER const actual_end = list_end( actual );
3192         int j;
3193         for ( j = 0; j < formal[ i ].size; ++j )
3194         {
3195             struct argument * formal_arg = &formal[ i ].args[ j ];
3196             LIST * value;
3197 
3198             switch ( formal_arg->flags )
3199             {
3200             case ARG_ONE:
3201                 if ( actual_iter == actual_end )
3202                     argument_error( "missing argument", function, frame,
3203                         formal_arg->arg_name );
3204                 value = list_new( object_copy( list_item( actual_iter ) ) );
3205                 actual_iter = list_next( actual_iter );
3206                 break;
3207             case ARG_OPTIONAL:
3208                 if ( actual_iter == actual_end )
3209                     value = L0;
3210                 else
3211                 {
3212                     value = list_new( object_copy( list_item( actual_iter ) ) );
3213                     actual_iter = list_next( actual_iter );
3214                 }
3215                 break;
3216             case ARG_PLUS:
3217                 if ( actual_iter == actual_end )
3218                     argument_error( "missing argument", function, frame,
3219                         formal_arg->arg_name );
3220                 /* fallthrough */
3221             case ARG_STAR:
3222                 value = list_copy_range( actual, actual_iter, actual_end );
3223                 actual_iter = actual_end;
3224                 break;
3225             case ARG_VARIADIC:
3226                 return;
3227             }
3228 
3229             type_check( formal_arg->type_name, value, frame, function,
3230                 formal_arg->arg_name );
3231 
3232             if ( formal_arg->index != -1 )
3233             {
3234                 LIST * * const old = &frame->module->fixed_variables[
3235                     formal_arg->index ];
3236                 stack_push( s, *old );
3237                 *old = value;
3238             }
3239             else
3240                 stack_push( s, var_swap( frame->module, formal_arg->arg_name,
3241                     value ) );
3242         }
3243 
3244         if ( actual_iter != actual_end )
3245             argument_error( "extra argument", function, frame, list_item(
3246                 actual_iter ) );
3247     }
3248 
3249     for ( ; i < all_actual->count; ++i )
3250     {
3251         LIST * const actual = lol_get( all_actual, i );
3252         if ( !list_empty( actual ) )
3253             argument_error( "extra argument", function, frame, list_front(
3254                 actual ) );
3255     }
3256 }
3257 
argument_list_pop(struct arg_list * formal,int formal_count,FRAME * frame,STACK * s)3258 void argument_list_pop( struct arg_list * formal, int formal_count,
3259     FRAME * frame, STACK * s )
3260 {
3261     int i;
3262     for ( i = formal_count - 1; i >= 0; --i )
3263     {
3264         int j;
3265         for ( j = formal[ i ].size - 1; j >= 0 ; --j )
3266         {
3267             struct argument * formal_arg = &formal[ i ].args[ j ];
3268 
3269             if ( formal_arg->flags == ARG_VARIADIC )
3270                 continue;
3271             if ( formal_arg->index != -1 )
3272             {
3273                 LIST * const old = stack_pop( s );
3274                 LIST * * const pos = &frame->module->fixed_variables[
3275                     formal_arg->index ];
3276                 list_free( *pos );
3277                 *pos = old;
3278             }
3279             else
3280                 var_set( frame->module, formal_arg->arg_name, stack_pop( s ),
3281                     VAR_SET );
3282         }
3283     }
3284 }
3285 
3286 
3287 struct argument_compiler
3288 {
3289     struct dynamic_array args[ 1 ];
3290     struct argument arg;
3291     int state;
3292 #define ARGUMENT_COMPILER_START         0
3293 #define ARGUMENT_COMPILER_FOUND_TYPE    1
3294 #define ARGUMENT_COMPILER_FOUND_OBJECT  2
3295 #define ARGUMENT_COMPILER_DONE          3
3296 };
3297 
3298 
argument_compiler_init(struct argument_compiler * c)3299 static void argument_compiler_init( struct argument_compiler * c )
3300 {
3301     dynamic_array_init( c->args );
3302     c->state = ARGUMENT_COMPILER_START;
3303 }
3304 
argument_compiler_free(struct argument_compiler * c)3305 static void argument_compiler_free( struct argument_compiler * c )
3306 {
3307     dynamic_array_free( c->args );
3308 }
3309 
argument_compiler_add(struct argument_compiler * c,OBJECT * arg,OBJECT * file,int line)3310 static void argument_compiler_add( struct argument_compiler * c, OBJECT * arg,
3311     OBJECT * file, int line )
3312 {
3313     switch ( c->state )
3314     {
3315     case ARGUMENT_COMPILER_FOUND_OBJECT:
3316 
3317         if ( object_equal( arg, constant_question_mark ) )
3318         {
3319             c->arg.flags = ARG_OPTIONAL;
3320         }
3321         else if ( object_equal( arg, constant_plus ) )
3322         {
3323             c->arg.flags = ARG_PLUS;
3324         }
3325         else if ( object_equal( arg, constant_star ) )
3326         {
3327             c->arg.flags = ARG_STAR;
3328         }
3329 
3330         dynamic_array_push( c->args, c->arg );
3331         c->state = ARGUMENT_COMPILER_START;
3332 
3333         if ( c->arg.flags != ARG_ONE )
3334             break;
3335         /* fall-through */
3336 
3337     case ARGUMENT_COMPILER_START:
3338 
3339         c->arg.type_name = 0;
3340         c->arg.index = -1;
3341         c->arg.flags = ARG_ONE;
3342 
3343         if ( is_type_name( object_str( arg ) ) )
3344         {
3345             c->arg.type_name = object_copy( arg );
3346             c->state = ARGUMENT_COMPILER_FOUND_TYPE;
3347             break;
3348         }
3349         /* fall-through */
3350 
3351     case ARGUMENT_COMPILER_FOUND_TYPE:
3352 
3353         if ( is_type_name( object_str( arg ) ) )
3354         {
3355             err_printf( "%s:%d: missing argument name before type name: %s\n",
3356                 object_str( file ), line, object_str( arg ) );
3357             exit( EXITBAD );
3358         }
3359 
3360         c->arg.arg_name = object_copy( arg );
3361         if ( object_equal( arg, constant_star ) )
3362         {
3363             c->arg.flags = ARG_VARIADIC;
3364             dynamic_array_push( c->args, c->arg );
3365             c->state = ARGUMENT_COMPILER_DONE;
3366         }
3367         else
3368         {
3369             c->state = ARGUMENT_COMPILER_FOUND_OBJECT;
3370         }
3371         break;
3372 
3373     case ARGUMENT_COMPILER_DONE:
3374         break;
3375     }
3376 }
3377 
argument_compiler_recurse(struct argument_compiler * c,PARSE * parse)3378 static void argument_compiler_recurse( struct argument_compiler * c,
3379     PARSE * parse )
3380 {
3381     if ( parse->type == PARSE_APPEND )
3382     {
3383         argument_compiler_recurse( c, parse->left );
3384         argument_compiler_recurse( c, parse->right );
3385     }
3386     else if ( parse->type != PARSE_NULL )
3387     {
3388         assert( parse->type == PARSE_LIST );
3389         argument_compiler_add( c, parse->string, parse->file, parse->line );
3390     }
3391 }
3392 
arg_compile_impl(struct argument_compiler * c,OBJECT * file,int line)3393 static struct arg_list arg_compile_impl( struct argument_compiler * c,
3394     OBJECT * file, int line )
3395 {
3396     struct arg_list result;
3397     switch ( c->state )
3398     {
3399     case ARGUMENT_COMPILER_START:
3400     case ARGUMENT_COMPILER_DONE:
3401         break;
3402     case ARGUMENT_COMPILER_FOUND_TYPE:
3403         err_printf( "%s:%d: missing argument name after type name: %s\n",
3404             object_str( file ), line, object_str( c->arg.type_name ) );
3405         exit( EXITBAD );
3406     case ARGUMENT_COMPILER_FOUND_OBJECT:
3407         dynamic_array_push( c->args, c->arg );
3408         break;
3409     }
3410     result.size = c->args->size;
3411     result.args = (struct argument*)BJAM_MALLOC( c->args->size * sizeof( struct argument ) );
3412     if ( c->args->size != 0 )
3413         memcpy( result.args, c->args->data,
3414                 c->args->size * sizeof( struct argument ) );
3415     return result;
3416 }
3417 
arg_compile(PARSE * parse)3418 static struct arg_list arg_compile( PARSE * parse )
3419 {
3420     struct argument_compiler c[ 1 ];
3421     struct arg_list result;
3422     argument_compiler_init( c );
3423     argument_compiler_recurse( c, parse );
3424     result = arg_compile_impl( c, parse->file, parse->line );
3425     argument_compiler_free( c );
3426     return result;
3427 }
3428 
3429 struct argument_list_compiler
3430 {
3431     struct dynamic_array args[ 1 ];
3432 };
3433 
argument_list_compiler_init(struct argument_list_compiler * c)3434 static void argument_list_compiler_init( struct argument_list_compiler * c )
3435 {
3436     dynamic_array_init( c->args );
3437 }
3438 
argument_list_compiler_free(struct argument_list_compiler * c)3439 static void argument_list_compiler_free( struct argument_list_compiler * c )
3440 {
3441     dynamic_array_free( c->args );
3442 }
3443 
argument_list_compiler_add(struct argument_list_compiler * c,PARSE * parse)3444 static void argument_list_compiler_add( struct argument_list_compiler * c,
3445     PARSE * parse )
3446 {
3447     struct arg_list args = arg_compile( parse );
3448     dynamic_array_push( c->args, args );
3449 }
3450 
argument_list_compiler_recurse(struct argument_list_compiler * c,PARSE * parse)3451 static void argument_list_compiler_recurse( struct argument_list_compiler * c,
3452     PARSE * parse )
3453 {
3454     if ( parse )
3455     {
3456         argument_list_compiler_add( c, parse->right );
3457         argument_list_compiler_recurse( c, parse->left );
3458     }
3459 }
3460 
arg_list_compile(PARSE * parse,int * num_arguments)3461 static struct arg_list * arg_list_compile( PARSE * parse, int * num_arguments )
3462 {
3463     if ( parse )
3464     {
3465         struct argument_list_compiler c[ 1 ];
3466         struct arg_list * result;
3467         argument_list_compiler_init( c );
3468         argument_list_compiler_recurse( c, parse );
3469         *num_arguments = c->args->size;
3470         result = (struct arg_list*)BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
3471         memcpy( result, c->args->data, c->args->size * sizeof( struct arg_list )
3472             );
3473         argument_list_compiler_free( c );
3474         return result;
3475     }
3476     *num_arguments = 0;
3477     return 0;
3478 }
3479 
arg_list_compile_builtin(char const ** args,int * num_arguments)3480 static struct arg_list * arg_list_compile_builtin( char const * * args,
3481     int * num_arguments )
3482 {
3483     if ( args )
3484     {
3485         struct argument_list_compiler c[ 1 ];
3486         struct arg_list * result;
3487         argument_list_compiler_init( c );
3488         while ( *args )
3489         {
3490             struct argument_compiler arg_comp[ 1 ];
3491             struct arg_list arg;
3492             argument_compiler_init( arg_comp );
3493             for ( ; *args; ++args )
3494             {
3495                 OBJECT * token;
3496                 if ( strcmp( *args, ":" ) == 0 )
3497                 {
3498                     ++args;
3499                     break;
3500                 }
3501                 token = object_new( *args );
3502                 argument_compiler_add( arg_comp, token, constant_builtin, -1 );
3503                 object_free( token );
3504             }
3505             arg = arg_compile_impl( arg_comp, constant_builtin, -1 );
3506             dynamic_array_push( c->args, arg );
3507             argument_compiler_free( arg_comp );
3508         }
3509         *num_arguments = c->args->size;
3510         result = (struct arg_list *)BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
3511         if ( c->args->size != 0 )
3512             memcpy( result, c->args->data,
3513                     c->args->size * sizeof( struct arg_list ) );
3514         argument_list_compiler_free( c );
3515         return result;
3516     }
3517     *num_arguments = 0;
3518     return 0;
3519 }
3520 
argument_list_print(struct arg_list * args,int num_args)3521 static void argument_list_print( struct arg_list * args, int num_args )
3522 {
3523     if ( args )
3524     {
3525         int i;
3526         for ( i = 0; i < num_args; ++i )
3527         {
3528             int j;
3529             if ( i ) out_printf( " : " );
3530             for ( j = 0; j < args[ i ].size; ++j )
3531             {
3532                 struct argument * formal_arg = &args[ i ].args[ j ];
3533                 if ( j ) out_printf( " " );
3534                 if ( formal_arg->type_name )
3535                     out_printf( "%s ", object_str( formal_arg->type_name ) );
3536                 out_printf( "%s", object_str( formal_arg->arg_name ) );
3537                 switch ( formal_arg->flags )
3538                 {
3539                 case ARG_OPTIONAL: out_printf( " ?" ); break;
3540                 case ARG_PLUS:     out_printf( " +" ); break;
3541                 case ARG_STAR:     out_printf( " *" ); break;
3542                 }
3543             }
3544         }
3545     }
3546 }
3547 
3548 
argument_list_bind_variables(struct arg_list * formal,int formal_count,module_t * module,int * counter)3549 struct arg_list * argument_list_bind_variables( struct arg_list * formal,
3550     int formal_count, module_t * module, int * counter )
3551 {
3552     if ( formal )
3553     {
3554         struct arg_list * result = (struct arg_list *)BJAM_MALLOC( sizeof(
3555             struct arg_list ) * formal_count );
3556         int i;
3557 
3558         for ( i = 0; i < formal_count; ++i )
3559         {
3560             int j;
3561             struct argument * args = (struct argument *)BJAM_MALLOC( sizeof(
3562                 struct argument ) * formal[ i ].size );
3563             for ( j = 0; j < formal[ i ].size; ++j )
3564             {
3565                 args[ j ] = formal[ i ].args[ j ];
3566                 if ( args[ j ].type_name )
3567                     args[ j ].type_name = object_copy( args[ j ].type_name );
3568                 args[ j ].arg_name = object_copy( args[ j ].arg_name );
3569                 if ( args[ j ].flags != ARG_VARIADIC )
3570                     args[ j ].index = module_add_fixed_var( module,
3571                         args[ j ].arg_name, counter );
3572             }
3573             result[ i ].args = args;
3574             result[ i ].size = formal[ i ].size;
3575         }
3576 
3577         return result;
3578     }
3579     return 0;
3580 }
3581 
3582 
argument_list_free(struct arg_list * args,int args_count)3583 void argument_list_free( struct arg_list * args, int args_count )
3584 {
3585     int i;
3586     for ( i = 0; i < args_count; ++i )
3587     {
3588         int j;
3589         for ( j = 0; j < args[ i ].size; ++j )
3590         {
3591             if ( args[ i ].args[ j ].type_name  )
3592                 object_free( args[ i ].args[ j ].type_name );
3593             object_free( args[ i ].args[ j ].arg_name );
3594         }
3595         BJAM_FREE( args[ i ].args );
3596     }
3597     BJAM_FREE( args );
3598 }
3599 
3600 
function_unbind_variables(FUNCTION * f)3601 FUNCTION * function_unbind_variables( FUNCTION * f )
3602 {
3603     if ( f->type == FUNCTION_JAM )
3604     {
3605         JAM_FUNCTION * const func = (JAM_FUNCTION *)f;
3606         return func->generic ? func->generic : f;
3607     }
3608 #ifdef HAVE_PYTHON
3609     if ( f->type == FUNCTION_PYTHON )
3610         return f;
3611 #endif
3612     assert( f->type == FUNCTION_BUILTIN );
3613     return f;
3614 }
3615 
function_bind_variables(FUNCTION * f,module_t * module,int * counter)3616 FUNCTION * function_bind_variables( FUNCTION * f, module_t * module,
3617     int * counter )
3618 {
3619     if ( f->type == FUNCTION_BUILTIN )
3620         return f;
3621 #ifdef HAVE_PYTHON
3622     if ( f->type == FUNCTION_PYTHON )
3623         return f;
3624 #endif
3625     {
3626         JAM_FUNCTION * func = (JAM_FUNCTION *)f;
3627         JAM_FUNCTION * new_func = (JAM_FUNCTION *)BJAM_MALLOC( sizeof( JAM_FUNCTION ) );
3628         instruction * code;
3629         int i;
3630         assert( f->type == FUNCTION_JAM );
3631         memcpy( new_func, func, sizeof( JAM_FUNCTION ) );
3632         new_func->base.reference_count = 1;
3633         new_func->base.formal_arguments = argument_list_bind_variables(
3634             f->formal_arguments, f->num_formal_arguments, module, counter );
3635         new_func->code = (instruction *)BJAM_MALLOC( func->code_size * sizeof( instruction ) );
3636         memcpy( new_func->code, func->code, func->code_size * sizeof(
3637             instruction ) );
3638         new_func->generic = (FUNCTION *)func;
3639         func = new_func;
3640         for ( i = 0; ; ++i )
3641         {
3642             OBJECT * key;
3643             int op_code;
3644             code = func->code + i;
3645             switch ( code->op_code )
3646             {
3647             case INSTR_PUSH_VAR: op_code = INSTR_PUSH_VAR_FIXED; break;
3648             case INSTR_PUSH_LOCAL: op_code = INSTR_PUSH_LOCAL_FIXED; break;
3649             case INSTR_POP_LOCAL: op_code = INSTR_POP_LOCAL_FIXED; break;
3650             case INSTR_SET: op_code = INSTR_SET_FIXED; break;
3651             case INSTR_APPEND: op_code = INSTR_APPEND_FIXED; break;
3652             case INSTR_DEFAULT: op_code = INSTR_DEFAULT_FIXED; break;
3653             case INSTR_RETURN:
3654                 if( code->arg == 1 ) return (FUNCTION *)new_func;
3655                 else continue;
3656             case INSTR_CALL_MEMBER_RULE:
3657             case INSTR_CALL_RULE: ++i; continue;
3658             case INSTR_PUSH_MODULE:
3659                 {
3660                     int depth = 1;
3661                     ++i;
3662                     while ( depth > 0 )
3663                     {
3664                         code = func->code + i;
3665                         switch ( code->op_code )
3666                         {
3667                         case INSTR_PUSH_MODULE:
3668                         case INSTR_CLASS:
3669                             ++depth;
3670                             break;
3671                         case INSTR_POP_MODULE:
3672                             --depth;
3673                             break;
3674                         case INSTR_CALL_RULE:
3675                             ++i;
3676                             break;
3677                         }
3678                         ++i;
3679                     }
3680                     --i;
3681                 }
3682             default: continue;
3683             }
3684             key = func->constants[ code->arg ];
3685             if ( !( object_equal( key, constant_TMPDIR ) ||
3686                     object_equal( key, constant_TMPNAME ) ||
3687                     object_equal( key, constant_TMPFILE ) ||
3688                     object_equal( key, constant_STDOUT ) ||
3689                     object_equal( key, constant_STDERR ) ) )
3690             {
3691                 code->op_code = op_code;
3692                 code->arg = module_add_fixed_var( module, key, counter );
3693             }
3694         }
3695     }
3696 }
3697 
function_get_variables(FUNCTION * f)3698 LIST * function_get_variables( FUNCTION * f )
3699 {
3700     if ( f->type == FUNCTION_BUILTIN )
3701         return L0;
3702 #ifdef HAVE_PYTHON
3703     if ( f->type == FUNCTION_PYTHON )
3704         return L0;
3705 #endif
3706     {
3707         JAM_FUNCTION * func = (JAM_FUNCTION *)f;
3708         LIST * result = L0;
3709         instruction * code;
3710         int i;
3711         assert( f->type == FUNCTION_JAM );
3712         if ( func->generic ) func = ( JAM_FUNCTION * )func->generic;
3713 
3714         for ( i = 0; ; ++i )
3715         {
3716             OBJECT * var;
3717             code = func->code + i;
3718             switch ( code->op_code )
3719             {
3720             case INSTR_PUSH_LOCAL: break;
3721             case INSTR_RETURN: return result;
3722             case INSTR_CALL_MEMBER_RULE:
3723             case INSTR_CALL_RULE: ++i; continue;
3724             case INSTR_PUSH_MODULE:
3725                 {
3726                     int depth = 1;
3727                     ++i;
3728                     while ( depth > 0 )
3729                     {
3730                         code = func->code + i;
3731                         switch ( code->op_code )
3732                         {
3733                         case INSTR_PUSH_MODULE:
3734                         case INSTR_CLASS:
3735                             ++depth;
3736                             break;
3737                         case INSTR_POP_MODULE:
3738                             --depth;
3739                             break;
3740                         case INSTR_CALL_RULE:
3741                             ++i;
3742                             break;
3743                         }
3744                         ++i;
3745                     }
3746                     --i;
3747                 }
3748             default: continue;
3749             }
3750             var = func->constants[ code->arg ];
3751             if ( !( object_equal( var, constant_TMPDIR ) ||
3752                     object_equal( var, constant_TMPNAME ) ||
3753                     object_equal( var, constant_TMPFILE ) ||
3754                     object_equal( var, constant_STDOUT ) ||
3755                     object_equal( var, constant_STDERR ) ) )
3756             {
3757                 result = list_push_back( result, var );
3758             }
3759         }
3760     }
3761 }
3762 
function_refer(FUNCTION * func)3763 void function_refer( FUNCTION * func )
3764 {
3765     ++func->reference_count;
3766 }
3767 
function_free(FUNCTION * function_)3768 void function_free( FUNCTION * function_ )
3769 {
3770     int i;
3771 
3772     if ( --function_->reference_count != 0 )
3773         return;
3774 
3775     if ( function_->formal_arguments )
3776         argument_list_free( function_->formal_arguments,
3777             function_->num_formal_arguments );
3778 
3779     if ( function_->type == FUNCTION_JAM )
3780     {
3781         JAM_FUNCTION * func = (JAM_FUNCTION *)function_;
3782 
3783         BJAM_FREE( func->code );
3784 
3785         if ( func->generic )
3786             function_free( func->generic );
3787         else
3788         {
3789             if ( function_->rulename ) object_free( function_->rulename );
3790 
3791             for ( i = 0; i < func->num_constants; ++i )
3792                 object_free( func->constants[ i ] );
3793             BJAM_FREE( func->constants );
3794 
3795             for ( i = 0; i < func->num_subfunctions; ++i )
3796             {
3797                 object_free( func->functions[ i ].name );
3798                 function_free( func->functions[ i ].code );
3799             }
3800             BJAM_FREE( func->functions );
3801 
3802             for ( i = 0; i < func->num_subactions; ++i )
3803             {
3804                 object_free( func->actions[ i ].name );
3805                 function_free( func->actions[ i ].command );
3806             }
3807             BJAM_FREE( func->actions );
3808 
3809             object_free( func->file );
3810         }
3811     }
3812 #ifdef HAVE_PYTHON
3813     else if ( function_->type == FUNCTION_PYTHON )
3814     {
3815         PYTHON_FUNCTION * func = (PYTHON_FUNCTION *)function_;
3816         Py_DECREF( func->python_function );
3817         if ( function_->rulename ) object_free( function_->rulename );
3818     }
3819 #endif
3820     else
3821     {
3822         assert( function_->type == FUNCTION_BUILTIN );
3823         if ( function_->rulename ) object_free( function_->rulename );
3824     }
3825 
3826     BJAM_FREE( function_ );
3827 }
3828 
3829 
3830 /* Alignment check for stack */
3831 
3832 struct align_var_edits
3833 {
3834     char ch;
3835     VAR_EDITS e;
3836 };
3837 
3838 struct align_expansion_item
3839 {
3840     char ch;
3841     expansion_item e;
3842 };
3843 
3844 static_assert(
3845     sizeof(struct align_var_edits) <= sizeof(VAR_EDITS) + sizeof(void *),
3846     "sizeof(struct align_var_edits) <= sizeof(VAR_EDITS) + sizeof(void *)" );
3847 static_assert(
3848     sizeof(struct align_expansion_item) <= sizeof(expansion_item) + sizeof(void *),
3849     "sizeof(struct align_expansion_item) <= sizeof(expansion_item) + sizeof(void *)" );
3850 
3851 static_assert( sizeof(LIST *) <= sizeof(void *), "sizeof(LIST *) <= sizeof(void *)" );
3852 static_assert( sizeof(char *) <= sizeof(void *), "sizeof(char *) <= sizeof(void *)" );
3853 
function_run_actions(FUNCTION * function,FRAME * frame,STACK * s,string * out)3854 void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s,
3855     string * out )
3856 {
3857     *(string * *)stack_allocate( s, sizeof( string * ) ) = out;
3858     list_free( function_run( function, frame, s ) );
3859     stack_deallocate( s, sizeof( string * ) );
3860 }
3861 
3862 /*
3863  * WARNING: The instruction set is tuned for Jam and is not really generic. Be
3864  * especially careful about stack push/pop.
3865  */
3866 
function_run(FUNCTION * function_,FRAME * frame,STACK * s)3867 LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
3868 {
3869     JAM_FUNCTION * function;
3870     instruction * code;
3871     LIST * l;
3872     LIST * r;
3873     LIST * result = L0;
3874     void * saved_stack = s->data;
3875 
3876     PROFILE_ENTER_LOCAL(function_run);
3877 
3878 #ifdef JAM_DEBUGGER
3879     frame->function = function_;
3880 #endif
3881 
3882     if ( function_->type == FUNCTION_BUILTIN )
3883     {
3884         PROFILE_ENTER_LOCAL(function_run_FUNCTION_BUILTIN);
3885         BUILTIN_FUNCTION const * const f = (BUILTIN_FUNCTION *)function_;
3886         if ( function_->formal_arguments )
3887             argument_list_check( function_->formal_arguments,
3888                 function_->num_formal_arguments, function_, frame );
3889 
3890         debug_on_enter_function( frame, f->base.rulename, NULL, -1 );
3891         result = f->func( frame, f->flags );
3892         debug_on_exit_function( f->base.rulename );
3893         PROFILE_EXIT_LOCAL(function_run_FUNCTION_BUILTIN);
3894         PROFILE_EXIT_LOCAL(function_run);
3895         return result;
3896     }
3897 
3898 #ifdef HAVE_PYTHON
3899     else if ( function_->type == FUNCTION_PYTHON )
3900     {
3901         PROFILE_ENTER_LOCAL(function_run_FUNCTION_PYTHON);
3902         PYTHON_FUNCTION * f = (PYTHON_FUNCTION *)function_;
3903         debug_on_enter_function( frame, f->base.rulename, NULL, -1 );
3904         result = call_python_function( f, frame );
3905         debug_on_exit_function( f->base.rulename );
3906         PROFILE_EXIT_LOCAL(function_run_FUNCTION_PYTHON);
3907         PROFILE_EXIT_LOCAL(function_run);
3908         return result;
3909     }
3910 #endif
3911 
3912     assert( function_->type == FUNCTION_JAM );
3913 
3914     if ( function_->formal_arguments )
3915         argument_list_push( function_->formal_arguments,
3916             function_->num_formal_arguments, function_, frame, s );
3917 
3918     function = (JAM_FUNCTION *)function_;
3919     debug_on_enter_function( frame, function->base.rulename, function->file, function->line );
3920     code = function->code;
3921     for ( ; ; )
3922     {
3923         switch ( code->op_code )
3924         {
3925 
3926         /*
3927          * Basic stack manipulation
3928          */
3929 
3930         case INSTR_PUSH_EMPTY:
3931         {
3932             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_EMPTY);
3933             stack_push( s, L0 );
3934             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_EMPTY);
3935             break;
3936         }
3937 
3938         case INSTR_PUSH_CONSTANT:
3939         {
3940             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_CONSTANT);
3941             OBJECT * value = function_get_constant( function, code->arg );
3942             stack_push( s, list_new( object_copy( value ) ) );
3943             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_CONSTANT);
3944             break;
3945         }
3946 
3947         case INSTR_PUSH_ARG:
3948         {
3949             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_ARG);
3950             stack_push( s, frame_get_local( frame, code->arg ) );
3951             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_ARG);
3952             break;
3953         }
3954 
3955         case INSTR_PUSH_VAR:
3956         {
3957             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_VAR);
3958             stack_push( s, function_get_variable( function, frame, code->arg ) );
3959             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_VAR);
3960             break;
3961         }
3962 
3963         case INSTR_PUSH_VAR_FIXED:
3964         {
3965             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_VAR_FIXED);
3966             stack_push( s, list_copy( frame->module->fixed_variables[ code->arg
3967                 ] ) );
3968             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_VAR_FIXED);
3969             break;
3970         }
3971 
3972         case INSTR_PUSH_GROUP:
3973         {
3974             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_GROUP);
3975             LIST * value = L0;
3976             LISTITER iter;
3977             LISTITER end;
3978             l = stack_pop( s );
3979             for ( iter = list_begin( l ), end = list_end( l ); iter != end;
3980                 iter = list_next( iter ) )
3981                 value = list_append( value, function_get_named_variable(
3982                     function, frame, list_item( iter ) ) );
3983             list_free( l );
3984             stack_push( s, value );
3985             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_GROUP);
3986             break;
3987         }
3988 
3989         case INSTR_PUSH_APPEND:
3990         {
3991             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_APPEND);
3992             r = stack_pop( s );
3993             l = stack_pop( s );
3994             stack_push( s, list_append( l, r ) );
3995             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_APPEND);
3996             break;
3997         }
3998 
3999         case INSTR_SWAP:
4000         {
4001             PROFILE_ENTER_LOCAL(function_run_INSTR_SWAP);
4002             l = stack_top( s );
4003             stack_set( s, 0, stack_at( s, code->arg ) );
4004             stack_set( s, code->arg, l );
4005             PROFILE_EXIT_LOCAL(function_run_INSTR_SWAP);
4006             break;
4007         }
4008 
4009         case INSTR_POP:
4010         {
4011             PROFILE_ENTER_LOCAL(function_run_INSTR_POP);
4012             list_free( stack_pop( s ) );
4013             PROFILE_EXIT_LOCAL(function_run_INSTR_POP);
4014             break;
4015         }
4016 
4017         /*
4018          * Branch instructions
4019          */
4020 
4021         case INSTR_JUMP:
4022         {
4023             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP);
4024             code += code->arg;
4025             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP);
4026             break;
4027         }
4028 
4029         case INSTR_JUMP_EMPTY:
4030         {
4031             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_EMPTY);
4032             l = stack_pop( s );
4033             if ( !list_cmp( l, L0 ) ) code += code->arg;
4034             list_free( l );
4035             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_EMPTY);
4036             break;
4037         }
4038 
4039         case INSTR_JUMP_NOT_EMPTY:
4040         {
4041             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NOT_EMPTY);
4042             l = stack_pop( s );
4043             if ( list_cmp( l, L0 ) ) code += code->arg;
4044             list_free( l );
4045             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NOT_EMPTY);
4046             break;
4047         }
4048 
4049         case INSTR_JUMP_LT:
4050         {
4051             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_LT);
4052             r = stack_pop( s );
4053             l = stack_pop( s );
4054             if ( list_cmp( l, r ) < 0 ) code += code->arg;
4055             list_free( l );
4056             list_free( r );
4057             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_LT);
4058             break;
4059         }
4060 
4061         case INSTR_JUMP_LE:
4062         {
4063             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_LE);
4064             r = stack_pop( s );
4065             l = stack_pop( s );
4066             if ( list_cmp( l, r ) <= 0 ) code += code->arg;
4067             list_free( l );
4068             list_free( r );
4069             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_LE);
4070             break;
4071         }
4072 
4073         case INSTR_JUMP_GT:
4074         {
4075             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_GT);
4076             r = stack_pop( s );
4077             l = stack_pop( s );
4078             if ( list_cmp( l, r ) > 0 ) code += code->arg;
4079             list_free( l );
4080             list_free( r );
4081             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_GT);
4082             break;
4083         }
4084 
4085         case INSTR_JUMP_GE:
4086         {
4087             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_GE);
4088             r = stack_pop( s );
4089             l = stack_pop( s );
4090             if ( list_cmp( l, r ) >= 0 ) code += code->arg;
4091             list_free( l );
4092             list_free( r );
4093             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_GE);
4094             break;
4095         }
4096 
4097         case INSTR_JUMP_EQ:
4098         {
4099             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_EQ);
4100             r = stack_pop( s );
4101             l = stack_pop( s );
4102             if ( list_cmp( l, r ) == 0 ) code += code->arg;
4103             list_free( l );
4104             list_free( r );
4105             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_EQ);
4106             break;
4107         }
4108 
4109         case INSTR_JUMP_NE:
4110         {
4111             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NE);
4112             r = stack_pop(s);
4113             l = stack_pop(s);
4114             if ( list_cmp(l, r) != 0 ) code += code->arg;
4115             list_free(l);
4116             list_free(r);
4117             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NE);
4118             break;
4119         }
4120 
4121         case INSTR_JUMP_IN:
4122         {
4123             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_IN);
4124             r = stack_pop(s);
4125             l = stack_pop(s);
4126             if ( list_is_sublist( l, r ) ) code += code->arg;
4127             list_free(l);
4128             list_free(r);
4129             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_IN);
4130             break;
4131         }
4132 
4133         case INSTR_JUMP_NOT_IN:
4134         {
4135             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NOT_IN);
4136             r = stack_pop( s );
4137             l = stack_pop( s );
4138             if ( !list_is_sublist( l, r ) ) code += code->arg;
4139             list_free( l );
4140             list_free( r );
4141             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NOT_IN);
4142             break;
4143         }
4144 
4145         /*
4146          * For
4147          */
4148 
4149         case INSTR_FOR_INIT:
4150         {
4151             PROFILE_ENTER_LOCAL(function_run_INSTR_FOR_INIT);
4152             l = stack_top( s );
4153             *(LISTITER *)stack_allocate( s, sizeof( LISTITER ) ) =
4154                 list_begin( l );
4155             PROFILE_EXIT_LOCAL(function_run_INSTR_FOR_INIT);
4156             break;
4157         }
4158 
4159         case INSTR_FOR_LOOP:
4160         {
4161             PROFILE_ENTER_LOCAL(function_run_INSTR_FOR_LOOP);
4162             LISTITER iter = *(LISTITER *)stack_get( s );
4163             stack_deallocate( s, sizeof( LISTITER ) );
4164             l = stack_top( s );
4165             if ( iter == list_end( l ) )
4166             {
4167                 list_free( stack_pop( s ) );
4168                 code += code->arg;
4169             }
4170             else
4171             {
4172                 r = list_new( object_copy( list_item( iter ) ) );
4173                 iter = list_next( iter );
4174                 *(LISTITER *)stack_allocate( s, sizeof( LISTITER ) ) = iter;
4175                 stack_push( s, r );
4176             }
4177             PROFILE_EXIT_LOCAL(function_run_INSTR_FOR_LOOP);
4178             break;
4179         }
4180 
4181         case INSTR_FOR_POP:
4182         {
4183             PROFILE_ENTER_LOCAL(function_run_INSTR_FOR_POP);
4184             stack_deallocate( s, sizeof( LISTITER ) );
4185             list_free( stack_pop( s ) );
4186             PROFILE_EXIT_LOCAL(function_run_INSTR_FOR_POP);
4187             break;
4188         }
4189 
4190         /*
4191          * Switch
4192          */
4193 
4194         case INSTR_JUMP_NOT_GLOB:
4195         {
4196             PROFILE_ENTER_LOCAL(function_run_INSTR_JUMP_NOT_GLOB);
4197             char const * pattern;
4198             char const * match;
4199             l = stack_pop( s );
4200             r = stack_top( s );
4201             pattern = list_empty( l ) ? "" : object_str( list_front( l ) );
4202             match = list_empty( r ) ? "" : object_str( list_front( r ) );
4203             if ( glob( pattern, match ) )
4204                 code += code->arg;
4205             else
4206                 list_free( stack_pop( s ) );
4207             list_free( l );
4208             PROFILE_EXIT_LOCAL(function_run_INSTR_JUMP_NOT_GLOB);
4209             break;
4210         }
4211 
4212         /*
4213          * Return
4214          */
4215 
4216         case INSTR_SET_RESULT:
4217         {
4218             PROFILE_ENTER_LOCAL(function_run_INSTR_SET_RESULT);
4219             list_free( result );
4220             if ( !code->arg )
4221                 result = stack_pop( s );
4222             else
4223                 result = list_copy( stack_top( s ) );
4224             PROFILE_EXIT_LOCAL(function_run_INSTR_SET_RESULT);
4225             break;
4226         }
4227 
4228         case INSTR_PUSH_RESULT:
4229         {
4230             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_RESULT);
4231             stack_push( s, result );
4232             result = L0;
4233             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_RESULT);
4234             break;
4235         }
4236 
4237         case INSTR_RETURN:
4238         {
4239             PROFILE_ENTER_LOCAL(function_run_INSTR_RETURN);
4240             if ( function_->formal_arguments )
4241                 argument_list_pop( function_->formal_arguments,
4242                     function_->num_formal_arguments, frame, s );
4243 #ifndef NDEBUG
4244             if ( !( saved_stack == s->data ) )
4245             {
4246                 frame->file = function->file;
4247                 frame->line = function->line;
4248                 backtrace_line( frame );
4249                 out_printf( "error: stack check failed.\n" );
4250                 backtrace( frame );
4251                 assert( saved_stack == s->data );
4252             }
4253 #endif
4254             assert( saved_stack == s->data );
4255             debug_on_exit_function( function->base.rulename );
4256             PROFILE_EXIT_LOCAL(function_run_INSTR_RETURN);
4257             PROFILE_EXIT_LOCAL(function_run);
4258             return result;
4259         }
4260 
4261         /*
4262          * Local variables
4263          */
4264 
4265         case INSTR_PUSH_LOCAL:
4266         {
4267             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_LOCAL);
4268             LIST * value = stack_pop( s );
4269             stack_push( s, function_swap_variable( function, frame, code->arg,
4270                 value ) );
4271             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_LOCAL);
4272             break;
4273         }
4274 
4275         case INSTR_POP_LOCAL:
4276         {
4277             PROFILE_ENTER_LOCAL(function_run_INSTR_POP_LOCAL);
4278             function_set_variable( function, frame, code->arg, stack_pop( s ) );
4279             PROFILE_EXIT_LOCAL(function_run_INSTR_POP_LOCAL);
4280             break;
4281         }
4282 
4283         case INSTR_PUSH_LOCAL_FIXED:
4284         {
4285             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_LOCAL_FIXED);
4286             LIST * value = stack_pop( s );
4287             LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
4288             assert( code->arg < frame->module->num_fixed_variables );
4289             stack_push( s, *ptr );
4290             *ptr = value;
4291             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_LOCAL_FIXED);
4292             break;
4293         }
4294 
4295         case INSTR_POP_LOCAL_FIXED:
4296         {
4297             PROFILE_ENTER_LOCAL(function_run_INSTR_POP_LOCAL_FIXED);
4298             LIST * value = stack_pop( s );
4299             LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
4300             assert( code->arg < frame->module->num_fixed_variables );
4301             list_free( *ptr );
4302             *ptr = value;
4303             PROFILE_EXIT_LOCAL(function_run_INSTR_POP_LOCAL_FIXED);
4304             break;
4305         }
4306 
4307         case INSTR_PUSH_LOCAL_GROUP:
4308         {
4309             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_LOCAL_GROUP);
4310             LIST * const value = stack_pop( s );
4311             LISTITER iter;
4312             LISTITER end;
4313             l = stack_pop( s );
4314             for ( iter = list_begin( l ), end = list_end( l ); iter != end;
4315                 iter = list_next( iter ) )
4316                 stack_push( s, function_swap_named_variable( function, frame,
4317                     list_item( iter ), list_copy( value ) ) );
4318             list_free( value );
4319             stack_push( s, l );
4320             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_LOCAL_GROUP);
4321             break;
4322         }
4323 
4324         case INSTR_POP_LOCAL_GROUP:
4325         {
4326             PROFILE_ENTER_LOCAL(function_run_INSTR_POP_LOCAL_GROUP);
4327             LISTITER iter;
4328             LISTITER end;
4329             r = stack_pop( s );
4330             l = list_reverse( r );
4331             list_free( r );
4332             for ( iter = list_begin( l ), end = list_end( l ); iter != end;
4333                 iter = list_next( iter ) )
4334                 function_set_named_variable( function, frame, list_item( iter ),
4335                     stack_pop( s ) );
4336             list_free( l );
4337             PROFILE_EXIT_LOCAL(function_run_INSTR_POP_LOCAL_GROUP);
4338             break;
4339         }
4340 
4341         /*
4342          * on $(TARGET) variables
4343          */
4344 
4345         case INSTR_PUSH_ON:
4346         {
4347             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_ON);
4348             LIST * targets = stack_top( s );
4349             if ( !list_empty( targets ) )
4350             {
4351                 /* FIXME: push the state onto the stack instead of using
4352                  * pushsettings.
4353                  */
4354                 TARGET * t = bindtarget( list_front( targets ) );
4355                 pushsettings( frame->module, t->settings );
4356             }
4357             else
4358             {
4359                 /* [ on $(TARGET) ... ] is ignored if $(TARGET) is empty. */
4360                 list_free( stack_pop( s ) );
4361                 stack_push( s, L0 );
4362                 code += code->arg;
4363             }
4364             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_ON);
4365             break;
4366         }
4367 
4368         case INSTR_POP_ON:
4369         {
4370             PROFILE_ENTER_LOCAL(function_run_INSTR_POP_ON);
4371             LIST * result = stack_pop( s );
4372             LIST * targets = stack_pop( s );
4373             if ( !list_empty( targets ) )
4374             {
4375                 TARGET * t = bindtarget( list_front( targets ) );
4376                 popsettings( frame->module, t->settings );
4377             }
4378             list_free( targets );
4379             stack_push( s, result );
4380             PROFILE_EXIT_LOCAL(function_run_INSTR_POP_ON);
4381             break;
4382         }
4383 
4384         case INSTR_SET_ON:
4385         {
4386             PROFILE_ENTER_LOCAL(function_run_INSTR_SET_ON);
4387             LIST * targets = stack_pop( s );
4388             LIST * value = stack_pop( s );
4389             LIST * vars = stack_pop( s );
4390             LISTITER iter = list_begin( targets );
4391             LISTITER const end = list_end( targets );
4392             for ( ; iter != end; iter = list_next( iter ) )
4393             {
4394                 TARGET * t = bindtarget( list_item( iter ) );
4395                 LISTITER vars_iter = list_begin( vars );
4396                 LISTITER const vars_end = list_end( vars );
4397                 for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter
4398                     ) )
4399                     t->settings = addsettings( t->settings, VAR_SET, list_item(
4400                         vars_iter ), list_copy( value ) );
4401             }
4402             list_free( vars );
4403             list_free( targets );
4404             stack_push( s, value );
4405             PROFILE_EXIT_LOCAL(function_run_INSTR_SET_ON);
4406             break;
4407         }
4408 
4409         case INSTR_APPEND_ON:
4410         {
4411             PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_ON);
4412             LIST * targets = stack_pop( s );
4413             LIST * value = stack_pop( s );
4414             LIST * vars = stack_pop( s );
4415             LISTITER iter = list_begin( targets );
4416             LISTITER const end = list_end( targets );
4417             for ( ; iter != end; iter = list_next( iter ) )
4418             {
4419                 TARGET * const t = bindtarget( list_item( iter ) );
4420                 LISTITER vars_iter = list_begin( vars );
4421                 LISTITER const vars_end = list_end( vars );
4422                 for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter
4423                     ) )
4424                     t->settings = addsettings( t->settings, VAR_APPEND,
4425                         list_item( vars_iter ), list_copy( value ) );
4426             }
4427             list_free( vars );
4428             list_free( targets );
4429             stack_push( s, value );
4430             PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_ON);
4431             break;
4432         }
4433 
4434         case INSTR_DEFAULT_ON:
4435         {
4436             PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT_ON);
4437             LIST * targets = stack_pop( s );
4438             LIST * value = stack_pop( s );
4439             LIST * vars = stack_pop( s );
4440             LISTITER iter = list_begin( targets );
4441             LISTITER const end = list_end( targets );
4442             for ( ; iter != end; iter = list_next( iter ) )
4443             {
4444                 TARGET * t = bindtarget( list_item( iter ) );
4445                 LISTITER vars_iter = list_begin( vars );
4446                 LISTITER const vars_end = list_end( vars );
4447                 for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter
4448                     ) )
4449                     t->settings = addsettings( t->settings, VAR_DEFAULT,
4450                         list_item( vars_iter ), list_copy( value ) );
4451             }
4452             list_free( vars );
4453             list_free( targets );
4454             stack_push( s, value );
4455             PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT_ON);
4456             break;
4457         }
4458 
4459         /* [ on $(target) return $(variable) ] */
4460         case INSTR_GET_ON:
4461         {
4462             PROFILE_ENTER_LOCAL(function_run_INSTR_GET_ON);
4463             LIST * targets = stack_pop( s );
4464             LIST * result = L0;
4465             if ( !list_empty( targets ) )
4466             {
4467                 OBJECT * varname = function->constants[ code->arg ];
4468                 TARGET * t = bindtarget( list_front( targets ) );
4469                 SETTINGS * s = t->settings;
4470                 int found = 0;
4471                 for ( ; s != 0; s = s->next )
4472                 {
4473                     if ( object_equal( s->symbol, varname ) )
4474                     {
4475                         result = s->value;
4476                         found = 1;
4477                         break;
4478                     }
4479                 }
4480                 if ( !found )
4481                 {
4482                     result = var_get( frame->module, varname ) ;
4483                 }
4484             }
4485             list_free( targets );
4486             stack_push( s, list_copy( result ) );
4487             PROFILE_EXIT_LOCAL(function_run_INSTR_GET_ON);
4488             break;
4489         }
4490 
4491         /*
4492          * Variable setting
4493          */
4494 
4495         case INSTR_SET:
4496         {
4497             PROFILE_ENTER_LOCAL(function_run_INSTR_SET);
4498             function_set_variable( function, frame, code->arg,
4499                 stack_pop( s ) );
4500             PROFILE_EXIT_LOCAL(function_run_INSTR_SET);
4501             break;
4502         }
4503 
4504         case INSTR_APPEND:
4505         {
4506             PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND);
4507             function_append_variable( function, frame, code->arg,
4508                 stack_pop( s ) );
4509             PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND);
4510             break;
4511         }
4512 
4513         case INSTR_DEFAULT:
4514         {
4515             PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT);
4516             function_default_variable( function, frame, code->arg,
4517                 stack_pop( s ) );
4518             PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT);
4519             break;
4520         }
4521 
4522         case INSTR_SET_FIXED:
4523         {
4524             PROFILE_ENTER_LOCAL(function_run_INSTR_SET_FIXED);
4525             LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
4526             assert( code->arg < frame->module->num_fixed_variables );
4527             list_free( *ptr );
4528             *ptr = stack_pop( s );
4529             PROFILE_EXIT_LOCAL(function_run_INSTR_SET_FIXED);
4530             break;
4531         }
4532 
4533         case INSTR_APPEND_FIXED:
4534         {
4535             PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_FIXED);
4536             LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
4537             assert( code->arg < frame->module->num_fixed_variables );
4538             *ptr = list_append( *ptr, stack_pop( s ) );
4539             PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_FIXED);
4540             break;
4541         }
4542 
4543         case INSTR_DEFAULT_FIXED:
4544         {
4545             PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT_FIXED);
4546             LIST * * ptr = &frame->module->fixed_variables[ code->arg ];
4547             LIST * value = stack_pop( s );
4548             assert( code->arg < frame->module->num_fixed_variables );
4549             if ( list_empty( *ptr ) )
4550                 *ptr = value;
4551             else
4552                 list_free( value );
4553             PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT_FIXED);
4554             break;
4555         }
4556 
4557         case INSTR_SET_GROUP:
4558         {
4559             PROFILE_ENTER_LOCAL(function_run_INSTR_SET_GROUP);
4560             LIST * value = stack_pop( s );
4561             LIST * vars = stack_pop( s );
4562             LISTITER iter = list_begin( vars );
4563             LISTITER const end = list_end( vars );
4564             for ( ; iter != end; iter = list_next( iter ) )
4565                 function_set_named_variable( function, frame, list_item( iter ),
4566                     list_copy( value ) );
4567             list_free( vars );
4568             list_free( value );
4569             PROFILE_EXIT_LOCAL(function_run_INSTR_SET_GROUP);
4570             break;
4571         }
4572 
4573         case INSTR_APPEND_GROUP:
4574         {
4575             PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_GROUP);
4576             LIST * value = stack_pop( s );
4577             LIST * vars = stack_pop( s );
4578             LISTITER iter = list_begin( vars );
4579             LISTITER const end = list_end( vars );
4580             for ( ; iter != end; iter = list_next( iter ) )
4581                 function_append_named_variable( function, frame, list_item( iter
4582                     ), list_copy( value ) );
4583             list_free( vars );
4584             list_free( value );
4585             PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_GROUP);
4586             break;
4587         }
4588 
4589         case INSTR_DEFAULT_GROUP:
4590         {
4591             PROFILE_ENTER_LOCAL(function_run_INSTR_DEFAULT_GROUP);
4592             LIST * value = stack_pop( s );
4593             LIST * vars = stack_pop( s );
4594             LISTITER iter = list_begin( vars );
4595             LISTITER const end = list_end( vars );
4596             for ( ; iter != end; iter = list_next( iter ) )
4597                 function_default_named_variable( function, frame, list_item(
4598                     iter ), list_copy( value ) );
4599             list_free( vars );
4600             list_free( value );
4601             PROFILE_EXIT_LOCAL(function_run_INSTR_DEFAULT_GROUP);
4602             break;
4603         }
4604 
4605         /*
4606          * Rules
4607          */
4608 
4609         case INSTR_CALL_RULE:
4610         {
4611             PROFILE_ENTER_LOCAL(function_run_INSTR_CALL_RULE);
4612             char const * unexpanded = object_str( function_get_constant(
4613                 function, code[ 1 ].op_code ) );
4614             LIST * result = function_call_rule( function, frame, s, code->arg,
4615                 unexpanded, function->file, code[ 1 ].arg );
4616             stack_push( s, result );
4617             ++code;
4618             PROFILE_EXIT_LOCAL(function_run_INSTR_CALL_RULE);
4619             break;
4620         }
4621 
4622         case INSTR_CALL_MEMBER_RULE:
4623         {
4624             PROFILE_ENTER_LOCAL(function_run_INSTR_CALL_MEMBER_RULE);
4625             OBJECT * rule_name = function_get_constant( function, code[1].op_code );
4626             LIST * result = function_call_member_rule( function, frame, s, code->arg, rule_name, function->file, code[1].arg );
4627             stack_push( s, result );
4628             ++code;
4629             PROFILE_EXIT_LOCAL(function_run_INSTR_CALL_MEMBER_RULE);
4630             break;
4631         }
4632 
4633         case INSTR_RULE:
4634         {
4635             PROFILE_ENTER_LOCAL(function_run_INSTR_RULE);
4636             function_set_rule( function, frame, s, code->arg );
4637             PROFILE_EXIT_LOCAL(function_run_INSTR_RULE);
4638             break;
4639         }
4640 
4641         case INSTR_ACTIONS:
4642         {
4643             PROFILE_ENTER_LOCAL(function_run_INSTR_ACTIONS);
4644             function_set_actions( function, frame, s, code->arg );
4645             PROFILE_EXIT_LOCAL(function_run_INSTR_ACTIONS);
4646             break;
4647         }
4648 
4649         /*
4650          * Variable expansion
4651          */
4652 
4653         case INSTR_APPLY_MODIFIERS:
4654         {
4655             PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_MODIFIERS);
4656             int n;
4657             int i;
4658             l = stack_pop( s );
4659             n = expand_modifiers( s, code->arg );
4660             stack_push( s, l );
4661             l = apply_modifiers( s, n );
4662             list_free( stack_pop( s ) );
4663             stack_deallocate( s, n * sizeof( VAR_EDITS ) );
4664             for ( i = 0; i < code->arg; ++i )
4665                 list_free( stack_pop( s ) );  /* pop modifiers */
4666             stack_push( s, l );
4667             PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_MODIFIERS);
4668             break;
4669         }
4670 
4671         case INSTR_APPLY_INDEX:
4672         {
4673             PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX);
4674             l = apply_subscript( s );
4675             list_free( stack_pop( s ) );
4676             list_free( stack_pop( s ) );
4677             stack_push( s, l );
4678             PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX);
4679             break;
4680         }
4681 
4682         case INSTR_APPLY_INDEX_MODIFIERS:
4683         {
4684             PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS);
4685             int i;
4686             int n;
4687             l = stack_pop( s );
4688             r = stack_pop( s );
4689             n = expand_modifiers( s, code->arg );
4690             stack_push( s, r );
4691             stack_push( s, l );
4692             l = apply_subscript_and_modifiers( s, n );
4693             list_free( stack_pop( s ) );
4694             list_free( stack_pop( s ) );
4695             stack_deallocate( s, n * sizeof( VAR_EDITS ) );
4696             for ( i = 0; i < code->arg; ++i )
4697                 list_free( stack_pop( s ) );  /* pop modifiers */
4698             stack_push( s, l );
4699             PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS);
4700             break;
4701         }
4702 
4703         case INSTR_APPLY_MODIFIERS_GROUP:
4704         {
4705             PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_MODIFIERS_GROUP);
4706             int i;
4707             LIST * const vars = stack_pop( s );
4708             int const n = expand_modifiers( s, code->arg );
4709             LIST * result = L0;
4710             LISTITER iter = list_begin( vars );
4711             LISTITER const end = list_end( vars );
4712             for ( ; iter != end; iter = list_next( iter ) )
4713             {
4714                 stack_push( s, function_get_named_variable( function, frame,
4715                     list_item( iter ) ) );
4716                 result = list_append( result, apply_modifiers( s, n ) );
4717                 list_free( stack_pop( s ) );
4718             }
4719             list_free( vars );
4720             stack_deallocate( s, n * sizeof( VAR_EDITS ) );
4721             for ( i = 0; i < code->arg; ++i )
4722                 list_free( stack_pop( s ) );  /* pop modifiers */
4723             stack_push( s, result );
4724             PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_MODIFIERS_GROUP);
4725             break;
4726         }
4727 
4728         case INSTR_APPLY_INDEX_GROUP:
4729         {
4730             PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX_GROUP);
4731             LIST * vars = stack_pop( s );
4732             LIST * result = L0;
4733             LISTITER iter = list_begin( vars );
4734             LISTITER const end = list_end( vars );
4735             for ( ; iter != end; iter = list_next( iter ) )
4736             {
4737                 stack_push( s, function_get_named_variable( function, frame,
4738                     list_item( iter ) ) );
4739                 result = list_append( result, apply_subscript( s ) );
4740                 list_free( stack_pop( s ) );
4741             }
4742             list_free( vars );
4743             list_free( stack_pop( s ) );
4744             stack_push( s, result );
4745             PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX_GROUP);
4746             break;
4747         }
4748 
4749         case INSTR_APPLY_INDEX_MODIFIERS_GROUP:
4750         {
4751             PROFILE_ENTER_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS_GROUP);
4752             int i;
4753             LIST * const vars = stack_pop( s );
4754             LIST * const r = stack_pop( s );
4755             int const n = expand_modifiers( s, code->arg );
4756             LIST * result = L0;
4757             LISTITER iter = list_begin( vars );
4758             LISTITER const end = list_end( vars );
4759             stack_push( s, r );
4760             for ( ; iter != end; iter = list_next( iter ) )
4761             {
4762                 stack_push( s, function_get_named_variable( function, frame,
4763                     list_item( iter ) ) );
4764                 result = list_append( result, apply_subscript_and_modifiers( s,
4765                     n ) );
4766                 list_free( stack_pop( s ) );
4767             }
4768             list_free( stack_pop( s ) );
4769             list_free( vars );
4770             stack_deallocate( s, n * sizeof( VAR_EDITS ) );
4771             for ( i = 0; i < code->arg; ++i )
4772                 list_free( stack_pop( s ) );  /* pop modifiers */
4773             stack_push( s, result );
4774             PROFILE_EXIT_LOCAL(function_run_INSTR_APPLY_INDEX_MODIFIERS_GROUP);
4775             break;
4776         }
4777 
4778         case INSTR_COMBINE_STRINGS:
4779         {
4780             PROFILE_ENTER_LOCAL(function_run_INSTR_COMBINE_STRINGS);
4781             size_t const buffer_size = code->arg * sizeof( expansion_item );
4782             LIST * * const stack_pos = (LIST * * const)stack_get( s );
4783             expansion_item * items = (expansion_item *)stack_allocate( s, buffer_size );
4784             LIST * result;
4785             int i;
4786             for ( i = 0; i < code->arg; ++i )
4787                 items[ i ].values = stack_pos[ i ];
4788             result = expand( items, code->arg );
4789             stack_deallocate( s, buffer_size );
4790             for ( i = 0; i < code->arg; ++i )
4791                 list_free( stack_pop( s ) );
4792             stack_push( s, result );
4793             PROFILE_EXIT_LOCAL(function_run_INSTR_COMBINE_STRINGS);
4794             break;
4795         }
4796 
4797         case INSTR_GET_GRIST:
4798         {
4799             PROFILE_ENTER_LOCAL(function_run_INSTR_GET_GRIST);
4800             LIST * vals = stack_pop( s );
4801             LIST * result = L0;
4802             LISTITER iter, end;
4803 
4804             for ( iter = list_begin( vals ), end = list_end( vals ); iter != end; ++iter )
4805             {
4806                 OBJECT * new_object;
4807                 const char * value = object_str( list_item( iter ) );
4808                 const char * p;
4809                 if ( value[ 0 ] == '<' && ( p = strchr( value, '>' ) ) )
4810                 {
4811                     if( p[ 1 ] )
4812                         new_object = object_new_range( value, p - value + 1 );
4813                     else
4814                         new_object = object_copy( list_item( iter ) );
4815                 }
4816                 else
4817                 {
4818                     new_object = object_copy( constant_empty );
4819                 }
4820                 result = list_push_back( result, new_object );
4821             }
4822 
4823             list_free( vals );
4824             stack_push( s, result );
4825             PROFILE_EXIT_LOCAL(function_run_INSTR_GET_GRIST);
4826             break;
4827         }
4828 
4829         case INSTR_INCLUDE:
4830         {
4831             PROFILE_ENTER_LOCAL(function_run_INSTR_INCLUDE);
4832             LIST * nt = stack_pop( s );
4833             if ( !list_empty( nt ) )
4834             {
4835                 TARGET * const t = bindtarget( list_front( nt ) );
4836                 list_free( nt );
4837 
4838                 /* DWA 2001/10/22 - Perforce Jam cleared the arguments here,
4839                  * which prevented an included file from being treated as part
4840                  * of the body of a rule. I did not see any reason to do that,
4841                  * so I lifted the restriction.
4842                  */
4843 
4844                 /* Bind the include file under the influence of "on-target"
4845                  * variables. Though they are targets, include files are not
4846                  * built with make().
4847                  */
4848 
4849                 pushsettings( root_module(), t->settings );
4850                 /* We do not expect that a file to be included is generated by
4851                  * some action. Therefore, pass 0 as third argument. If the name
4852                  * resolves to a directory, let it error out.
4853                  */
4854                 object_free( t->boundname );
4855                 t->boundname = search( t->name, &t->time, 0, 0 );
4856                 popsettings( root_module(), t->settings );
4857 
4858                 parse_file( t->boundname, frame );
4859 #ifdef JAM_DEBUGGER
4860                 frame->function = function_;
4861 #endif
4862             }
4863             PROFILE_EXIT_LOCAL(function_run_INSTR_INCLUDE);
4864             break;
4865         }
4866 
4867         /*
4868          * Classes and modules
4869          */
4870 
4871         case INSTR_PUSH_MODULE:
4872         {
4873             PROFILE_ENTER_LOCAL(function_run_INSTR_PUSH_MODULE);
4874             LIST * const module_name = stack_pop( s );
4875             module_t * const outer_module = frame->module;
4876             frame->module = !list_empty( module_name )
4877                 ? bindmodule( list_front( module_name ) )
4878                 : root_module();
4879             list_free( module_name );
4880             *(module_t * *)stack_allocate( s, sizeof( module_t * ) ) =
4881                 outer_module;
4882             PROFILE_EXIT_LOCAL(function_run_INSTR_PUSH_MODULE);
4883             break;
4884         }
4885 
4886         case INSTR_POP_MODULE:
4887         {
4888             PROFILE_ENTER_LOCAL(function_run_INSTR_POP_MODULE);
4889             module_t * const outer_module = *(module_t * *)stack_get( s );
4890             stack_deallocate( s, sizeof( module_t * ) );
4891             frame->module = outer_module;
4892             PROFILE_EXIT_LOCAL(function_run_INSTR_POP_MODULE);
4893             break;
4894         }
4895 
4896         case INSTR_CLASS:
4897         {
4898             PROFILE_ENTER_LOCAL(function_run_INSTR_CLASS);
4899             LIST * bases = stack_pop( s );
4900             LIST * name = stack_pop( s );
4901             OBJECT * class_module = make_class_module( name, bases, frame );
4902 
4903             module_t * const outer_module = frame->module;
4904             frame->module = bindmodule( class_module );
4905             object_free( class_module );
4906 
4907             *(module_t * *)stack_allocate( s, sizeof( module_t * ) ) =
4908                 outer_module;
4909             PROFILE_EXIT_LOCAL(function_run_INSTR_CLASS);
4910             break;
4911         }
4912 
4913         case INSTR_BIND_MODULE_VARIABLES:
4914         {
4915             PROFILE_ENTER_LOCAL(function_run_INSTR_BIND_MODULE_VARIABLES);
4916             module_bind_variables( frame->module );
4917             PROFILE_EXIT_LOCAL(function_run_INSTR_BIND_MODULE_VARIABLES);
4918             break;
4919         }
4920 
4921         case INSTR_APPEND_STRINGS:
4922         {
4923             PROFILE_ENTER_LOCAL(function_run_INSTR_APPEND_STRINGS);
4924             string buf[ 1 ];
4925             string_new( buf );
4926             combine_strings( s, code->arg, buf );
4927             stack_push( s, list_new( object_new( buf->value ) ) );
4928             string_free( buf );
4929             PROFILE_EXIT_LOCAL(function_run_INSTR_APPEND_STRINGS);
4930             break;
4931         }
4932 
4933         case INSTR_WRITE_FILE:
4934         {
4935             PROFILE_ENTER_LOCAL(function_run_INSTR_WRITE_FILE);
4936             string buf[ 1 ];
4937             char const * out;
4938             OBJECT * tmp_filename = 0;
4939             int out_debug = DEBUG_EXEC ? 1 : 0;
4940             FILE * out_file = 0;
4941             string_new( buf );
4942             combine_strings( s, code->arg, buf );
4943             out = object_str( list_front( stack_top( s ) ) );
4944 
4945             /* For stdout/stderr we will create a temp file and generate a
4946              * command that outputs the content as needed.
4947              */
4948             if ( ( strcmp( "STDOUT", out ) == 0 ) ||
4949                 ( strcmp( "STDERR", out ) == 0 ) )
4950             {
4951                 int err_redir = strcmp( "STDERR", out ) == 0;
4952                 string result[ 1 ];
4953 
4954                 tmp_filename = path_tmpfile();
4955 
4956                 /* Construct os-specific cat command. */
4957                 {
4958                     const char * command = "cat";
4959                     const char * quote = "\"";
4960                     const char * redirect = "1>&2";
4961 
4962                 #ifdef OS_NT
4963                     command = "type";
4964                     quote = "\"";
4965                 #elif defined( OS_VMS )
4966                     command = "pipe type";
4967                     quote = "";
4968 
4969                     /* Get tmp file name is os-format. */
4970                     {
4971                         string os_filename[ 1 ];
4972 
4973                         string_new( os_filename );
4974                         path_translate_to_os( object_str( tmp_filename ), os_filename );
4975                         object_free( tmp_filename );
4976                         tmp_filename = object_new( os_filename->value );
4977                         string_free( os_filename );
4978                     }
4979                 #endif
4980 
4981                     string_new( result );
4982                     string_append( result, command );
4983                     string_append( result, " " );
4984                     string_append( result, quote );
4985                     string_append( result, object_str( tmp_filename ) );
4986                     string_append( result, quote );
4987                     if ( err_redir )
4988                     {
4989                         string_append( result, " " );
4990                         string_append( result, redirect );
4991                     }
4992                 }
4993 
4994                 /* Replace STDXXX with the temporary file. */
4995                 list_free( stack_pop( s ) );
4996                 stack_push( s, list_new( object_new( result->value ) ) );
4997                 out = object_str( tmp_filename );
4998 
4999                 string_free( result );
5000 
5001                 /* Make sure temp files created by this get nuked eventually. */
5002                 file_remove_atexit( tmp_filename );
5003             }
5004 
5005             if ( !globs.noexec )
5006             {
5007                 string out_name[ 1 ];
5008                 /* Handle "path to file" filenames. */
5009                 if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' )
5010                     )
5011                 {
5012                     string_copy( out_name, out + 1 );
5013                     string_truncate( out_name, out_name->size - 1 );
5014                 }
5015                 else
5016                     string_copy( out_name, out );
5017                 out_file = fopen( out_name->value, "w" );
5018 
5019                 if ( !out_file )
5020                 {
5021                     err_printf( "[errno %d] failed to write output file '%s': %s",
5022                         errno, out_name->value, strerror(errno) );
5023                     exit( EXITBAD );
5024                 }
5025                 string_free( out_name );
5026             }
5027 
5028             if ( out_debug ) out_printf( "\nfile %s\n", out );
5029             if ( out_file ) fputs( buf->value, out_file );
5030             if ( out_debug ) out_puts( buf->value );
5031             if ( out_file )
5032             {
5033                 fflush( out_file );
5034                 fclose( out_file );
5035             }
5036             string_free( buf );
5037             if ( tmp_filename )
5038                 object_free( tmp_filename );
5039 
5040             if ( out_debug ) out_putc( '\n' );
5041             PROFILE_EXIT_LOCAL(function_run_INSTR_WRITE_FILE);
5042             break;
5043         }
5044 
5045         case INSTR_OUTPUT_STRINGS:
5046         {
5047             PROFILE_ENTER_LOCAL(function_run_INSTR_OUTPUT_STRINGS);
5048             string * const buf = *(string * *)( (char *)stack_get( s ) + (
5049                 code->arg * sizeof( LIST * ) ) );
5050             combine_strings( s, code->arg, buf );
5051             PROFILE_EXIT_LOCAL(function_run_INSTR_OUTPUT_STRINGS);
5052             break;
5053         }
5054 
5055         case INSTR_DEBUG_LINE:
5056         {
5057             debug_on_instruction( frame, function->file, code->arg );
5058             break;
5059         }
5060 
5061         }
5062         ++code;
5063     }
5064 
5065     PROFILE_EXIT_LOCAL(function_run);
5066 }
5067 
5068 
5069 #ifdef HAVE_PYTHON
5070 
arg_list_compile_python(PyObject * bjam_signature,int * num_arguments)5071 static struct arg_list * arg_list_compile_python( PyObject * bjam_signature,
5072     int * num_arguments )
5073 {
5074     if ( bjam_signature )
5075     {
5076         struct argument_list_compiler c[ 1 ];
5077         struct arg_list * result;
5078         Py_ssize_t s;
5079         Py_ssize_t i;
5080         argument_list_compiler_init( c );
5081 
5082         s = PySequence_Size( bjam_signature );
5083         for ( i = 0; i < s; ++i )
5084         {
5085             struct argument_compiler arg_comp[ 1 ];
5086             struct arg_list arg;
5087             PyObject * v = PySequence_GetItem( bjam_signature, i );
5088             Py_ssize_t j;
5089             Py_ssize_t inner;
5090             argument_compiler_init( arg_comp );
5091 
5092             inner = PySequence_Size( v );
5093             for ( j = 0; j < inner; ++j )
5094                 argument_compiler_add( arg_comp, object_new( PyString_AsString(
5095                     PySequence_GetItem( v, j ) ) ), constant_builtin, -1 );
5096 
5097             arg = arg_compile_impl( arg_comp, constant_builtin, -1 );
5098             dynamic_array_push( c->args, arg );
5099             argument_compiler_free( arg_comp );
5100             Py_DECREF( v );
5101         }
5102 
5103         *num_arguments = c->args->size;
5104         result = (struct arg_list *)BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
5105         memcpy( result, c->args->data, c->args->size * sizeof( struct arg_list )
5106             );
5107         argument_list_compiler_free( c );
5108         return result;
5109     }
5110     *num_arguments = 0;
5111     return 0;
5112 }
5113 
function_python(PyObject * function,PyObject * bjam_signature)5114 FUNCTION * function_python( PyObject * function, PyObject * bjam_signature )
5115 {
5116     PYTHON_FUNCTION * result = (PYTHON_FUNCTION *)BJAM_MALLOC( sizeof( PYTHON_FUNCTION ) );
5117 
5118     result->base.type = FUNCTION_PYTHON;
5119     result->base.reference_count = 1;
5120     result->base.rulename = 0;
5121     result->base.formal_arguments = arg_list_compile_python( bjam_signature,
5122         &result->base.num_formal_arguments );
5123     Py_INCREF( function );
5124     result->python_function = function;
5125 
5126     return (FUNCTION *)result;
5127 }
5128 
5129 
argument_list_to_python(struct arg_list * formal,int formal_count,FUNCTION * function,FRAME * frame,PyObject * kw)5130 static void argument_list_to_python( struct arg_list * formal, int formal_count,
5131     FUNCTION * function, FRAME * frame, PyObject * kw )
5132 {
5133     LOL * all_actual = frame->args;
5134     int i;
5135 
5136     for ( i = 0; i < formal_count; ++i )
5137     {
5138         LIST * actual = lol_get( all_actual, i );
5139         LISTITER actual_iter = list_begin( actual );
5140         LISTITER const actual_end = list_end( actual );
5141         int j;
5142         for ( j = 0; j < formal[ i ].size; ++j )
5143         {
5144             struct argument * formal_arg = &formal[ i ].args[ j ];
5145             PyObject * value;
5146             LIST * l;
5147 
5148             switch ( formal_arg->flags )
5149             {
5150             case ARG_ONE:
5151                 if ( actual_iter == actual_end )
5152                     argument_error( "missing argument", function, frame,
5153                         formal_arg->arg_name );
5154                 type_check_range( formal_arg->type_name, actual_iter, list_next(
5155                     actual_iter ), frame, function, formal_arg->arg_name );
5156                 value = PyString_FromString( object_str( list_item( actual_iter
5157                     ) ) );
5158                 actual_iter = list_next( actual_iter );
5159                 break;
5160             case ARG_OPTIONAL:
5161                 if ( actual_iter == actual_end )
5162                     value = 0;
5163                 else
5164                 {
5165                     type_check_range( formal_arg->type_name, actual_iter,
5166                         list_next( actual_iter ), frame, function,
5167                         formal_arg->arg_name );
5168                     value = PyString_FromString( object_str( list_item(
5169                         actual_iter ) ) );
5170                     actual_iter = list_next( actual_iter );
5171                 }
5172                 break;
5173             case ARG_PLUS:
5174                 if ( actual_iter == actual_end )
5175                     argument_error( "missing argument", function, frame,
5176                         formal_arg->arg_name );
5177                 /* fallthrough */
5178             case ARG_STAR:
5179                 type_check_range( formal_arg->type_name, actual_iter,
5180                     actual_end, frame, function, formal_arg->arg_name );
5181                 l = list_copy_range( actual, actual_iter, actual_end );
5182                 value = list_to_python( l );
5183                 list_free( l );
5184                 actual_iter = actual_end;
5185                 break;
5186             case ARG_VARIADIC:
5187                 return;
5188             }
5189 
5190             if ( value )
5191             {
5192                 PyObject * key = PyString_FromString( object_str(
5193                     formal_arg->arg_name ) );
5194                 PyDict_SetItem( kw, key, value );
5195                 Py_DECREF( key );
5196                 Py_DECREF( value );
5197             }
5198         }
5199 
5200         if ( actual_iter != actual_end )
5201             argument_error( "extra argument", function, frame, list_item(
5202                 actual_iter ) );
5203     }
5204 
5205     for ( ; i < all_actual->count; ++i )
5206     {
5207         LIST * const actual = lol_get( all_actual, i );
5208         if ( !list_empty( actual ) )
5209             argument_error( "extra argument", function, frame, list_front(
5210                 actual ) );
5211     }
5212 }
5213 
5214 
5215 /* Given a Python object, return a string to use in Jam code instead of the said
5216  * object.
5217  *
5218  * If the object is a string, use the string value.
5219  * If the object implemenets __jam_repr__ method, use that.
5220  * Otherwise return 0.
5221  */
5222 
python_to_string(PyObject * value)5223 OBJECT * python_to_string( PyObject * value )
5224 {
5225     if ( PyString_Check( value ) )
5226         return object_new( PyString_AS_STRING( value ) );
5227 
5228     /* See if this instance defines the special __jam_repr__ method. */
5229     if ( PyInstance_Check( value )
5230         && PyObject_HasAttrString( value, "__jam_repr__" ) )
5231     {
5232         PyObject * repr = PyObject_GetAttrString( value, "__jam_repr__" );
5233         if ( repr )
5234         {
5235             PyObject * arguments2 = PyTuple_New( 0 );
5236             PyObject * value2 = PyObject_Call( repr, arguments2, 0 );
5237             Py_DECREF( repr );
5238             Py_DECREF( arguments2 );
5239             if ( PyString_Check( value2 ) )
5240                 return object_new( PyString_AS_STRING( value2 ) );
5241             Py_DECREF( value2 );
5242         }
5243     }
5244     return 0;
5245 }
5246 
5247 
python_module()5248 static module_t * python_module()
5249 {
5250     static module_t * python = 0;
5251     if ( !python )
5252         python = bindmodule( constant_python );
5253     return python;
5254 }
5255 
5256 
call_python_function(PYTHON_FUNCTION * function,FRAME * frame)5257 static LIST * call_python_function( PYTHON_FUNCTION * function, FRAME * frame )
5258 {
5259     LIST * result = 0;
5260     PyObject * arguments = 0;
5261     PyObject * kw = NULL;
5262     int i;
5263     PyObject * py_result;
5264     FRAME * prev_frame_before_python_call;
5265 
5266     if ( function->base.formal_arguments )
5267     {
5268         arguments = PyTuple_New( 0 );
5269         kw = PyDict_New();
5270         argument_list_to_python( function->base.formal_arguments,
5271             function->base.num_formal_arguments, &function->base, frame, kw );
5272     }
5273     else
5274     {
5275         arguments = PyTuple_New( frame->args->count );
5276         for ( i = 0; i < frame->args->count; ++i )
5277             PyTuple_SetItem( arguments, i, list_to_python( lol_get( frame->args,
5278                 i ) ) );
5279     }
5280 
5281     frame->module = python_module();
5282 
5283     prev_frame_before_python_call = frame_before_python_call;
5284     frame_before_python_call = frame;
5285     py_result = PyObject_Call( function->python_function, arguments, kw );
5286     frame_before_python_call = prev_frame_before_python_call;
5287     Py_DECREF( arguments );
5288     Py_XDECREF( kw );
5289     if ( py_result != NULL )
5290     {
5291         if ( PyList_Check( py_result ) )
5292         {
5293             int size = PyList_Size( py_result );
5294             int i;
5295             for ( i = 0; i < size; ++i )
5296             {
5297                 OBJECT * s = python_to_string( PyList_GetItem( py_result, i ) );
5298                 if ( !s )
5299                     err_printf(
5300                         "Non-string object returned by Python call.\n" );
5301                 else
5302                     result = list_push_back( result, s );
5303             }
5304         }
5305         else if ( py_result == Py_None )
5306         {
5307             result = L0;
5308         }
5309         else
5310         {
5311             OBJECT * const s = python_to_string( py_result );
5312             if ( s )
5313                 result = list_new( s );
5314             else
5315                 /* We have tried all we could. Return empty list. There are
5316                  * cases, e.g. feature.feature function that should return a
5317                  * value for the benefit of Python code and which also can be
5318                  * called by Jam code, where no sensible value can be returned.
5319                  * We cannot even emit a warning, since there would be a pile of
5320                  * them.
5321                  */
5322                 result = L0;
5323         }
5324 
5325         Py_DECREF( py_result );
5326     }
5327     else
5328     {
5329         PyErr_Print();
5330         err_printf( "Call failed\n" );
5331     }
5332 
5333     return result;
5334 }
5335 
5336 #endif
5337 
5338 
function_done(void)5339 void function_done( void )
5340 {
5341     BJAM_FREE( stack );
5342 }
5343