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