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