[Tizen_6_build] Fixed 32-bit arm build with gcc 9
[platform/upstream/boost-jam.git] / builtins.c
1 /*
2  * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
6
7 #include "jam.h"
8
9 #include "lists.h"
10 #include "parse.h"
11 #include "builtins.h"
12 #include "rules.h"
13 #include "filesys.h"
14 #include "newstr.h"
15 #include "regexp.h"
16 #include "frames.h"
17 #include "hash.h"
18 #include "strings.h"
19 #include "pwd.h"
20 #include "pathsys.h"
21 #include "make.h"
22 #include "hdrmacro.h"
23 #include "compile.h"
24 #include "native.h"
25 #include "variable.h"
26 #include "timestamp.h"
27 #include "md5.h"
28 #include <ctype.h>
29
30 #if defined(USE_EXECUNIX)
31 # include <sys/types.h>
32 # include <sys/wait.h>
33 #else
34 /*
35   NT does not have wait() and associated macros, it uses the return value
36   of system() instead. Status code group are documented at
37   http://msdn.microsoft.com/en-gb/library/ff565436.aspx
38 */
39 # define WIFEXITED(w)  (((w) & 0XFFFFFF00) == 0)
40 # define WEXITSTATUS(w)(w)
41 #endif
42
43 /*
44  * builtins.c - builtin jam rules
45  *
46  * External routines:
47  *
48  *  load_builtin() - define builtin rules
49  *
50  * Internal routines:
51  *
52  *  builtin_depends() - DEPENDS/INCLUDES rule.
53  *  builtin_echo() - ECHO rule.
54  *  builtin_exit() - EXIT rule.
55  *  builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule.
56  *  builtin_glob() - GLOB rule.
57  *  builtin_match() - MATCH rule.
58  *
59  * 01/10/01 (seiwald) - split from compile.c
60  */
61
62
63 /*
64  * compile_builtin() - define builtin rules
65  */
66
67 #define P0 (PARSE *)0
68 #define C0 (char *)0
69
70 #if defined( OS_NT ) || defined( OS_CYGWIN )
71     LIST * builtin_system_registry      ( PARSE *, FRAME * );
72     LIST * builtin_system_registry_names( PARSE *, FRAME * );
73 #endif
74
75 int glob( char * s, char * c );
76
77 void backtrace        ( FRAME * );
78 void backtrace_line   ( FRAME * );
79 void print_source_line( PARSE * );
80
81
82 RULE * bind_builtin( char * name, LIST * (* f)( PARSE *, FRAME * ), int flags, char * * args )
83 {
84     argument_list* arg_list = 0;
85
86     if ( args )
87     {
88         arg_list = args_new();
89         lol_build( arg_list->data, args );
90     }
91
92     return new_rule_body( root_module(), name, arg_list,
93                           parse_make( f, P0, P0, P0, C0, C0, flags ), 1 );
94 }
95
96
97 RULE * duplicate_rule( char * name, RULE * other )
98 {
99     return import_rule( other, root_module(), name );
100 }
101
102
103 void load_builtins()
104 {
105     duplicate_rule( "Always",
106       bind_builtin( "ALWAYS",
107                     builtin_flags, T_FLAG_TOUCHED, 0 ) );
108
109     duplicate_rule( "Depends",
110       bind_builtin( "DEPENDS",
111                     builtin_depends, 0, 0 ) );
112
113     duplicate_rule( "echo",
114     duplicate_rule( "Echo",
115       bind_builtin( "ECHO",
116                     builtin_echo, 0, 0 ) ) );
117
118     {
119         char * args[] = { "message", "*", ":", "result-value", "?", 0 };
120         duplicate_rule( "exit",
121         duplicate_rule( "Exit",
122           bind_builtin( "EXIT",
123                         builtin_exit, 0, args ) ) );
124     }
125
126     {
127         char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
128         duplicate_rule( "Glob",
129                         bind_builtin( "GLOB", builtin_glob, 0, args ) );
130     }
131
132     {
133         char * args[] = { "patterns", "*", 0 };
134         bind_builtin( "GLOB-RECURSIVELY",
135                       builtin_glob_recursive, 0, args );
136     }
137
138     duplicate_rule( "Includes",
139       bind_builtin( "INCLUDES",
140                     builtin_depends, 1, 0 ) );
141
142     {
143         char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
144         bind_builtin( "REBUILDS",
145                       builtin_rebuilds, 0, args );
146     }
147
148     duplicate_rule( "Leaves",
149       bind_builtin( "LEAVES",
150                     builtin_flags, T_FLAG_LEAVES, 0 ) );
151
152     duplicate_rule( "Match",
153       bind_builtin( "MATCH",
154                     builtin_match, 0, 0 ) );
155
156     {
157         char * args[] = { "string", ":", "delimiters" };
158         bind_builtin( "SPLIT_BY_CHARACTERS", 
159                       builtin_split_by_characters, 0, 0 );
160     }
161
162     duplicate_rule( "NoCare",
163       bind_builtin( "NOCARE",
164                     builtin_flags, T_FLAG_NOCARE, 0 ) );
165
166     duplicate_rule( "NOTIME",
167     duplicate_rule( "NotFile",
168       bind_builtin( "NOTFILE",
169                     builtin_flags, T_FLAG_NOTFILE, 0 ) ) );
170
171     duplicate_rule( "NoUpdate",
172       bind_builtin( "NOUPDATE",
173                     builtin_flags, T_FLAG_NOUPDATE, 0 ) );
174
175     duplicate_rule( "Temporary",
176       bind_builtin( "TEMPORARY",
177                     builtin_flags, T_FLAG_TEMP, 0 ) );
178
179       bind_builtin( "ISFILE",
180                     builtin_flags, T_FLAG_ISFILE, 0 );
181
182     duplicate_rule( "HdrMacro",
183       bind_builtin( "HDRMACRO",
184                     builtin_hdrmacro, 0, 0 ) );
185
186     /* FAIL_EXPECTED is used to indicate that the result of a target build
187      * action should be inverted (ok <=> fail) this can be useful when
188      * performing test runs from Jamfiles.
189      */
190       bind_builtin( "FAIL_EXPECTED",
191                     builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
192
193       bind_builtin( "RMOLD",
194                     builtin_flags, T_FLAG_RMOLD, 0 );
195
196       {
197           char * args[] = { "targets", "*", 0 };
198           bind_builtin( "UPDATE",
199                         builtin_update, 0, args );
200       }
201
202       {
203           char * args[] = { "targets", "*", 
204                             ":", "log", "?",
205                             ":", "ignore-minus-n", "?", 
206                             ":", "ignore-minus-q", "?", 0 };
207           bind_builtin( "UPDATE_NOW",
208                         builtin_update_now, 0, args );
209       }
210
211       {
212           char * args[] = { "string", "pattern", "replacements", "+", 0 };
213           duplicate_rule( "subst",
214             bind_builtin( "SUBST",
215                           builtin_subst, 0, args ) );
216       }
217
218       {
219           char * args[] = { "module", "?", 0 };
220           bind_builtin( "RULENAMES",
221                          builtin_rulenames, 0, args );
222       }
223
224
225       {
226           char * args[] = { "module", "?", 0 };
227           bind_builtin( "VARNAMES",
228                          builtin_varnames, 0, args );
229       }
230
231       {
232           char * args[] = { "module", "?", 0 };
233           bind_builtin( "DELETE_MODULE",
234                          builtin_delete_module, 0, args );
235       }
236
237       {
238           char * args[] = { "source_module", "?",
239                             ":", "source_rules", "*",
240                             ":", "target_module", "?",
241                             ":", "target_rules", "*",
242                             ":", "localize", "?", 0 };
243           bind_builtin( "IMPORT",
244                         builtin_import, 0, args );
245       }
246
247       {
248           char * args[] = { "module", "?", ":", "rules", "*", 0 };
249           bind_builtin( "EXPORT",
250                         builtin_export, 0, args );
251       }
252
253       {
254           char * args[] = { "levels", "?", 0 };
255           bind_builtin( "CALLER_MODULE",
256                          builtin_caller_module, 0, args );
257       }
258
259       {
260           char * args[] = { "levels", "?", 0 };
261           bind_builtin( "BACKTRACE",
262                         builtin_backtrace, 0, args );
263       }
264
265       {
266           char * args[] = { 0 };
267           bind_builtin( "PWD",
268                         builtin_pwd, 0, args );
269       }
270
271       {
272           char * args[] = { "target", "*", ":", "path", "*", 0 };
273           bind_builtin( "SEARCH_FOR_TARGET",
274                         builtin_search_for_target, 0, args );
275       }
276
277       {
278           char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
279           bind_builtin( "IMPORT_MODULE",
280                         builtin_import_module, 0, args );
281       }
282
283       {
284           char * args[] = { "module", "?", 0 };
285           bind_builtin( "IMPORTED_MODULES",
286                         builtin_imported_modules, 0, args );
287       }
288
289       {
290           char * args[] = { "instance_module", ":", "class_module", 0 };
291           bind_builtin( "INSTANCE",
292                         builtin_instance, 0, args );
293       }
294
295       {
296           char * args[] = { "sequence", "*", 0 };
297           bind_builtin( "SORT",
298                         builtin_sort, 0, args );
299       }
300
301       {
302           char * args[] = { "path_parts", "*", 0 };
303           bind_builtin( "NORMALIZE_PATH",
304                         builtin_normalize_path, 0, args );
305       }
306
307       {
308           char * args[] = { "args", "*", 0 };
309           bind_builtin( "CALC",
310                         builtin_calc, 0, args );
311       }
312
313       {
314           char * args[] = { "module", ":", "rule", 0 };
315           bind_builtin( "NATIVE_RULE",
316                         builtin_native_rule, 0, args );
317       }
318
319       {
320           char * args[] = { "module", ":", "rule", ":", "version", 0 };
321           bind_builtin( "HAS_NATIVE_RULE",
322                         builtin_has_native_rule, 0, args );
323       }
324
325       {
326           char * args[] = { "module", "*", 0 };
327           bind_builtin( "USER_MODULE",
328                         builtin_user_module, 0, args );
329       }
330
331       {
332           char * args[] = { 0 };
333           bind_builtin( "NEAREST_USER_LOCATION",
334                         builtin_nearest_user_location, 0, args );
335       }
336
337       {
338           char * args[] = { "file", 0 };
339           bind_builtin( "CHECK_IF_FILE",
340                         builtin_check_if_file, 0, args );
341       }
342
343 #ifdef HAVE_PYTHON
344       {
345           char * args[] = { "python-module", ":", "function", ":",
346                             "jam-module", ":", "rule-name", 0 };
347           bind_builtin( "PYTHON_IMPORT_RULE",
348                         builtin_python_import_rule, 0, args );
349       }
350 #endif
351
352 # if defined( OS_NT ) || defined( OS_CYGWIN )
353       {
354           char * args[] = { "key_path", ":", "data", "?", 0 };
355           bind_builtin( "W32_GETREG",
356                         builtin_system_registry, 0, args );
357       }
358
359       {
360           char * args[] = { "key_path", ":", "result-type", 0 };
361           bind_builtin( "W32_GETREGNAMES",
362                         builtin_system_registry_names, 0, args );
363       }
364 # endif
365
366       {
367           char * args[] = { "command", ":", "*", 0 };
368           duplicate_rule( "SHELL",
369             bind_builtin( "COMMAND",
370                           builtin_shell, 0, args ) );
371       }
372
373       {
374           char * args[] = { "string", 0 };
375           bind_builtin( "MD5",
376                         builtin_md5, 0, args ) ;
377       }
378
379       {
380           char * args[] = { "name", ":", "mode", 0 };
381           bind_builtin( "FILE_OPEN",
382                         builtin_file_open, 0, args );
383       }
384
385       {
386           char * args[] = { "string", ":", "width", 0 };
387           bind_builtin( "PAD",
388                         builtin_pad, 0, args );
389       }
390
391       {
392           char * args[] = { "targets", "*", 0 };
393           bind_builtin( "PRECIOUS",
394                         builtin_precious, 0, args );
395       }
396
397       {
398           char * args [] = { 0 };
399           bind_builtin( "SELF_PATH", builtin_self_path, 0, args );
400       }
401
402       {
403           char * args [] = { "path", 0 };
404           bind_builtin( "MAKEDIR", builtin_makedir, 0, args );
405       }
406
407       /* Initialize builtin modules. */
408       init_set();
409       init_path();
410       init_regex();
411       init_property_set();
412       init_sequence();
413       init_order();
414 }
415
416
417 /*
418  * builtin_calc() - CALC rule.
419  *
420  * The CALC rule performs simple mathematical operations on two arguments.
421  */
422
423 LIST * builtin_calc( PARSE * parse, FRAME * frame )
424 {
425     LIST * arg = lol_get( frame->args, 0 );
426
427     LIST * result = 0;
428     long lhs_value;
429     long rhs_value;
430     long result_value;
431     char buffer [ 16 ];
432     char const * lhs;
433     char const * op;
434     char const * rhs;
435
436     if ( arg == 0 ) return L0;
437     lhs = arg->string;
438
439     arg = list_next( arg );
440     if ( arg == 0 ) return L0;
441     op = arg->string;
442
443     arg = list_next( arg );
444     if ( arg == 0 ) return L0;
445     rhs = arg->string;
446
447     lhs_value = atoi( lhs );
448     rhs_value = atoi( rhs );
449
450     if ( strcmp( "+", op ) == 0 )
451     {
452         result_value = lhs_value + rhs_value;
453     }
454     else if ( strcmp( "-", op ) == 0 )
455     {
456         result_value = lhs_value - rhs_value;
457     }
458     else
459     {
460         return L0;
461     }
462
463     sprintf( buffer, "%ld", result_value );
464     result = list_new( result, newstr( buffer ) );
465     return result;
466 }
467
468
469 /*
470  * builtin_depends() - DEPENDS/INCLUDES rule.
471  *
472  * The DEPENDS/INCLUDES builtin rule appends each of the listed sources on the
473  * dependency/includes list of each of the listed targets. It binds both the
474  * targets and sources as TARGETs.
475  */
476
477 LIST * builtin_depends( PARSE * parse, FRAME * frame )
478 {
479     LIST * targets = lol_get( frame->args, 0 );
480     LIST * sources = lol_get( frame->args, 1 );
481     LIST * l;
482
483     for ( l = targets; l; l = list_next( l ) )
484     {
485         TARGET * t = bindtarget( l->string );
486
487         /* If doing INCLUDES, switch to the TARGET's include */
488         /* TARGET, creating it if needed.  The internal include */
489         /* TARGET shares the name of its parent. */
490
491         if ( parse->num )
492         {
493             if ( !t->includes )
494             {
495                 t->includes = copytarget( t );
496                 t->includes->original_target = t;
497             }
498             t = t->includes;
499         }
500
501         t->depends = targetlist( t->depends, sources );
502     }
503
504     /* Enter reverse links */
505     for ( l = sources; l; l = list_next( l ) )
506     {
507         TARGET * s = bindtarget( l->string );
508         s->dependants = targetlist( s->dependants, targets );
509     }
510
511     return L0;
512 }
513
514
515 /*
516  * builtin_rebuilds() - REBUILDS rule.
517  *
518  * The REBUILDS builtin rule appends each of the listed rebuild-targets in its
519  * 2nd argument on the rebuilds list of each of the listed targets in its first
520  * argument.
521  */
522
523 LIST * builtin_rebuilds( PARSE * parse, FRAME * frame )
524 {
525     LIST * targets = lol_get( frame->args, 0 );
526     LIST * rebuilds = lol_get( frame->args, 1 );
527     LIST * l;
528
529     for ( l = targets; l; l = list_next( l ) )
530     {
531         TARGET * t = bindtarget( l->string );
532         t->rebuilds = targetlist( t->rebuilds, rebuilds );
533     }
534
535     return L0;
536 }
537
538
539 /*
540  * builtin_echo() - ECHO rule.
541  *
542  * The ECHO builtin rule echoes the targets to the user. No other actions are
543  * taken.
544  */
545
546 LIST * builtin_echo( PARSE * parse, FRAME * frame )
547 {
548     list_print( lol_get( frame->args, 0 ) );
549     printf( "\n" );
550     fflush( stdout );
551     return L0;
552 }
553
554
555 /*
556  * builtin_exit() - EXIT rule.
557  *
558  * The EXIT builtin rule echoes the targets to the user and exits the program
559  * with a failure status.
560  */
561
562 LIST * builtin_exit( PARSE * parse, FRAME * frame )
563 {
564     list_print( lol_get( frame->args, 0 ) );
565     printf( "\n" );
566     if ( lol_get( frame->args, 1 ) )
567     {
568         exit( atoi( lol_get( frame->args, 1 )->string ) );
569     }
570     else
571     {
572         exit( EXITBAD );  /* yeech */
573     }
574     return L0;
575 }
576
577
578 /*
579  * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule.
580  *
581  * Builtin_flags() marks the target with the appropriate flag, for use by make0().
582  * It binds each target as a TARGET.
583  */
584
585 LIST * builtin_flags( PARSE * parse, FRAME * frame )
586 {
587     LIST * l = lol_get( frame->args, 0 );
588     for ( ; l; l = list_next( l ) )
589         bindtarget( l->string )->flags |= parse->num;
590     return L0;
591 }
592
593
594 /*
595  * builtin_globbing() - GLOB rule.
596  */
597
598 struct globbing
599 {
600     LIST * patterns;
601     LIST * results;
602     LIST * case_insensitive;
603 };
604
605
606 static void downcase_inplace( char * p )
607 {
608     for ( ; *p; ++p )
609         *p = tolower( *p );
610 }
611
612
613 static void builtin_glob_back
614 (
615     void * closure,
616     char * file,
617     int    status,
618     time_t time
619 )
620 {
621     PROFILE_ENTER( BUILTIN_GLOB_BACK );
622
623     struct globbing * globbing = (struct globbing *)closure;
624     LIST            * l;
625     PATHNAME          f;
626     string            buf[ 1 ];
627
628     /* Null out directory for matching. We wish we had file_dirscan() pass up a
629      * PATHNAME.
630      */
631     path_parse( file, &f );
632     f.f_dir.len = 0;
633
634     /* For globbing, we unconditionally ignore current and parent directory
635      * items. Since they items always exist, there is no reason why caller of
636      * GLOB would want to see them. We could also change file_dirscan(), but
637      * then paths with embedded "." and ".." would not work anywhere.
638     */
639     if ( !strcmp( f.f_base.ptr, "." ) || !strcmp( f.f_base.ptr, ".." ) )
640     {
641         PROFILE_EXIT( BUILTIN_GLOB_BACK );
642         return;
643     }
644
645     string_new( buf );
646     path_build( &f, buf, 0 );
647
648     if ( globbing->case_insensitive )
649         downcase_inplace( buf->value );
650
651     for ( l = globbing->patterns; l; l = l->next )
652     {
653         if ( !glob( l->string, buf->value ) )
654         {
655             globbing->results = list_new( globbing->results, newstr( file ) );
656             break;
657         }
658     }
659
660     string_free( buf );
661
662     PROFILE_EXIT( BUILTIN_GLOB_BACK );
663 }
664
665
666 static LIST * downcase_list( LIST * in )
667 {
668     LIST * result = 0;
669
670     string s[ 1 ];
671     string_new( s );
672
673     while ( in )
674     {
675         string_copy( s, in->string );
676         downcase_inplace( s->value );
677         result = list_append( result, list_new( 0, newstr( s->value ) ) );
678         in = in->next;
679     }
680
681     string_free( s );
682     return result;
683 }
684
685
686 LIST * builtin_glob( PARSE * parse, FRAME * frame )
687 {
688     LIST * l = lol_get( frame->args, 0 );
689     LIST * r = lol_get( frame->args, 1 );
690
691     struct globbing globbing;
692
693     globbing.results = L0;
694     globbing.patterns = r;
695
696     globbing.case_insensitive
697 # if defined( OS_NT ) || defined( OS_CYGWIN )
698        = l;  /* Always case-insensitive if any files can be found. */
699 # else
700        = lol_get( frame->args, 2 );
701 # endif
702
703     if ( globbing.case_insensitive )
704         globbing.patterns = downcase_list( r );
705
706     for ( ; l; l = list_next( l ) )
707         file_dirscan( l->string, builtin_glob_back, &globbing );
708
709     if ( globbing.case_insensitive )
710         list_free( globbing.patterns );
711
712     return globbing.results;
713 }
714
715
716 static int has_wildcards( char const * str )
717 {
718     size_t const index = strcspn( str, "[]*?" );
719     return str[ index ] == '\0' ? 0 : 1;
720 }
721
722
723 /*
724  * If 'file' exists, append 'file' to 'list'. Returns 'list'.
725  */
726
727 static LIST * append_if_exists( LIST * list, char * file )
728 {
729     time_t time;
730     timestamp( file, &time );
731     return time > 0
732         ? list_new( list, newstr( file ) )
733         : list;
734 }
735
736
737 LIST * glob1( char * dirname, char * pattern )
738 {
739     LIST * plist = list_new( L0, pattern );
740     struct globbing globbing;
741
742     globbing.results = L0;
743     globbing.patterns = plist;
744
745     globbing.case_insensitive
746 # if defined( OS_NT ) || defined( OS_CYGWIN )
747        = plist;  /* always case-insensitive if any files can be found */
748 # else
749        = L0;
750 # endif
751
752     if ( globbing.case_insensitive )
753         globbing.patterns = downcase_list( plist );
754
755     file_dirscan( dirname, builtin_glob_back, &globbing );
756
757     if ( globbing.case_insensitive )
758         list_free( globbing.patterns );
759
760     list_free( plist );
761
762     return globbing.results;
763 }
764
765
766 LIST * glob_recursive( char * pattern )
767 {
768     LIST * result = L0;
769
770     /* Check if there's metacharacters in pattern */
771     if ( !has_wildcards( pattern ) )
772     {
773         /* No metacharacters. Check if the path exists. */
774         result = append_if_exists(result, pattern);
775     }
776     else
777     {
778         /* Have metacharacters in the pattern. Split into dir/name. */
779         PATHNAME path[ 1 ];
780         path_parse( pattern, path );
781
782         if ( path->f_dir.ptr )
783         {
784             LIST * dirs = L0;
785             string dirname[ 1 ];
786             string basename[ 1 ];
787             string_new( dirname );
788             string_new( basename );
789
790             string_append_range( dirname, path->f_dir.ptr,
791                                 path->f_dir.ptr + path->f_dir.len );
792
793             path->f_grist.ptr = 0;
794             path->f_grist.len = 0;
795             path->f_dir.ptr = 0;
796             path->f_dir.len = 0;
797             path_build( path, basename, 0 );
798
799             dirs =  has_wildcards( dirname->value )
800                 ? glob_recursive( dirname->value )
801                 : list_new( dirs, dirname->value );
802
803             if ( has_wildcards( basename->value ) )
804             {
805                 for ( ; dirs; dirs = dirs->next )
806                     result = list_append( result, glob1( dirs->string,
807                         basename->value ) );
808             }
809             else
810             {
811                 string file_string[ 1 ];
812                 string_new( file_string );
813
814                 /* No wildcard in basename. */
815                 for ( ; dirs; dirs = dirs->next )
816                 {
817                     path->f_dir.ptr = dirs->string;
818                     path->f_dir.len = strlen( dirs->string );
819                     path_build( path, file_string, 0 );
820
821                     result = append_if_exists( result, file_string->value );
822
823                     string_truncate( file_string, 0 );
824                 }
825
826                 string_free( file_string );
827             }
828
829             string_free( dirname );
830             string_free( basename );
831         }
832         else
833         {
834             /** No directory, just a pattern. */
835             result = list_append( result, glob1( ".", pattern ) );
836         }
837     }
838
839     return result;
840 }
841
842
843 LIST * builtin_glob_recursive( PARSE * parse, FRAME * frame )
844 {
845     LIST * result = L0;
846     LIST * l = lol_get( frame->args, 0 );
847     for ( ; l; l = l->next )
848         result = list_append( result, glob_recursive( l->string ) );
849     return result;
850 }
851
852
853 /*
854  * builtin_match() - MATCH rule, regexp matching.
855  */
856
857 LIST * builtin_match( PARSE * parse, FRAME * frame )
858 {
859     LIST * l;
860     LIST * r;
861     LIST * result = 0;
862
863     string buf[ 1 ];
864     string_new( buf );
865
866     /* For each pattern */
867
868     for ( l = lol_get( frame->args, 0 ); l; l = l->next )
869     {
870         /* Result is cached and intentionally never freed. */
871         regexp * re = regex_compile( l->string );
872
873         /* For each string to match against. */
874         for ( r = lol_get( frame->args, 1 ); r; r = r->next )
875         {
876             if ( regexec( re, r->string ) )
877             {
878                 int i;
879                 int top;
880
881                 /* Find highest parameter */
882
883                 for ( top = NSUBEXP; top-- > 1; )
884                     if ( re->startp[ top ] )
885                         break;
886
887                 /* And add all parameters up to highest onto list. */
888                 /* Must have parameters to have results! */
889                 for ( i = 1; i <= top; ++i )
890                 {
891                     string_append_range( buf, re->startp[ i ], re->endp[ i ] );
892                     result = list_new( result, newstr( buf->value ) );
893                     string_truncate( buf, 0 );
894                 }
895             }
896         }
897     }
898
899     string_free( buf );
900     return result;
901 }
902
903 LIST * builtin_split_by_characters( PARSE * parse, FRAME * frame )
904 {
905     LIST * l1 = lol_get( frame->args, 0 );
906     LIST * l2 = lol_get( frame->args, 1 );
907
908     LIST * result = 0;
909
910     char* s = strdup (l1->string);
911     char* delimiters = l2->string;
912     char* t;
913
914     t = strtok (s, delimiters);
915     while (t)
916     {
917         result = list_new(result, newstr(t));
918         t = strtok (NULL, delimiters);
919     }
920
921     free (s);
922
923     return result;
924 }
925
926 LIST * builtin_hdrmacro( PARSE * parse, FRAME * frame )
927 {
928   LIST * l = lol_get( frame->args, 0 );
929
930   for ( ; l; l = list_next( l ) )
931   {
932     TARGET * t = bindtarget( l->string );
933
934     /* Scan file for header filename macro definitions. */
935     if ( DEBUG_HEADER )
936         printf( "scanning '%s' for header file macro definitions\n",
937             l->string );
938
939     macro_headers( t );
940   }
941
942   return L0;
943 }
944
945
946 /*
947  * builtin_rulenames() - RULENAMES ( MODULE ? ).
948  *
949  * Returns a list of the non-local rule names in the given MODULE. If MODULE is
950  * not supplied, returns the list of rule names in the global module.
951  */
952
953 static void add_rule_name( void * r_, void * result_ )
954 {
955     RULE * r = (RULE *)r_;
956     LIST * * result = (LIST * *)result_;
957     if ( r->exported )
958         *result = list_new( *result, copystr( r->name ) );
959 }
960
961
962 LIST * builtin_rulenames( PARSE * parse, FRAME * frame )
963 {
964     LIST * arg0 = lol_get( frame->args, 0 );
965     LIST * result = L0;
966     module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
967
968     if ( source_module->rules )
969         hashenumerate( source_module->rules, add_rule_name, &result );
970     return result;
971 }
972
973
974 /*
975  * builtin_varnames() - VARNAMES ( MODULE ? ).
976  *
977  * Returns a list of the variable names in the given MODULE. If MODULE is not
978  * supplied, returns the list of variable names in the global module.
979  */
980
981 /* helper function for builtin_varnames(), below. Used with hashenumerate, will
982  * prepend the key of each element to the list
983  */
984 static void add_hash_key( void * np, void * result_ )
985 {
986     LIST * * result = (LIST * *)result_;
987     *result = list_new( *result, copystr( *(char * *)np ) );
988 }
989
990
991 static struct hash * get_running_module_vars()
992 {
993     struct hash * dummy;
994     struct hash * vars = NULL;
995     /* Get the global variables pointer (that of the currently running module).
996      */
997     var_hash_swap( &vars );
998     dummy = vars;
999     /* Put the global variables pointer in its right place. */
1000     var_hash_swap( &dummy );
1001     return vars;
1002 }
1003
1004
1005 LIST * builtin_varnames( PARSE * parse, FRAME * frame )
1006 {
1007     LIST * arg0 = lol_get( frame->args, 0 );
1008     LIST * result = L0;
1009     module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
1010
1011     /* The running module _always_ has its 'variables' member set to NULL due to
1012      * the way enter_module() and var_hash_swap() work.
1013      */
1014     struct hash * vars = source_module == frame->module
1015         ? get_running_module_vars()
1016         : source_module->variables;
1017
1018     if ( vars )
1019         hashenumerate( vars, add_hash_key, &result );
1020     return result;
1021 }
1022
1023
1024 /*
1025  * builtin_delete_module() - MODULE ?.
1026  *
1027  * Clears all rules and variables from the given module.
1028  */
1029
1030 LIST * builtin_delete_module( PARSE * parse, FRAME * frame )
1031 {
1032     LIST     * arg0 = lol_get( frame->args, 0 );
1033     LIST     * result = L0;
1034     module_t * source_module = bindmodule( arg0 ? arg0->string : 0 );
1035     delete_module( source_module );
1036     return result;
1037 }
1038
1039
1040 static void unknown_rule( FRAME * frame, char * key, char * module_name, char * rule_name )
1041 {
1042     backtrace_line( frame->prev );
1043     printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
1044     backtrace( frame->prev );
1045     exit( 1 );
1046 }
1047
1048
1049 /*
1050  * builtin_import() - IMPORT
1051  * (
1052  *     SOURCE_MODULE ? :
1053  *     SOURCE_RULES  * :
1054  *     TARGET_MODULE ? :
1055  *     TARGET_RULES  * :
1056  *     LOCALIZE      ?
1057  * )
1058  *
1059  * The IMPORT rule imports rules from the SOURCE_MODULE into the TARGET_MODULE
1060  * as local rules. If either SOURCE_MODULE or TARGET_MODULE is not supplied, it
1061  * refers to the global module. SOURCE_RULES specifies which rules from the
1062  * SOURCE_MODULE to import; TARGET_RULES specifies the names to give those rules
1063  * in TARGET_MODULE. If SOURCE_RULES contains a name which doesn't correspond to
1064  * a rule in SOURCE_MODULE, or if it contains a different number of items than
1065  * TARGET_RULES, an error is issued. If LOCALIZE is specified, the rules will be
1066  * executed in TARGET_MODULE, with corresponding access to its module local
1067  * variables.
1068  */
1069
1070 LIST * builtin_import( PARSE * parse, FRAME * frame )
1071 {
1072     LIST * source_module_list = lol_get( frame->args, 0 );
1073     LIST * source_rules       = lol_get( frame->args, 1 );
1074     LIST * target_module_list = lol_get( frame->args, 2 );
1075     LIST * target_rules       = lol_get( frame->args, 3 );
1076     LIST * localize           = lol_get( frame->args, 4 );
1077
1078     module_t * target_module =
1079         bindmodule( target_module_list ? target_module_list->string : 0 );
1080     module_t * source_module =
1081         bindmodule( source_module_list ? source_module_list->string : 0 );
1082
1083     LIST * source_name;
1084     LIST * target_name;
1085
1086     for ( source_name = source_rules, target_name = target_rules;
1087           source_name && target_name;
1088           source_name = list_next( source_name ),
1089           target_name = list_next( target_name ) )
1090     {
1091         RULE   r_;
1092         RULE * r = &r_;
1093         RULE * imported;
1094         r_.name = source_name->string;
1095
1096         if ( !source_module->rules ||
1097             !hashcheck( source_module->rules, (HASHDATA * *)&r ) )
1098             unknown_rule( frame, "IMPORT", source_module->name, r_.name );
1099
1100         imported = import_rule( r, target_module, target_name->string );
1101         if ( localize )
1102             imported->module = target_module;
1103         /* This rule is really part of some other module. Just refer to it here,
1104          * but do not let it out.
1105          */
1106         imported->exported = 0;
1107     }
1108
1109     if ( source_name || target_name )
1110     {
1111         backtrace_line( frame->prev );
1112         printf( "import error: length of source and target rule name lists don't match!\n" );
1113         printf( "    source: " );
1114         list_print( source_rules );
1115         printf( "\n    target: " );
1116         list_print( target_rules );
1117         printf( "\n" );
1118         backtrace( frame->prev );
1119         exit( 1 );
1120     }
1121
1122     return L0;
1123 }
1124
1125
1126 /*
1127  * builtin_export() - EXPORT ( MODULE ? : RULES * ).
1128  *
1129  * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local (and thus
1130  * exportable). If an element of RULES does not name a rule in MODULE, an error
1131  * is issued.
1132  */
1133
1134 LIST * builtin_export( PARSE * parse, FRAME * frame )
1135 {
1136     LIST     * module_list = lol_get( frame->args, 0 );
1137     LIST     * rules       = lol_get( frame->args, 1 );
1138     module_t * m           = bindmodule( module_list ? module_list->string : 0 );
1139
1140     for ( ; rules; rules = list_next( rules ) )
1141     {
1142         RULE   r_;
1143         RULE * r = &r_;
1144         r_.name = rules->string;
1145
1146         if ( !m->rules || !hashcheck( m->rules, (HASHDATA * *)&r ) )
1147             unknown_rule( frame, "EXPORT", m->name, r_.name );
1148
1149         r->exported = 1;
1150     }
1151     return L0;
1152 }
1153
1154
1155 /*
1156  * get_source_line() - Retrieve the file and line number that should be
1157  * indicated for a given procedure in debug output or an error backtrace.
1158  */
1159
1160 static void get_source_line( PARSE * procedure, char * * file, int * line )
1161 {
1162     if ( procedure )
1163     {
1164         char * f = procedure->file;
1165         int    l = procedure->line;
1166         if ( !strcmp( f, "+" ) )
1167         {
1168             f = "jambase.c";
1169             l += 3;
1170         }
1171         *file = f;
1172         *line = l;
1173     }
1174     else
1175     {
1176         *file = "(builtin)";
1177         *line = -1;
1178     }
1179 }
1180
1181
1182 void print_source_line( PARSE * p )
1183 {
1184     char * file;
1185     int    line;
1186
1187     get_source_line( p, &file, &line );
1188     if ( line < 0 )
1189         printf( "(builtin):" );
1190     else
1191         printf( "%s:%d:", file, line );
1192 }
1193
1194
1195 /*
1196  * backtrace_line() - print a single line of error backtrace for the given
1197  * frame.
1198  */
1199
1200 void backtrace_line( FRAME * frame )
1201 {
1202     if ( frame == 0 )
1203     {
1204         printf( "(no frame):" );
1205     }
1206     else
1207     {
1208         print_source_line( frame->procedure );
1209         printf( " in %s\n", frame->rulename );
1210     }
1211 }
1212
1213
1214 /*
1215  * backtrace() - Print the entire backtrace from the given frame to the Jambase
1216  * which invoked it.
1217  */
1218
1219 void backtrace( FRAME * frame )
1220 {
1221     if ( !frame ) return;
1222     while ( ( frame = frame->prev ) )
1223         backtrace_line( frame );
1224 }
1225
1226
1227 /*
1228  * builtin_backtrace() - A Jam version of the backtrace function, taking no
1229  * arguments and returning a list of quadruples: FILENAME LINE MODULE. RULENAME
1230  * describing each frame. Note that the module-name is always followed by a
1231  * period.
1232  */
1233
1234 LIST * builtin_backtrace( PARSE * parse, FRAME * frame )
1235 {
1236     LIST * levels_arg = lol_get( frame->args, 0 );
1237     int levels = levels_arg ? atoi( levels_arg->string ) : ( (unsigned int)(-1) >> 1 ) ;
1238
1239     LIST * result = L0;
1240     for ( ; ( frame = frame->prev ) && levels ; --levels )
1241     {
1242         char * file;
1243         int    line;
1244         char   buf[32];
1245         get_source_line( frame->procedure, &file, &line );
1246         sprintf( buf, "%d", line );
1247         result = list_new( result, newstr( file ) );
1248         result = list_new( result, newstr( buf ) );
1249         result = list_new( result, newstr( frame->module->name ) );
1250         result = list_new( result, newstr( frame->rulename ) );
1251     }
1252     return result;
1253 }
1254
1255
1256 /*
1257  * builtin_caller_module() - CALLER_MODULE ( levels ? )
1258  *
1259  * If levels is not supplied, returns the name of the module of the rule which
1260  * called the one calling this one. If levels is supplied, it is interpreted as
1261  * an integer specifying a number of additional levels of call stack to traverse
1262  * in order to locate the module in question. If no such module exists, returns
1263  * the empty list. Also returns the empty list when the module in question is
1264  * the global module. This rule is needed for implementing module import
1265  * behavior.
1266  */
1267
1268 LIST * builtin_caller_module( PARSE * parse, FRAME * frame )
1269 {
1270     LIST * levels_arg = lol_get( frame->args, 0 );
1271     int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
1272
1273     int i;
1274     for ( i = 0; ( i < levels + 2 ) && frame->prev; ++i )
1275         frame = frame->prev;
1276
1277     if ( frame->module == root_module() )
1278         return L0;
1279
1280     {
1281         LIST * result;
1282         string name;
1283         string_copy( &name, frame->module->name );
1284         string_pop_back( &name );
1285         result = list_new( L0, newstr(name.value) );
1286         string_free( &name );
1287         return result;
1288     }
1289 }
1290
1291
1292 /*
1293  * Return the current working directory.
1294  *
1295  * Usage: pwd = [ PWD ] ;
1296  */
1297
1298 LIST * builtin_pwd( PARSE * parse, FRAME * frame )
1299 {
1300     return pwd();
1301 }
1302
1303
1304 /*
1305  * Adds targets to the list of target that jam will attempt to update.
1306  */
1307
1308 LIST * builtin_update( PARSE * parse, FRAME * frame )
1309 {
1310     LIST * result = list_copy( L0, targets_to_update() );
1311     LIST * arg1 = lol_get( frame->args, 0 );
1312     clear_targets_to_update();
1313     for ( ; arg1; arg1 = list_next( arg1 ) )
1314         mark_target_for_updating( newstr( arg1->string ) );
1315     return result;
1316 }
1317
1318 extern int anyhow;
1319 int last_update_now_status;
1320
1321 /* Takes a list of target names as first argument, and immediately
1322    updates them.
1323    Second parameter, if specified, if the descriptor (converted to a string)
1324    of a log file where all build output is redirected.
1325    Third parameter, if non-empty, specifies that the -n option should have
1326    no effect -- that is, all out-of-date targets should be rebuild.
1327 */
1328 LIST * builtin_update_now( PARSE * parse, FRAME * frame )
1329 {
1330     LIST * targets = lol_get( frame->args, 0 );
1331     LIST * log = lol_get( frame->args, 1 );
1332     LIST * force = lol_get (frame->args, 2);
1333     LIST * continue_ = lol_get(frame->args, 3);
1334     int status = 0;
1335     int original_stdout;
1336     int original_stderr;
1337     int n;
1338     int targets_count;
1339     const char** targets2;
1340     int i;
1341     int original_noexec;
1342     int original_quitquick;
1343         
1344
1345     if (log)
1346     {
1347         int fd = atoi(log->string);
1348         /* Redirect stdout and stderr, temporary, to the log file.  */
1349         original_stdout = dup (0);
1350         original_stderr = dup (1);
1351         dup2 (fd, 0);
1352         dup2 (fd, 1);
1353     }
1354
1355     if (force)
1356     {
1357         original_noexec = globs.noexec;
1358         globs.noexec = 0;
1359         original_quitquick = globs.quitquick;
1360         globs.quitquick = 0;
1361     }
1362
1363     if (continue_)
1364     {
1365         original_quitquick = globs.quitquick;
1366         globs.quitquick = 0;
1367     }
1368
1369     targets_count = list_length( targets );
1370     targets2 = (const char * *)BJAM_MALLOC( targets_count * sizeof( char * ) );    
1371     for (i = 0 ; targets; targets = list_next( targets ) )
1372         targets2[ i++ ] = targets->string;
1373     status |= make( targets_count, targets2, anyhow);
1374     free( targets );
1375
1376     if (force)
1377     {
1378         globs.noexec = original_noexec;
1379         globs.quitquick = original_quitquick;
1380     }
1381
1382     if (continue_)
1383     {
1384         globs.quitquick = original_quitquick;
1385     }
1386
1387     if (log)
1388     {
1389         /* Flush whatever stdio might have buffered, while descriptions
1390            0 and 1 still refer to the log file.  */
1391         fflush (stdout);
1392         fflush (stderr);
1393         dup2 (original_stdout, 0);
1394         dup2 (original_stderr, 1);
1395         close (original_stdout);
1396         close (original_stderr);
1397     }
1398
1399     last_update_now_status = status;
1400         
1401     if (status == 0)
1402         return list_new (L0, newstr ("ok"));
1403     else
1404         return L0;
1405 }
1406
1407 LIST * builtin_search_for_target( PARSE * parse, FRAME * frame )
1408 {
1409     LIST * arg1 = lol_get( frame->args, 0 );
1410     LIST * arg2 = lol_get( frame->args, 1 );
1411     TARGET * t = search_for_target( arg1->string, arg2 );
1412     return list_new( L0, t->name );
1413 }
1414
1415
1416 LIST * builtin_import_module( PARSE * parse, FRAME * frame )
1417 {
1418     LIST * arg1 = lol_get( frame->args, 0 );
1419     LIST * arg2 = lol_get( frame->args, 1 );
1420     module_t * m = arg2 ? bindmodule( arg2->string ) : root_module();
1421     import_module( arg1, m );
1422     return L0;
1423 }
1424
1425
1426 LIST * builtin_imported_modules( PARSE * parse, FRAME * frame )
1427 {
1428     LIST * arg0 = lol_get( frame->args, 0 );
1429     return imported_modules( bindmodule( arg0 ? arg0->string : 0 ) );
1430 }
1431
1432
1433 LIST * builtin_instance( PARSE * parse, FRAME * frame )
1434 {
1435     LIST * arg1 = lol_get( frame->args, 0 );
1436     LIST * arg2 = lol_get( frame->args, 1 );
1437     module_t * const instance     = bindmodule( arg1->string );
1438     module_t * const class_module = bindmodule( arg2->string );
1439     instance->class_module = class_module;
1440     return L0;
1441 }
1442
1443
1444 LIST * builtin_sort( PARSE * parse, FRAME * frame )
1445 {
1446     LIST * arg1 = lol_get( frame->args, 0 );
1447     return list_sort( arg1 );
1448 }
1449
1450
1451 LIST * builtin_normalize_path( PARSE * parse, FRAME * frame )
1452 {
1453     LIST * arg = lol_get( frame->args, 0 );
1454
1455     /* First, we iterate over all '/'-separated elements, starting from the end
1456      * of string. If we see a '..', we remove a previous path elements. If we
1457      * see '.', we remove it. The removal is done by overwriting data using '\1'
1458      * in the string. After the whole string has been processed, we do a second
1459      * pass, removing all the entered '\1' characters.
1460      */
1461
1462     string   in[ 1 ];
1463     string   out[ 1 ];
1464         /* Last character of the part of string still to be processed. */
1465     char   * end;
1466         /* Working pointer. */
1467     char   * current;
1468         /* Number of '..' elements seen and not processed yet. */
1469     int      dotdots = 0;
1470     int      rooted  = 0;
1471     char   * result  = 0;
1472
1473     /* Make a copy of input: we should not change it. Prepend a '/' before it as
1474      * a guard for the algorithm later on and remember whether it was originally
1475      * rooted or not.
1476      */
1477     string_new( in );
1478     string_push_back( in, '/' );
1479     for ( ; arg; arg = list_next( arg ) )
1480     {
1481         if ( arg->string[ 0 ] != '\0' )
1482         {
1483             if ( in->size == 1 )
1484                 rooted = ( ( arg->string[ 0 ] == '/'  ) ||
1485                            ( arg->string[ 0 ] == '\\' ) );
1486             else
1487                 string_append( in, "/" );
1488             string_append( in, arg->string );
1489         }
1490     }
1491
1492     /* Convert \ into /. On Windows, paths using / and \ are equivalent, and we
1493      * want this function to obtain a canonic representation.
1494      */
1495     for ( current = in->value, end = in->value + in->size;
1496         current < end; ++current )
1497         if ( *current == '\\' )
1498             *current = '/';
1499
1500     /* Now we remove any extra path elements by overwriting them with '\1'
1501      * characters and cound how many more unused '..' path elements there are
1502      * remaining. Note that each remaining path element with always starts with
1503      * a '/' character.
1504      */
1505     for ( end = in->value + in->size - 1; end >= in->value; )
1506     {
1507         /* Set 'current' to the next occurence of '/', which always exists. */
1508         for ( current = end; *current != '/'; --current );
1509
1510         if ( current == end )
1511         {
1512             /* Found a trailing or duplicate '/'. Remove it. */
1513             *current = '\1';
1514         }
1515         else if ( ( end - current == 1 ) && ( *(current + 1) == '.' ) )
1516         {
1517             /* Found '/.'. Remove them all. */
1518             *current = '\1';
1519             *(current + 1) = '\1';
1520         }
1521         else if ( ( end - current == 2 ) && ( *(current + 1) == '.' ) && ( *(current + 2) == '.' ) )
1522         {
1523             /* Found '/..'. Remove them all. */
1524             *current = '\1';
1525             *(current + 1) = '\1';
1526             *(current + 2) = '\1';
1527             ++dotdots;
1528         }
1529         else if ( dotdots )
1530         {
1531             memset( current, '\1', end - current + 1 );
1532             --dotdots;
1533         }
1534         end = current - 1;
1535     }
1536
1537     string_new( out );
1538
1539     /* Now we know that we need to add exactly dotdots '..' path elements to the
1540      * front and that our string is either empty or has a '/' as its first
1541      * significant character. If we have any dotdots remaining then the passed
1542      * path must not have been rooted or else it is invalid we return an empty
1543      * list.
1544      */
1545     if ( dotdots )
1546     {
1547         if ( rooted ) return L0;
1548         do
1549             string_append( out, "/.." );
1550         while ( --dotdots );
1551     }
1552
1553     /* Now we actually remove all the path characters marked for removal. */
1554     for ( current = in->value; *current; ++current )
1555         if ( *current != '\1' )
1556             string_push_back( out, *current );
1557
1558     /* Here we know that our string contains no '\1' characters and is either
1559      * empty or has a '/' as its initial character. If the original path was not
1560      * rooted and we have a non-empty path we need to drop the initial '/'. If
1561      * the original path was rooted and we have an empty path we need to add
1562      * back the '/'.
1563      */
1564     result = newstr( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) );
1565
1566     string_free( out );
1567     string_free( in );
1568
1569     return list_new( 0, result );
1570 }
1571
1572
1573 LIST * builtin_native_rule( PARSE * parse, FRAME * frame )
1574 {
1575     LIST * module_name = lol_get( frame->args, 0 );
1576     LIST * rule_name = lol_get( frame->args, 1 );
1577
1578     module_t * module = bindmodule( module_name->string );
1579
1580     native_rule_t n;
1581     native_rule_t * np = &n;
1582     n.name = rule_name->string;
1583     if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
1584     {
1585         new_rule_body( module, np->name, np->arguments, np->procedure, 1 );
1586     }
1587     else
1588     {
1589         backtrace_line( frame->prev );
1590         printf( "error: no native rule \"%s\" defined in module \"%s\"\n",
1591                 n.name, module->name );
1592         backtrace( frame->prev );
1593         exit( 1 );
1594     }
1595     return L0;
1596 }
1597
1598
1599 LIST * builtin_has_native_rule( PARSE * parse, FRAME * frame )
1600 {
1601     LIST * module_name = lol_get( frame->args, 0 );
1602     LIST * rule_name   = lol_get( frame->args, 1 );
1603     LIST * version     = lol_get( frame->args, 2 );
1604
1605     module_t * module = bindmodule( module_name->string );
1606
1607     native_rule_t n;
1608     native_rule_t * np = &n;
1609     n.name = rule_name->string;
1610     if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) )
1611     {
1612         int expected_version = atoi( version->string );
1613         if ( np->version == expected_version )
1614             return list_new( 0, newstr( "true" ) );
1615     }
1616     return L0;
1617 }
1618
1619
1620 LIST * builtin_user_module( PARSE * parse, FRAME * frame )
1621 {
1622     LIST * module_name = lol_get( frame->args, 0 );
1623     for ( ; module_name; module_name = module_name->next )
1624     {
1625         module_t * m = bindmodule( module_name->string );
1626         m->user_module = 1;
1627     }
1628     return L0;
1629 }
1630
1631
1632 LIST * builtin_nearest_user_location( PARSE * parse, FRAME * frame )
1633 {
1634     FRAME * nearest_user_frame =
1635         frame->module->user_module ? frame : frame->prev_user;
1636     if ( !nearest_user_frame )
1637         return L0;
1638
1639     {
1640         LIST * result = 0;
1641         char * file;
1642         int    line;
1643         char   buf[32];
1644
1645         get_source_line( nearest_user_frame->procedure, &file, &line );
1646         sprintf( buf, "%d", line );
1647         result = list_new( result, newstr( file ) );
1648         result = list_new( result, newstr( buf ) );
1649         return result;
1650     }
1651 }
1652
1653
1654 LIST * builtin_check_if_file( PARSE * parse, FRAME * frame )
1655 {
1656     LIST * name = lol_get( frame->args, 0 );
1657     return file_is_file( name->string ) == 1
1658         ? list_new( 0, newstr( "true" ) )
1659         : L0 ;
1660 }
1661
1662
1663 LIST * builtin_md5( PARSE * parse, FRAME * frame )
1664 {
1665     LIST * l = lol_get( frame->args, 0 );
1666     char* s = l->string;
1667
1668     md5_state_t state;
1669     md5_byte_t digest[16];
1670     char hex_output[16*2 + 1];
1671
1672     int di;
1673
1674     md5_init(&state);
1675     md5_append(&state, (const md5_byte_t *)s, strlen(s));
1676     md5_finish(&state, digest);
1677
1678     for (di = 0; di < 16; ++di)
1679         sprintf(hex_output + di * 2, "%02x", digest[di]);
1680
1681     return list_new (0, newstr(hex_output));
1682 }
1683
1684 LIST *builtin_file_open( PARSE *parse, FRAME *frame )
1685 {
1686     char* name = lol_get(frame->args, 0)->string;
1687     char* mode = lol_get(frame->args, 1)->string;
1688     int fd;
1689     char buffer[sizeof("4294967295")];
1690
1691     if (strcmp(mode, "w") == 0)
1692     {
1693         fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
1694     }
1695     else
1696     {
1697         fd = open(name, O_RDONLY);
1698     }
1699
1700     if (fd != -1)
1701     {
1702         sprintf(buffer, "%d", fd);
1703         return list_new(L0, newstr(buffer));
1704     }
1705     else
1706     {
1707         return L0;
1708     }
1709 }
1710
1711 LIST *builtin_pad( PARSE *parse, FRAME *frame )
1712 {
1713     char *string = lol_get(frame->args, 0)->string;
1714     char *width_s = lol_get(frame->args, 1)->string;
1715
1716     int current = strlen (string);
1717     int desired = atoi(width_s);
1718     if (current >= desired)
1719         return list_new (L0, string);
1720     else
1721     {
1722         char *buffer = malloc (desired + 1);
1723         int i;
1724         LIST *result;
1725
1726         strcpy (buffer, string);
1727         for (i = current; i < desired; ++i)
1728             buffer[i] = ' ';
1729         buffer[desired] = '\0';
1730         result = list_new (L0, newstr (buffer));
1731         free (buffer);
1732         return result;
1733     }
1734 }
1735
1736 LIST *builtin_precious( PARSE *parse, FRAME *frame )
1737 {
1738     LIST* targets = lol_get(frame->args, 0);
1739
1740     for ( ; targets; targets = list_next( targets ) )    
1741     {
1742         TARGET* t = bindtarget (targets->string);
1743         t->flags |= T_FLAG_PRECIOUS;
1744     }
1745
1746     return L0;
1747 }
1748
1749 LIST *builtin_self_path( PARSE *parse, FRAME *frame )
1750 {
1751     extern char *saved_argv0;
1752     char *p = executable_path (saved_argv0);
1753     if (p)
1754     {
1755         LIST* result = list_new (0, newstr (p));
1756         free(p);
1757         return result;
1758     }
1759     else
1760     {
1761         return L0;
1762     }
1763 }
1764
1765 LIST *builtin_makedir( PARSE *parse, FRAME *frame )
1766 {
1767     LIST *path = lol_get(frame->args, 0);
1768
1769     if (file_mkdir(path->string) == 0)
1770     {
1771         LIST *result = list_new (0, newstr(path->string));
1772         return result;
1773     }
1774     else
1775     {
1776         return L0;
1777     }    
1778 }
1779
1780 #ifdef HAVE_PYTHON
1781
1782 LIST * builtin_python_import_rule( PARSE * parse, FRAME * frame )
1783 {
1784     static int first_time = 1;
1785     char * python_module   = lol_get( frame->args, 0 )->string;
1786     char * python_function = lol_get( frame->args, 1 )->string;
1787     char * jam_module      = lol_get( frame->args, 2 )->string;
1788     char * jam_rule        = lol_get( frame->args, 3 )->string;
1789
1790     PyObject * pName;
1791     PyObject * pModule;
1792     PyObject * pDict;
1793     PyObject * pFunc;
1794
1795     if ( first_time )
1796     {
1797         /* At the first invocation, we add the value of the global
1798          * EXTRA_PYTHONPATH to the sys.path Python variable.
1799          */
1800         LIST * extra = 0;
1801         module_t * outer_module = frame->module;
1802
1803         first_time = 0;
1804
1805         if ( outer_module != root_module() )
1806         {
1807             exit_module( outer_module );
1808             enter_module( root_module() );
1809         }
1810
1811         extra = var_get( "EXTRA_PYTHONPATH" );
1812
1813         if ( outer_module != root_module() )
1814         {
1815              exit_module( root_module() );
1816              enter_module( outer_module );
1817         }
1818
1819         for ( ; extra; extra = extra->next )
1820         {
1821             string buf[ 1 ];
1822             string_new( buf );
1823             string_append( buf, "import sys\nsys.path.append(\"" );
1824             string_append( buf, extra->string );
1825             string_append( buf, "\")\n" );
1826             PyRun_SimpleString( buf->value );
1827             string_free( buf );
1828         }
1829     }
1830
1831     pName   = PyString_FromString( python_module );
1832     pModule = PyImport_Import( pName );
1833     Py_DECREF( pName );
1834
1835     if ( pModule != NULL )
1836     {
1837         pDict = PyModule_GetDict( pModule );
1838         pFunc = PyDict_GetItemString( pDict, python_function );
1839
1840         if ( pFunc && PyCallable_Check( pFunc ) )
1841         {
1842             module_t * m = bindmodule( jam_module );
1843             RULE * r = bindrule( jam_rule, m );
1844
1845             /* Make pFunc owned. */
1846             Py_INCREF( pFunc );
1847
1848             r->python_function = pFunc;
1849         }
1850         else
1851         {
1852             if ( PyErr_Occurred() )
1853                 PyErr_Print();
1854             fprintf( stderr, "Cannot find function \"%s\"\n", python_function );
1855         }
1856         Py_DECREF( pModule );
1857     }
1858     else
1859     {
1860         PyErr_Print();
1861         fprintf( stderr, "Failed to load \"%s\"\n", python_module );
1862     }
1863     return L0;
1864
1865 }
1866
1867 #endif
1868
1869 void lol_build( LOL * lol, char * * elements )
1870 {
1871     LIST * l = L0;
1872     lol_init( lol );
1873
1874     while ( elements && *elements )
1875     {
1876         if ( !strcmp( *elements, ":" ) )
1877         {
1878             lol_add( lol, l );
1879             l = L0 ;
1880         }
1881         else
1882         {
1883             l = list_new( l, newstr( *elements ) );
1884         }
1885         ++elements;
1886     }
1887
1888     if ( l != L0 )
1889         lol_add( lol, l );
1890 }
1891
1892
1893 #ifdef HAVE_PYTHON
1894
1895 /*
1896  * Calls the bjam rule specified by name passed in 'args'. The name is looked up
1897  * in the context of bjam's 'python_interface' module. Returns the list of
1898  * string retured by the rule.
1899  */
1900
1901 PyObject* bjam_call( PyObject * self, PyObject * args )
1902 {
1903     FRAME   inner[ 1 ];
1904     LIST  * result;
1905     PARSE * p;
1906     char  * rulename;
1907
1908     /* Build up the list of arg lists. */
1909     frame_init( inner );
1910     inner->prev = 0;
1911     inner->prev_user = 0;
1912     inner->module = bindmodule( "python_interface" );
1913     inner->procedure = 0;
1914
1915     /* Extract the rule name and arguments from 'args'. */
1916
1917     /* PyTuple_GetItem returns borrowed reference. */
1918     rulename = PyString_AsString( PyTuple_GetItem( args, 0 ) );
1919     {
1920         int i = 1;
1921         int size = PyTuple_Size( args );
1922         for ( ; i < size; ++i )
1923         {
1924             PyObject * a = PyTuple_GetItem( args, i );
1925             if ( PyString_Check( a ) )
1926             {
1927                 lol_add( inner->args, list_new( 0, newstr(
1928                     PyString_AsString( a ) ) ) );
1929             }
1930             else if ( PySequence_Check( a ) )
1931             {
1932                 LIST * l = 0;
1933                 int s = PySequence_Size( a );
1934                 int i = 0;
1935                 for ( ; i < s; ++i )
1936                 {
1937                     /* PySequence_GetItem returns new reference. */
1938                     PyObject * e = PySequence_GetItem( a, i );
1939                     char * s = PyString_AsString( e );
1940                     if ( !s )
1941                     {
1942                         printf( "Invalid parameter type passed from Python\n" );
1943                         exit( 1 );
1944                     }
1945                     l = list_new( l, newstr( s ) );
1946                     Py_DECREF( e );
1947                 }
1948                 lol_add( inner->args, l );
1949             }
1950         }
1951     }
1952
1953     result = evaluate_rule( rulename, inner );
1954
1955     frame_free( inner );
1956
1957     /* Convert the bjam list into a Python list result. */
1958     {
1959         PyObject * pyResult = PyList_New( list_length( result ) );
1960         int i = 0;
1961         while ( result )
1962         {
1963             PyList_SetItem( pyResult, i, PyString_FromString( result->string ) );
1964             result = list_next( result );
1965             i += 1;
1966         }
1967         list_free( result );
1968         return pyResult;
1969     }
1970 }
1971
1972
1973 /*
1974  * Accepts four arguments: 
1975  * - module name
1976  * - rule name,
1977  * - Python callable. 
1978  * - (optional) bjam language function signature.
1979  * Creates a bjam rule with the specified name in the specified module, which will
1980  * invoke the Python callable.
1981  */
1982
1983 PyObject * bjam_import_rule( PyObject * self, PyObject * args )
1984 {
1985     char     * module;
1986     char     * rule;
1987     PyObject * func;
1988     PyObject * bjam_signature = NULL;
1989     module_t * m;
1990     RULE     * r;
1991
1992     if ( !PyArg_ParseTuple( args, "ssO|O:import_rule", 
1993                             &module, &rule, &func, &bjam_signature ) )
1994         return NULL;
1995
1996     if ( !PyCallable_Check( func ) )
1997     {
1998         PyErr_SetString( PyExc_RuntimeError,
1999                         "Non-callable object passed to bjam.import_rule" );
2000         return NULL;
2001     }
2002
2003     m = bindmodule( *module ? module : 0 );
2004     r = bindrule( rule, m );
2005
2006     /* Make pFunc owned. */
2007     Py_INCREF( func );
2008
2009     r->python_function = func;
2010     r->arguments = 0;
2011
2012     if (bjam_signature)
2013     {
2014         argument_list * arg_list = args_new();
2015         Py_ssize_t i;
2016
2017         Py_ssize_t s = PySequence_Size (bjam_signature);
2018         for (i = 0; i < s; ++i)
2019         {
2020             PyObject* v = PySequence_GetItem (bjam_signature, i);
2021             lol_add(arg_list->data, list_from_python (v));
2022             Py_DECREF(v);
2023         }
2024         r->arguments = arg_list;
2025     }
2026
2027     Py_INCREF( Py_None );
2028     return Py_None;
2029 }
2030
2031
2032 /*
2033  * Accepts four arguments:
2034  *  - an action name
2035  *  - an action body
2036  *  - a list of variable that will be bound inside the action
2037  *  - integer flags.
2038  *  Defines an action on bjam side.
2039  */
2040
2041 PyObject * bjam_define_action( PyObject * self, PyObject * args )
2042 {
2043     char     * name;
2044     char     * body;
2045     module_t * m;
2046     PyObject * bindlist_python;
2047     int        flags;
2048     LIST     * bindlist = L0;
2049     int        n;
2050     int        i;
2051
2052     if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body,
2053                           &PyList_Type, &bindlist_python, &flags ) )
2054         return NULL;
2055
2056     n = PyList_Size( bindlist_python );
2057     for ( i = 0; i < n; ++i )
2058     {
2059         PyObject * next = PyList_GetItem( bindlist_python, i );
2060         if ( !PyString_Check( next ) )
2061         {
2062             PyErr_SetString( PyExc_RuntimeError,
2063                             "bind list has non-string type" );
2064             return NULL;
2065         }
2066         bindlist = list_new( bindlist, PyString_AsString( next ) );
2067     }
2068
2069     new_rule_actions( root_module(), name, newstr( body ), bindlist, flags );
2070
2071     Py_INCREF( Py_None );
2072     return Py_None;
2073 }
2074
2075
2076 /*
2077  * Returns the value of a variable in root Jam module.
2078  */
2079
2080 PyObject * bjam_variable( PyObject * self, PyObject * args )
2081 {
2082     char     * name;
2083     LIST     * value;
2084     PyObject * result;
2085     int        i;
2086
2087     if ( !PyArg_ParseTuple( args, "s", &name ) )
2088         return NULL;
2089
2090     enter_module( root_module() );
2091     value = var_get( name );
2092     exit_module( root_module() );
2093
2094     result = PyList_New( list_length( value ) );
2095     for ( i = 0; value; value = list_next( value ), ++i )
2096         PyList_SetItem( result, i, PyString_FromString( value->string ) );
2097
2098     return result;
2099 }
2100
2101
2102 PyObject * bjam_backtrace( PyObject * self, PyObject * args )
2103 {
2104     PyObject     * result = PyList_New( 0 );
2105     struct frame * f = frame_before_python_call;
2106
2107     for ( ; f = f->prev; )
2108     {
2109         PyObject * tuple = PyTuple_New( 4 );
2110         char     * file;
2111         int        line;
2112         char       buf[ 32 ];
2113
2114         get_source_line( f->procedure, &file, &line );
2115         sprintf( buf, "%d", line );
2116
2117         /* PyTuple_SetItem steals reference. */
2118         PyTuple_SetItem( tuple, 0, PyString_FromString( file            ) );
2119         PyTuple_SetItem( tuple, 1, PyString_FromString( buf             ) );
2120         PyTuple_SetItem( tuple, 2, PyString_FromString( f->module->name ) );
2121         PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename     ) );
2122
2123         PyList_Append( result, tuple );
2124         Py_DECREF( tuple );
2125     }
2126     return result;
2127 }
2128
2129 PyObject * bjam_caller( PyObject * self, PyObject * args )
2130 {
2131     PyObject *result = PyString_FromString(
2132         frame_before_python_call->prev->module->name);
2133     return result;
2134 }
2135
2136 #endif  /* #ifdef HAVE_PYTHON */
2137
2138
2139 #ifdef HAVE_POPEN
2140
2141 #if defined(_MSC_VER) || defined(__BORLANDC__)
2142     #define popen windows_popen_wrapper
2143     #define pclose _pclose
2144
2145     /*
2146      * This wrapper is a workaround for a funny _popen() feature on Windows
2147      * where it eats external quotes in some cases. The bug seems to be related
2148      * to the quote stripping functionality used by the Windows cmd.exe
2149      * interpreter when its /S is not specified.
2150      *
2151      * Cleaned up quote from the cmd.exe help screen as displayed on Windows XP
2152      * SP3:
2153      *
2154      *   1. If all of the following conditions are met, then quote characters on
2155      *      the command line are preserved:
2156      *
2157      *       - no /S switch
2158      *       - exactly two quote characters
2159      *       - no special characters between the two quote characters, where
2160      *         special is one of: &<>()@^|
2161      *       - there are one or more whitespace characters between the two quote
2162      *         characters
2163      *       - the string between the two quote characters is the name of an
2164      *         executable file.
2165      *
2166      *   2. Otherwise, old behavior is to see if the first character is a quote
2167      *      character and if so, strip the leading character and remove the last
2168      *      quote character on the command line, preserving any text after the
2169      *      last quote character.
2170      *
2171      * This causes some commands containing quotes not to be executed correctly.
2172      * For example:
2173      *
2174      *   "\Long folder name\aaa.exe" --name="Jurko" --no-surname
2175      *
2176      * would get its outermost quotes stripped and would be executed as:
2177      *
2178      *   \Long folder name\aaa.exe" --name="Jurko --no-surname
2179      *
2180      * which would report an error about '\Long' not being a valid command.
2181      *
2182      * cmd.exe help seems to indicate it would be enough to add an extra space
2183      * character in front of the command to avoid this but this does not work,
2184      * most likely due to the shell first stripping all leading whitespace
2185      * characters from the command.
2186      *
2187      * Solution implemented here is to quote the whole command in case it
2188      * contains any quote characters. Note thought this will not work correctly
2189      * should Windows ever 'fix' this feature.
2190      *                                               (03.06.2008.) (Jurko)
2191      */
2192     static FILE * windows_popen_wrapper( char * command, char * mode )
2193     {
2194         int extra_command_quotes_needed = ( strchr( command, '"' ) != 0 );
2195         string quoted_command;
2196         FILE * result;
2197
2198         if ( extra_command_quotes_needed )
2199         {
2200             string_new( &quoted_command );
2201             string_append( &quoted_command, "\"" );
2202             string_append( &quoted_command, command );
2203             string_append( &quoted_command, "\"" );
2204             command = quoted_command.value;
2205         }
2206
2207         result = _popen( command, "r" );
2208
2209         if ( extra_command_quotes_needed )
2210             string_free( &quoted_command );
2211
2212         return result;
2213     }
2214 #endif
2215
2216
2217 static char * rtrim(char *s)
2218 {
2219     char *p = s;
2220     while(*p) ++p;
2221     for(--p; p >= s && isspace(*p); *p-- = 0);
2222     return s;
2223 }
2224
2225 LIST * builtin_shell( PARSE * parse, FRAME * frame )
2226 {
2227     LIST   * command = lol_get( frame->args, 0 );
2228     LIST   * result = 0;
2229     string   s;
2230     int      ret;
2231     char     buffer[ 1024 ];
2232     FILE   * p = NULL;
2233     int      exit_status = -1;
2234     int      exit_status_opt = 0;
2235     int      no_output_opt = 0;
2236     int      strip_eol_opt = 0;
2237
2238     /* Process the variable args options. */
2239     {
2240         int a = 1;
2241         LIST * arg = lol_get( frame->args, a );
2242         while ( arg )
2243         {
2244             if ( strcmp( "exit-status", arg->string ) == 0 )
2245             {
2246                 exit_status_opt = 1;
2247             }
2248             else if ( strcmp( "no-output", arg->string ) == 0 )
2249             {
2250                 no_output_opt = 1;
2251             }
2252             else if ( strcmp("strip-eol", arg->string) == 0 )
2253             {
2254                 strip_eol_opt = 1;
2255             }
2256             arg = lol_get( frame->args, ++a );
2257         }
2258     }
2259
2260     /* The following fflush() call seems to be indicated as a workaround for a
2261      * popen() bug on POSIX implementations related to synhronizing input
2262      * stream positions for the called and the calling process.
2263      */
2264     fflush( NULL );
2265
2266     p = popen( command->string, "r" );
2267     if ( p == NULL )
2268         return L0;
2269
2270     string_new( &s );
2271
2272     while ( ( ret = fread( buffer, sizeof( char ), sizeof( buffer ) - 1, p ) ) > 0 )
2273     {
2274         buffer[ret] = 0;
2275         if ( !no_output_opt )
2276         {
2277             if ( strip_eol_opt )
2278                 rtrim(buffer);
2279             string_append( &s, buffer );
2280         }
2281     }
2282
2283     exit_status = pclose( p );
2284
2285     /* The command output is returned first. */
2286     result = list_new( L0, newstr( s.value ) );
2287     string_free( &s );
2288
2289     /* The command exit result next. */
2290     if ( exit_status_opt )
2291     {
2292         if ( WIFEXITED(exit_status) )
2293             exit_status = WEXITSTATUS(exit_status);
2294         else
2295             exit_status = -1;
2296         sprintf( buffer, "%d", exit_status );
2297         result = list_new( result, newstr( buffer ) );
2298     }
2299
2300     return result;
2301 }
2302
2303 #else  /* #ifdef HAVE_POPEN */
2304
2305 LIST * builtin_shell( PARSE * parse, FRAME * frame )
2306 {
2307     return L0;
2308 }
2309
2310 #endif /* #ifdef HAVE_POPEN */