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