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