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