Ticket #7212: function.c

File function.c, 141.7 KB (added by Jurko Gospodnetic, 10 years ago)

Modified function.c Boost Jam source file based on revision [80313] that fixes the issue on one system.

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