2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
11 #include "constants.h"
26 #include "jam_strings.h"
28 #include "timestamp.h"
36 #ifndef FSCTL_GET_REPARSE_POINT
37 /* MinGW's version of windows.h is missing this, so we need
38 * to include winioctl.h directly
43 /* With VC8 (VS2005) these are not defined:
44 * FSCTL_GET_REPARSE_POINT (expects WINVER >= 0x0500 _WIN32_WINNT >= 0x0500 )
45 * IO_REPARSE_TAG_SYMLINK (is part of a separate Driver SDK)
46 * So define them explicitly to their expected values.
48 #ifndef FSCTL_GET_REPARSE_POINT
49 # define FSCTL_GET_REPARSE_POINT 0x000900a8
51 #ifndef IO_REPARSE_TAG_SYMLINK
52 # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
56 #if !defined(__BORLANDC__)
61 #endif /* __BORLANDC__ */
64 #if defined(USE_EXECUNIX)
65 # include <sys/types.h>
66 # include <sys/wait.h>
71 * NT does not have wait() and associated macros and uses the system() return
72 * value instead. Status code group are documented at:
73 * http://msdn.microsoft.com/en-gb/library/ff565436.aspx
75 # define WIFEXITED(w) (((w) & 0XFFFFFF00) == 0)
76 # define WEXITSTATUS(w)(w)
80 * builtins.c - builtin jam rules
83 * load_builtins() - define builtin rules
84 * unknown_rule() - reports an unknown rule occurrence to the
88 * append_if_exists() - if file exists, append it to the list
89 * builtin_calc() - CALC rule
90 * builtin_delete_module() - DELETE_MODULE ( MODULE ? )
91 * builtin_depends() - DEPENDS/INCLUDES rule
92 * builtin_echo() - ECHO rule
93 * builtin_exit() - EXIT rule
94 * builtin_export() - EXPORT ( MODULE ? : RULES * )
95 * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
96 * builtin_glob() - GLOB rule
97 * builtin_glob_recursive() - ???
98 * builtin_hdrmacro() - ???
99 * builtin_import() - IMPORT rule
100 * builtin_match() - MATCH rule, regexp matching
101 * builtin_rebuilds() - REBUILDS rule
102 * builtin_rulenames() - RULENAMES ( MODULE ? )
103 * builtin_split_by_characters() - splits the given string into tokens
104 * builtin_varnames() - VARNAMES ( MODULE ? )
105 * get_source_line() - get a frame's file and line number
111 * compile_builtin() - define builtin rules
114 #define P0 (PARSE *)0
115 #define C0 (OBJECT *)0
117 #if defined( OS_NT ) || defined( OS_CYGWIN )
118 LIST
* builtin_system_registry ( FRAME
*, int );
119 LIST
* builtin_system_registry_names( FRAME
*, int );
122 int glob( char const * s
, char const * c
);
124 void backtrace ( FRAME
* );
125 void backtrace_line ( FRAME
* );
126 void print_source_line( FRAME
* );
129 RULE
* bind_builtin( char const * name_
, LIST
* (* f
)( FRAME
*, int flags
),
130 int flags
, char const * * args
)
134 OBJECT
* name
= object_new( name_
);
136 func
= function_builtin( f
, flags
, args
);
138 result
= new_rule_body( root_module(), name
, func
, 1 );
140 function_free( func
);
148 RULE
* duplicate_rule( char const * name_
, RULE
* other
)
150 OBJECT
* name
= object_new( name_
);
151 RULE
* result
= import_rule( other
, root_module(), name
);
158 * load_builtins() - define builtin rules
163 duplicate_rule( "Always",
164 bind_builtin( "ALWAYS",
165 builtin_flags
, T_FLAG_TOUCHED
, 0 ) );
167 duplicate_rule( "Depends",
168 bind_builtin( "DEPENDS",
169 builtin_depends
, 0, 0 ) );
171 duplicate_rule( "echo",
172 duplicate_rule( "Echo",
173 bind_builtin( "ECHO",
174 builtin_echo
, 0, 0 ) ) );
177 char const * args
[] = { "message", "*", ":", "result-value", "?", 0 };
178 duplicate_rule( "exit",
179 duplicate_rule( "Exit",
180 bind_builtin( "EXIT",
181 builtin_exit
, 0, args
) ) );
185 char const * args
[] = { "directories", "*", ":", "patterns", "*", ":",
186 "case-insensitive", "?", 0 };
187 duplicate_rule( "Glob",
188 bind_builtin( "GLOB", builtin_glob
, 0, args
) );
192 char const * args
[] = { "patterns", "*", 0 };
193 bind_builtin( "GLOB-RECURSIVELY",
194 builtin_glob_recursive
, 0, args
);
197 duplicate_rule( "Includes",
198 bind_builtin( "INCLUDES",
199 builtin_depends
, 1, 0 ) );
202 char const * args
[] = { "targets", "*", ":", "targets-to-rebuild", "*",
204 bind_builtin( "REBUILDS",
205 builtin_rebuilds
, 0, args
);
208 duplicate_rule( "Leaves",
209 bind_builtin( "LEAVES",
210 builtin_flags
, T_FLAG_LEAVES
, 0 ) );
212 duplicate_rule( "Match",
213 bind_builtin( "MATCH",
214 builtin_match
, 0, 0 ) );
217 char const * args
[] = { "string", ":", "delimiters", 0 };
218 bind_builtin( "SPLIT_BY_CHARACTERS",
219 builtin_split_by_characters
, 0, args
);
222 duplicate_rule( "NoCare",
223 bind_builtin( "NOCARE",
224 builtin_flags
, T_FLAG_NOCARE
, 0 ) );
226 duplicate_rule( "NOTIME",
227 duplicate_rule( "NotFile",
228 bind_builtin( "NOTFILE",
229 builtin_flags
, T_FLAG_NOTFILE
, 0 ) ) );
231 duplicate_rule( "NoUpdate",
232 bind_builtin( "NOUPDATE",
233 builtin_flags
, T_FLAG_NOUPDATE
, 0 ) );
235 duplicate_rule( "Temporary",
236 bind_builtin( "TEMPORARY",
237 builtin_flags
, T_FLAG_TEMP
, 0 ) );
239 bind_builtin( "ISFILE",
240 builtin_flags
, T_FLAG_ISFILE
, 0 );
242 duplicate_rule( "HdrMacro",
243 bind_builtin( "HDRMACRO",
244 builtin_hdrmacro
, 0, 0 ) );
246 /* FAIL_EXPECTED is used to indicate that the result of a target build
247 * action should be inverted (ok <=> fail) this can be useful when
248 * performing test runs from Jamfiles.
250 bind_builtin( "FAIL_EXPECTED",
251 builtin_flags
, T_FLAG_FAIL_EXPECTED
, 0 );
253 bind_builtin( "RMOLD",
254 builtin_flags
, T_FLAG_RMOLD
, 0 );
257 char const * args
[] = { "targets", "*", 0 };
258 bind_builtin( "UPDATE",
259 builtin_update
, 0, args
);
263 char const * args
[] = { "targets", "*",
265 ":", "ignore-minus-n", "?",
266 ":", "ignore-minus-q", "?", 0 };
267 bind_builtin( "UPDATE_NOW",
268 builtin_update_now
, 0, args
);
272 char const * args
[] = { "string", "pattern", "replacements", "+", 0 };
273 duplicate_rule( "subst",
274 bind_builtin( "SUBST",
275 builtin_subst
, 0, args
) );
279 char const * args
[] = { "module", "?", 0 };
280 bind_builtin( "RULENAMES",
281 builtin_rulenames
, 0, args
);
285 char const * args
[] = { "module", "?", 0 };
286 bind_builtin( "VARNAMES",
287 builtin_varnames
, 0, args
);
291 char const * args
[] = { "module", "?", 0 };
292 bind_builtin( "DELETE_MODULE",
293 builtin_delete_module
, 0, args
);
297 char const * args
[] = { "source_module", "?",
298 ":", "source_rules", "*",
299 ":", "target_module", "?",
300 ":", "target_rules", "*",
301 ":", "localize", "?", 0 };
302 bind_builtin( "IMPORT",
303 builtin_import
, 0, args
);
307 char const * args
[] = { "module", "?", ":", "rules", "*", 0 };
308 bind_builtin( "EXPORT",
309 builtin_export
, 0, args
);
313 char const * args
[] = { "levels", "?", 0 };
314 bind_builtin( "CALLER_MODULE",
315 builtin_caller_module
, 0, args
);
319 char const * args
[] = { "levels", "?", 0 };
320 bind_builtin( "BACKTRACE",
321 builtin_backtrace
, 0, args
);
325 char const * args
[] = { 0 };
327 builtin_pwd
, 0, args
);
331 char const * args
[] = { "modules_to_import", "+",
332 ":", "target_module", "?", 0 };
333 bind_builtin( "IMPORT_MODULE",
334 builtin_import_module
, 0, args
);
338 char const * args
[] = { "module", "?", 0 };
339 bind_builtin( "IMPORTED_MODULES",
340 builtin_imported_modules
, 0, args
);
344 char const * args
[] = { "instance_module", ":", "class_module", 0 };
345 bind_builtin( "INSTANCE",
346 builtin_instance
, 0, args
);
350 char const * args
[] = { "sequence", "*", 0 };
351 bind_builtin( "SORT",
352 builtin_sort
, 0, args
);
356 char const * args
[] = { "path_parts", "*", 0 };
357 bind_builtin( "NORMALIZE_PATH",
358 builtin_normalize_path
, 0, args
);
362 char const * args
[] = { "args", "*", 0 };
363 bind_builtin( "CALC",
364 builtin_calc
, 0, args
);
368 char const * args
[] = { "module", ":", "rule", 0 };
369 bind_builtin( "NATIVE_RULE",
370 builtin_native_rule
, 0, args
);
374 char const * args
[] = { "module", ":", "rule", ":", "version", 0 };
375 bind_builtin( "HAS_NATIVE_RULE",
376 builtin_has_native_rule
, 0, args
);
380 char const * args
[] = { "module", "*", 0 };
381 bind_builtin( "USER_MODULE",
382 builtin_user_module
, 0, args
);
386 char const * args
[] = { 0 };
387 bind_builtin( "NEAREST_USER_LOCATION",
388 builtin_nearest_user_location
, 0, args
);
392 char const * args
[] = { "file", 0 };
393 bind_builtin( "CHECK_IF_FILE",
394 builtin_check_if_file
, 0, args
);
399 char const * args
[] = { "python-module",
402 ":", "rule-name", 0 };
403 bind_builtin( "PYTHON_IMPORT_RULE",
404 builtin_python_import_rule
, 0, args
);
408 # if defined( OS_NT ) || defined( OS_CYGWIN )
410 char const * args
[] = { "key_path", ":", "data", "?", 0 };
411 bind_builtin( "W32_GETREG",
412 builtin_system_registry
, 0, args
);
416 char const * args
[] = { "key_path", ":", "result-type", 0 };
417 bind_builtin( "W32_GETREGNAMES",
418 builtin_system_registry_names
, 0, args
);
423 char const * args
[] = { "command", ":", "*", 0 };
424 duplicate_rule( "SHELL",
425 bind_builtin( "COMMAND",
426 builtin_shell
, 0, args
) );
430 char const * args
[] = { "string", 0 };
432 builtin_md5
, 0, args
);
436 char const * args
[] = { "name", ":", "mode", 0 };
437 bind_builtin( "FILE_OPEN",
438 builtin_file_open
, 0, args
);
442 char const * args
[] = { "string", ":", "width", 0 };
444 builtin_pad
, 0, args
);
448 char const * args
[] = { "targets", "*", 0 };
449 bind_builtin( "PRECIOUS",
450 builtin_precious
, 0, args
);
454 char const * args
[] = { 0 };
455 bind_builtin( "SELF_PATH", builtin_self_path
, 0, args
);
459 char const * args
[] = { "path", 0 };
460 bind_builtin( "MAKEDIR", builtin_makedir
, 0, args
);
464 const char * args
[] = { "path", 0 };
465 bind_builtin( "READLINK", builtin_readlink
, 0, args
);
469 char const * args
[] = { "archives", "*",
470 ":", "member-patterns", "*",
471 ":", "case-insensitive", "?",
472 ":", "symbol-patterns", "*", 0 };
473 bind_builtin( "GLOB_ARCHIVE", builtin_glob_archive
, 0, args
);
479 const char * args
[] = { "list", "*", 0 };
480 bind_builtin("__DEBUG_PRINT_HELPER__", builtin_debug_print_helper
, 0, args
);
485 /* Initialize builtin modules. */
496 * builtin_calc() - CALC rule
498 * Performs simple mathematical operations on two arguments.
501 LIST
* builtin_calc( FRAME
* frame
, int flags
)
503 LIST
* arg
= lol_get( frame
->args
, 0 );
513 LISTITER iter
= list_begin( arg
);
514 LISTITER
const end
= list_end( arg
);
516 if ( iter
== end
) return L0
;
517 lhs
= object_str( list_item( iter
) );
519 iter
= list_next( iter
);
520 if ( iter
== end
) return L0
;
521 op
= object_str( list_item( iter
) );
523 iter
= list_next( iter
);
524 if ( iter
== end
) return L0
;
525 rhs
= object_str( list_item( iter
) );
527 lhs_value
= atoi( lhs
);
528 rhs_value
= atoi( rhs
);
530 if ( !strcmp( "+", op
) )
531 result_value
= lhs_value
+ rhs_value
;
532 else if ( !strcmp( "-", op
) )
533 result_value
= lhs_value
- rhs_value
;
537 sprintf( buffer
, "%ld", result_value
);
538 result
= list_push_back( result
, object_new( buffer
) );
544 * builtin_depends() - DEPENDS/INCLUDES rule
546 * The DEPENDS/INCLUDES builtin rule appends each of the listed sources on the
547 * dependency/includes list of each of the listed targets. It binds both the
548 * targets and sources as TARGETs.
551 LIST
* builtin_depends( FRAME
* frame
, int flags
)
553 LIST
* const targets
= lol_get( frame
->args
, 0 );
554 LIST
* const sources
= lol_get( frame
->args
, 1 );
556 LISTITER iter
= list_begin( targets
);
557 LISTITER end
= list_end( targets
);
558 for ( ; iter
!= end
; iter
= list_next( iter
) )
560 TARGET
* const t
= bindtarget( list_item( iter
) );
563 target_include_many( t
, sources
);
565 t
->depends
= targetlist( t
->depends
, sources
);
568 /* Enter reverse links */
569 iter
= list_begin( sources
);
570 end
= list_end( sources
);
571 for ( ; iter
!= end
; iter
= list_next( iter
) )
573 TARGET
* const s
= bindtarget( list_item( iter
) );
576 LISTITER t_iter
= list_begin( targets
);
577 LISTITER
const t_end
= list_end( targets
);
578 for ( ; t_iter
!= t_end
; t_iter
= list_next( t_iter
) )
579 s
->dependants
= targetentry( s
->dependants
, bindtarget(
580 list_item( t_iter
) )->includes
);
583 s
->dependants
= targetlist( s
->dependants
, targets
);
591 * builtin_rebuilds() - REBUILDS rule
593 * Appends each of the rebuild-targets listed in its second argument to the
594 * rebuilds list for each of the targets listed in its first argument.
597 LIST
* builtin_rebuilds( FRAME
* frame
, int flags
)
599 LIST
* targets
= lol_get( frame
->args
, 0 );
600 LIST
* rebuilds
= lol_get( frame
->args
, 1 );
601 LISTITER iter
= list_begin( targets
);
602 LISTITER
const end
= list_end( targets
);
603 for ( ; iter
!= end
; iter
= list_next( iter
) )
605 TARGET
* const t
= bindtarget( list_item( iter
) );
606 t
->rebuilds
= targetlist( t
->rebuilds
, rebuilds
);
613 * builtin_echo() - ECHO rule
615 * Echoes the targets to the user. No other actions are taken.
618 LIST
* builtin_echo( FRAME
* frame
, int flags
)
620 list_print( lol_get( frame
->args
, 0 ) );
628 * builtin_exit() - EXIT rule
630 * Echoes the targets to the user and exits the program with a failure status.
633 LIST
* builtin_exit( FRAME
* frame
, int flags
)
635 LIST
* const code
= lol_get( frame
->args
, 1 );
636 list_print( lol_get( frame
->args
, 0 ) );
638 if ( !list_empty( code
) )
640 int status
= atoi( object_str( list_front( code
) ) );
655 exit( EXITBAD
); /* yeech */
661 * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
663 * Marks the target with the appropriate flag, for use by make0(). It binds each
664 * target as a TARGET.
667 LIST
* builtin_flags( FRAME
* frame
, int flags
)
669 LIST
* const targets
= lol_get( frame
->args
, 0 );
670 LISTITER iter
= list_begin( targets
);
671 LISTITER
const end
= list_end( targets
);
672 for ( ; iter
!= end
; iter
= list_next( iter
) )
673 bindtarget( list_item( iter
) )->flags
|= flags
;
679 * builtin_glob() - GLOB rule
686 LIST
* case_insensitive
;
690 static void downcase_inplace( char * p
)
697 static void builtin_glob_back( void * closure
, OBJECT
* file
, int status
,
698 timestamp
const * const time
)
700 PROFILE_ENTER( BUILTIN_GLOB_BACK
);
702 struct globbing
* const globbing
= (struct globbing
*)closure
;
708 /* Null out directory for matching. We wish we had file_dirscan() pass up a
711 path_parse( object_str( file
), &f
);
714 /* For globbing, we unconditionally ignore current and parent directory
715 * items. Since these items always exist, there is no reason why caller of
716 * GLOB would want to see them. We could also change file_dirscan(), but
717 * then paths with embedded "." and ".." would not work anywhere.
719 if ( !strcmp( f
.f_base
.ptr
, "." ) || !strcmp( f
.f_base
.ptr
, ".." ) )
721 PROFILE_EXIT( BUILTIN_GLOB_BACK
);
726 path_build( &f
, buf
);
728 if ( globbing
->case_insensitive
)
729 downcase_inplace( buf
->value
);
731 iter
= list_begin( globbing
->patterns
);
732 end
= list_end( globbing
->patterns
);
733 for ( ; iter
!= end
; iter
= list_next( iter
) )
735 if ( !glob( object_str( list_item( iter
) ), buf
->value
) )
737 globbing
->results
= list_push_back( globbing
->results
, object_copy(
745 PROFILE_EXIT( BUILTIN_GLOB_BACK
);
749 static LIST
* downcase_list( LIST
* in
)
752 LISTITER iter
= list_begin( in
);
753 LISTITER
const end
= list_end( in
);
758 for ( ; iter
!= end
; iter
= list_next( iter
) )
760 string_append( s
, object_str( list_item( iter
) ) );
761 downcase_inplace( s
->value
);
762 result
= list_push_back( result
, object_new( s
->value
) );
763 string_truncate( s
, 0 );
771 LIST
* builtin_glob( FRAME
* frame
, int flags
)
773 LIST
* const l
= lol_get( frame
->args
, 0 );
774 LIST
* const r
= lol_get( frame
->args
, 1 );
778 struct globbing globbing
;
780 globbing
.results
= L0
;
781 globbing
.patterns
= r
;
783 globbing
.case_insensitive
=
784 # if defined( OS_NT ) || defined( OS_CYGWIN ) || defined( OS_VMS )
785 l
; /* Always case-insensitive if any files can be found. */
787 lol_get( frame
->args
, 2 );
790 if ( globbing
.case_insensitive
)
791 globbing
.patterns
= downcase_list( r
);
793 iter
= list_begin( l
);
795 for ( ; iter
!= end
; iter
= list_next( iter
) )
796 file_dirscan( list_item( iter
), builtin_glob_back
, &globbing
);
798 if ( globbing
.case_insensitive
)
799 list_free( globbing
.patterns
);
801 return globbing
.results
;
805 static int has_wildcards( char const * const str
)
807 return str
[ strcspn( str
, "[]*?" ) ] ? 1 : 0;
812 * append_if_exists() - if file exists, append it to the list
815 static LIST
* append_if_exists( LIST
* list
, OBJECT
* file
)
817 file_info_t
* info
= file_query( file
);
819 ? list_push_back( list
, object_copy( info
->name
) )
824 LIST
* glob1( OBJECT
* dirname
, OBJECT
* pattern
)
826 LIST
* const plist
= list_new( object_copy( pattern
) );
827 struct globbing globbing
;
829 globbing
.results
= L0
;
830 globbing
.patterns
= plist
;
832 globbing
.case_insensitive
833 # if defined( OS_NT ) || defined( OS_CYGWIN ) || defined( OS_VMS )
834 = plist
; /* always case-insensitive if any files can be found */
839 if ( globbing
.case_insensitive
)
840 globbing
.patterns
= downcase_list( plist
);
842 file_dirscan( dirname
, builtin_glob_back
, &globbing
);
844 if ( globbing
.case_insensitive
)
845 list_free( globbing
.patterns
);
849 return globbing
.results
;
853 LIST
* glob_recursive( char const * pattern
)
857 /* Check if there's metacharacters in pattern */
858 if ( !has_wildcards( pattern
) )
860 /* No metacharacters. Check if the path exists. */
861 OBJECT
* const p
= object_new( pattern
);
862 result
= append_if_exists( result
, p
);
867 /* Have metacharacters in the pattern. Split into dir/name. */
869 path_parse( pattern
, path
);
871 if ( path
->f_dir
.ptr
)
875 string basename
[ 1 ];
876 string_new( dirname
);
877 string_new( basename
);
879 string_append_range( dirname
, path
->f_dir
.ptr
,
880 path
->f_dir
.ptr
+ path
->f_dir
.len
);
882 path
->f_grist
.ptr
= 0;
883 path
->f_grist
.len
= 0;
886 path_build( path
, basename
);
888 dirs
= has_wildcards( dirname
->value
)
889 ? glob_recursive( dirname
->value
)
890 : list_push_back( dirs
, object_new( dirname
->value
) );
892 if ( has_wildcards( basename
->value
) )
894 OBJECT
* const b
= object_new( basename
->value
);
895 LISTITER iter
= list_begin( dirs
);
896 LISTITER
const end
= list_end( dirs
);
897 for ( ; iter
!= end
; iter
= list_next( iter
) )
898 result
= list_append( result
, glob1( list_item( iter
), b
)
904 LISTITER iter
= list_begin( dirs
);
905 LISTITER
const end
= list_end( dirs
);
906 string file_string
[ 1 ];
907 string_new( file_string
);
909 /* No wildcard in basename. */
910 for ( ; iter
!= end
; iter
= list_next( iter
) )
913 path
->f_dir
.ptr
= object_str( list_item( iter
) );
914 path
->f_dir
.len
= strlen( object_str( list_item( iter
) ) );
915 path_build( path
, file_string
);
917 p
= object_new( file_string
->value
);
919 result
= append_if_exists( result
, p
);
923 string_truncate( file_string
, 0 );
926 string_free( file_string
);
929 string_free( dirname
);
930 string_free( basename
);
936 /* No directory, just a pattern. */
937 OBJECT
* const p
= object_new( pattern
);
938 result
= list_append( result
, glob1( constant_dot
, p
) );
948 * builtin_glob_recursive() - ???
951 LIST
* builtin_glob_recursive( FRAME
* frame
, int flags
)
954 LIST
* const l
= lol_get( frame
->args
, 0 );
955 LISTITER iter
= list_begin( l
);
956 LISTITER
const end
= list_end( l
);
957 for ( ; iter
!= end
; iter
= list_next( iter
) )
958 result
= list_append( result
, glob_recursive( object_str( list_item(
965 * builtin_match() - MATCH rule, regexp matching
968 LIST
* builtin_match( FRAME
* frame
, int flags
)
981 /* For each pattern */
983 l
= lol_get( frame
->args
, 0 );
984 l_iter
= list_begin( l
);
985 l_end
= list_end( l
);
986 for ( ; l_iter
!= l_end
; l_iter
= list_next( l_iter
) )
988 /* Result is cached and intentionally never freed. */
989 regexp
* re
= regex_compile( list_item( l_iter
) );
991 /* For each string to match against. */
992 r
= lol_get( frame
->args
, 1 );
993 r_iter
= list_begin( r
);
994 r_end
= list_end( r
);
995 for ( ; r_iter
!= r_end
; r_iter
= list_next( r_iter
) )
997 if ( regexec( re
, object_str( list_item( r_iter
) ) ) )
1002 /* Find highest parameter */
1004 for ( top
= NSUBEXP
; top
-- > 1; )
1005 if ( re
->startp
[ top
] )
1008 /* And add all parameters up to highest onto list. */
1009 /* Must have parameters to have results! */
1010 for ( i
= 1; i
<= top
; ++i
)
1012 string_append_range( buf
, re
->startp
[ i
], re
->endp
[ i
] );
1013 result
= list_push_back( result
, object_new( buf
->value
) );
1014 string_truncate( buf
, 0 );
1026 * builtin_split_by_characters() - splits the given string into tokens
1029 LIST
* builtin_split_by_characters( FRAME
* frame
, int flags
)
1031 LIST
* l1
= lol_get( frame
->args
, 0 );
1032 LIST
* l2
= lol_get( frame
->args
, 1 );
1038 char const * delimiters
= object_str( list_front( l2
) );
1041 string_copy( buf
, object_str( list_front( l1
) ) );
1043 t
= strtok( buf
->value
, delimiters
);
1046 result
= list_push_back( result
, object_new( t
) );
1047 t
= strtok( NULL
, delimiters
);
1057 * builtin_hdrmacro() - ???
1060 LIST
* builtin_hdrmacro( FRAME
* frame
, int flags
)
1062 LIST
* const l
= lol_get( frame
->args
, 0 );
1063 LISTITER iter
= list_begin( l
);
1064 LISTITER
const end
= list_end( l
);
1066 for ( ; iter
!= end
; iter
= list_next( iter
) )
1068 TARGET
* const t
= bindtarget( list_item( iter
) );
1070 /* Scan file for header filename macro definitions. */
1072 out_printf( "scanning '%s' for header file macro definitions\n",
1073 object_str( list_item( iter
) ) );
1083 * builtin_rulenames() - RULENAMES ( MODULE ? )
1085 * Returns a list of the non-local rule names in the given MODULE. If MODULE is
1086 * not supplied, returns the list of rule names in the global module.
1089 static void add_rule_name( void * r_
, void * result_
)
1091 RULE
* const r
= (RULE
*)r_
;
1092 LIST
* * const result
= (LIST
* *)result_
;
1094 *result
= list_push_back( *result
, object_copy( r
->name
) );
1098 LIST
* builtin_rulenames( FRAME
* frame
, int flags
)
1100 LIST
* arg0
= lol_get( frame
->args
, 0 );
1102 module_t
* const source_module
= bindmodule( list_empty( arg0
)
1104 : list_front( arg0
) );
1106 if ( source_module
->rules
)
1107 hashenumerate( source_module
->rules
, add_rule_name
, &result
);
1113 * builtin_varnames() - VARNAMES ( MODULE ? )
1115 * Returns a list of the variable names in the given MODULE. If MODULE is not
1116 * supplied, returns the list of variable names in the global module.
1119 /* helper function for builtin_varnames(), below. Used with hashenumerate, will
1120 * prepend the key of each element to the list
1122 static void add_hash_key( void * np
, void * result_
)
1124 LIST
* * result
= (LIST
* *)result_
;
1125 *result
= list_push_back( *result
, object_copy( *(OBJECT
* *)np
) );
1129 LIST
* builtin_varnames( FRAME
* frame
, int flags
)
1131 LIST
* arg0
= lol_get( frame
->args
, 0 );
1133 module_t
* source_module
= bindmodule( list_empty( arg0
)
1135 : list_front( arg0
) );
1137 struct hash
* const vars
= source_module
->variables
;
1139 hashenumerate( vars
, add_hash_key
, &result
);
1145 * builtin_delete_module() - DELETE_MODULE ( MODULE ? )
1147 * Clears all rules and variables from the given module.
1150 LIST
* builtin_delete_module( FRAME
* frame
, int flags
)
1152 LIST
* const arg0
= lol_get( frame
->args
, 0 );
1153 module_t
* const source_module
= bindmodule( list_empty( arg0
) ? 0 :
1154 list_front( arg0
) );
1155 delete_module( source_module
);
1161 * unknown_rule() - reports an unknown rule occurrence to the user and exits
1164 void unknown_rule( FRAME
* frame
, char const * key
, module_t
* module
,
1165 OBJECT
* rule_name
)
1167 backtrace_line( frame
->prev
);
1169 out_printf("%s error", key
);
1171 out_printf("ERROR");
1172 out_printf( ": rule \"%s\" unknown in ", object_str( rule_name
) );
1174 out_printf( "module \"%s\".\n", object_str( module
->name
) );
1176 out_printf( "root module.\n" );
1177 backtrace( frame
->prev
);
1183 * builtin_import() - IMPORT rule
1194 * Imports rules from the SOURCE_MODULE into the TARGET_MODULE as local rules.
1195 * If either SOURCE_MODULE or TARGET_MODULE is not supplied, it refers to the
1196 * global module. SOURCE_RULES specifies which rules from the SOURCE_MODULE to
1197 * import; TARGET_RULES specifies the names to give those rules in
1198 * TARGET_MODULE. If SOURCE_RULES contains a name that does not correspond to
1199 * a rule in SOURCE_MODULE, or if it contains a different number of items than
1200 * TARGET_RULES, an error is issued. If LOCALIZE is specified, the rules will be
1201 * executed in TARGET_MODULE, with corresponding access to its module local
1205 LIST
* builtin_import( FRAME
* frame
, int flags
)
1207 LIST
* source_module_list
= lol_get( frame
->args
, 0 );
1208 LIST
* source_rules
= lol_get( frame
->args
, 1 );
1209 LIST
* target_module_list
= lol_get( frame
->args
, 2 );
1210 LIST
* target_rules
= lol_get( frame
->args
, 3 );
1211 LIST
* localize
= lol_get( frame
->args
, 4 );
1213 module_t
* target_module
= bindmodule( list_empty( target_module_list
)
1215 : list_front( target_module_list
) );
1216 module_t
* source_module
= bindmodule( list_empty( source_module_list
)
1218 : list_front( source_module_list
) );
1220 LISTITER source_iter
= list_begin( source_rules
);
1221 LISTITER
const source_end
= list_end( source_rules
);
1222 LISTITER target_iter
= list_begin( target_rules
);
1223 LISTITER
const target_end
= list_end( target_rules
);
1226 source_iter
!= source_end
&& target_iter
!= target_end
;
1227 source_iter
= list_next( source_iter
),
1228 target_iter
= list_next( target_iter
) )
1231 RULE
* imported
= nullptr;
1233 if ( !source_module
->rules
|| !(r
= (RULE
*)hash_find(
1234 source_module
->rules
, list_item( source_iter
) ) ) )
1236 unknown_rule( frame
, "IMPORT", source_module
, list_item( source_iter
1240 imported
= import_rule( r
, target_module
, list_item( target_iter
) );
1241 if ( !list_empty( localize
) )
1242 rule_localize( imported
, target_module
);
1243 /* This rule is really part of some other module. Just refer to it here,
1244 * but do not let it out.
1246 imported
->exported
= 0;
1249 if ( source_iter
!= source_end
|| target_iter
!= target_end
)
1251 backtrace_line( frame
->prev
);
1252 out_printf( "import error: length of source and target rule name lists "
1254 out_printf( " source: " );
1255 list_print( source_rules
);
1256 out_printf( "\n target: " );
1257 list_print( target_rules
);
1259 backtrace( frame
->prev
);
1268 * builtin_export() - EXPORT ( MODULE ? : RULES * )
1270 * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local (and thus
1271 * exportable). If an element of RULES does not name a rule in MODULE, an error
1275 LIST
* builtin_export( FRAME
* frame
, int flags
)
1277 LIST
* const module_list
= lol_get( frame
->args
, 0 );
1278 LIST
* const rules
= lol_get( frame
->args
, 1 );
1279 module_t
* const m
= bindmodule( list_empty( module_list
) ? 0 : list_front(
1282 LISTITER iter
= list_begin( rules
);
1283 LISTITER
const end
= list_end( rules
);
1284 for ( ; iter
!= end
; iter
= list_next( iter
) )
1287 if ( !m
->rules
|| !( r
= (RULE
*)hash_find( m
->rules
, list_item( iter
)
1290 unknown_rule( frame
, "EXPORT", m
, list_item( iter
) );
1299 * get_source_line() - get a frame's file and line number information
1301 * This is the execution traceback information to be indicated for in debug
1302 * output or an error backtrace.
1305 static void get_source_line( FRAME
* frame
, char const * * file
, int * line
)
1309 char const * f
= object_str( frame
->file
);
1310 int l
= frame
->line
;
1311 if ( !strcmp( f
, "+" ) )
1321 *file
= "(builtin)";
1327 void print_source_line( FRAME
* frame
)
1331 get_source_line( frame
, &file
, &line
);
1333 out_printf( "(builtin):" );
1335 out_printf( "%s:%d:", file
, line
);
1340 * backtrace_line() - print a single line of error backtrace for the given
1344 void backtrace_line( FRAME
* frame
)
1348 out_printf( "(no frame):" );
1352 print_source_line( frame
);
1353 out_printf( " in %s\n", frame
->rulename
);
1359 * backtrace() - Print the entire backtrace from the given frame to the Jambase
1363 void backtrace( FRAME
* frame
)
1365 if ( !frame
) return;
1366 while ( ( frame
= frame
->prev
) )
1367 backtrace_line( frame
);
1372 * builtin_backtrace() - A Jam version of the backtrace function, taking no
1373 * arguments and returning a list of quadruples: FILENAME LINE MODULE. RULENAME
1374 * describing each frame. Note that the module-name is always followed by a
1378 LIST
* builtin_backtrace( FRAME
* frame
, int flags
)
1380 LIST
* const levels_arg
= lol_get( frame
->args
, 0 );
1381 int levels
= list_empty( levels_arg
)
1382 ? (int)( (unsigned int)(-1) >> 1 )
1383 : atoi( object_str( list_front( levels_arg
) ) );
1386 for ( ; ( frame
= frame
->prev
) && levels
; --levels
)
1391 string module_name
[ 1 ];
1392 get_source_line( frame
, &file
, &line
);
1393 sprintf( buf
, "%d", line
);
1394 string_new( module_name
);
1395 if ( frame
->module
->name
)
1397 string_append( module_name
, object_str( frame
->module
->name
) );
1398 string_append( module_name
, "." );
1400 result
= list_push_back( result
, object_new( file
) );
1401 result
= list_push_back( result
, object_new( buf
) );
1402 result
= list_push_back( result
, object_new( module_name
->value
) );
1403 result
= list_push_back( result
, object_new( frame
->rulename
) );
1404 string_free( module_name
);
1411 * builtin_caller_module() - CALLER_MODULE ( levels ? )
1413 * If levels is not supplied, returns the name of the module of the rule which
1414 * called the one calling this one. If levels is supplied, it is interpreted as
1415 * an integer specifying a number of additional levels of call stack to traverse
1416 * in order to locate the module in question. If no such module exists, returns
1417 * the empty list. Also returns the empty list when the module in question is
1418 * the global module. This rule is needed for implementing module import
1422 LIST
* builtin_caller_module( FRAME
* frame
, int flags
)
1424 LIST
* const levels_arg
= lol_get( frame
->args
, 0 );
1425 int const levels
= list_empty( levels_arg
)
1427 : atoi( object_str( list_front( levels_arg
) ) );
1430 for ( i
= 0; ( i
< levels
+ 2 ) && frame
->prev
; ++i
)
1431 frame
= frame
->prev
;
1433 return frame
->module
== root_module()
1435 : list_new( object_copy( frame
->module
->name
) );
1440 * Return the current working directory.
1442 * Usage: pwd = [ PWD ] ;
1445 LIST
* builtin_pwd( FRAME
* frame
, int flags
)
1447 return list_new( object_copy( cwd() ) );
1452 * Adds targets to the list of target that jam will attempt to update.
1455 LIST
* builtin_update( FRAME
* frame
, int flags
)
1457 LIST
* result
= list_copy( targets_to_update() );
1458 LIST
* arg1
= lol_get( frame
->args
, 0 );
1459 LISTITER iter
= list_begin( arg1
), end
= list_end( arg1
);
1460 clear_targets_to_update();
1461 for ( ; iter
!= end
; iter
= list_next( iter
) )
1462 mark_target_for_updating( object_copy( list_item( iter
) ) );
1467 int last_update_now_status
;
1469 /* Takes a list of target names and immediately updates them.
1473 * 2. Optional file descriptor (converted to a string) for a log file where all
1474 * the related build output should be redirected.
1475 * 3. If specified, makes the build temporarily disable the -n option, i.e.
1476 * forces all needed out-of-date targets to be rebuilt.
1477 * 4. If specified, makes the build temporarily disable the -q option, i.e.
1478 * forces the build to continue even if one of the targets fails to build.
1480 LIST
* builtin_update_now( FRAME
* frame
, int flags
)
1482 LIST
* targets
= lol_get( frame
->args
, 0 );
1483 LIST
* log
= lol_get( frame
->args
, 1 );
1484 LIST
* force
= lol_get( frame
->args
, 2 );
1485 LIST
* continue_
= lol_get( frame
->args
, 3 );
1487 int original_stdout
= 0;
1488 int original_stderr
= 0;
1489 int original_noexec
= 0;
1490 int original_quitquick
= 0;
1492 if ( !list_empty( log
) )
1494 /* Temporarily redirect stdout and stderr to the given log file. */
1495 int const fd
= atoi( object_str( list_front( log
) ) );
1496 original_stdout
= dup( 0 );
1497 original_stderr
= dup( 1 );
1502 if ( !list_empty( force
) )
1504 original_noexec
= globs
.noexec
;
1508 if ( !list_empty( continue_
) )
1510 original_quitquick
= globs
.quitquick
;
1511 globs
.quitquick
= 0;
1514 status
= make( targets
, anyhow
);
1516 if ( !list_empty( force
) )
1518 globs
.noexec
= original_noexec
;
1521 if ( !list_empty( continue_
) )
1523 globs
.quitquick
= original_quitquick
;
1526 if ( !list_empty( log
) )
1528 /* Flush whatever stdio might have buffered, while descriptions 0 and 1
1529 * still refer to the log file.
1533 dup2( original_stdout
, 0 );
1534 dup2( original_stderr
, 1 );
1535 close( original_stdout
);
1536 close( original_stderr
);
1539 last_update_now_status
= status
;
1541 return status
? L0
: list_new( object_copy( constant_ok
) );
1545 LIST
* builtin_import_module( FRAME
* frame
, int flags
)
1547 LIST
* const arg1
= lol_get( frame
->args
, 0 );
1548 LIST
* const arg2
= lol_get( frame
->args
, 1 );
1549 module_t
* const m
= list_empty( arg2
)
1551 : bindmodule( list_front( arg2
) );
1552 import_module( arg1
, m
);
1557 LIST
* builtin_imported_modules( FRAME
* frame
, int flags
)
1559 LIST
* const arg0
= lol_get( frame
->args
, 0 );
1560 OBJECT
* const module
= list_empty( arg0
) ? 0 : list_front( arg0
);
1561 return imported_modules( bindmodule( module
) );
1565 LIST
* builtin_instance( FRAME
* frame
, int flags
)
1567 LIST
* arg1
= lol_get( frame
->args
, 0 );
1568 LIST
* arg2
= lol_get( frame
->args
, 1 );
1569 module_t
* const instance
= bindmodule( list_front( arg1
) );
1570 module_t
* const class_module
= bindmodule( list_front( arg2
) );
1571 instance
->class_module
= class_module
;
1572 module_set_fixed_variables( instance
, class_module
->num_fixed_variables
);
1577 LIST
* builtin_sort( FRAME
* frame
, int flags
)
1579 return list_sort( lol_get( frame
->args
, 0 ) );
1583 LIST
* builtin_normalize_path( FRAME
* frame
, int flags
)
1585 LIST
* arg
= lol_get( frame
->args
, 0 );
1587 /* First, we iterate over all '/'-separated elements, starting from the end
1588 * of string. If we see a '..', we remove a preceding path element. If we
1589 * see '.', we remove it. Removal is done by overwriting data using '\1'
1590 * characters. After the whole string has been processed, we do a second
1591 * pass, removing any entered '\1' characters.
1596 /* Last character of the part of string still to be processed. */
1598 /* Working pointer. */
1600 /* Number of '..' elements seen and not processed yet. */
1603 OBJECT
* result
= 0;
1604 LISTITER arg_iter
= list_begin( arg
);
1605 LISTITER arg_end
= list_end( arg
);
1607 /* Make a copy of input: we should not change it. Prepend a '/' before it as
1608 * a guard for the algorithm later on and remember whether it was originally
1612 string_push_back( in
, '/' );
1613 for ( ; arg_iter
!= arg_end
; arg_iter
= list_next( arg_iter
) )
1615 if ( object_str( list_item( arg_iter
) )[ 0 ] != '\0' )
1617 if ( in
->size
== 1 )
1618 rooted
= ( object_str( list_item( arg_iter
) )[ 0 ] == '/' ) ||
1619 ( object_str( list_item( arg_iter
) )[ 0 ] == '\\' );
1621 string_append( in
, "/" );
1622 string_append( in
, object_str( list_item( arg_iter
) ) );
1626 /* Convert \ into /. On Windows, paths using / and \ are equivalent, and we
1627 * want this function to obtain a canonic representation.
1629 for ( current
= in
->value
, end
= in
->value
+ in
->size
;
1630 current
< end
; ++current
)
1631 if ( *current
== '\\' )
1634 /* Now we remove any extra path elements by overwriting them with '\1'
1635 * characters and count how many more unused '..' path elements there are
1636 * remaining. Note that each remaining path element with always starts with
1639 for ( end
= in
->value
+ in
->size
- 1; end
>= in
->value
; )
1641 /* Set 'current' to the next occurrence of '/', which always exists. */
1642 for ( current
= end
; *current
!= '/'; --current
);
1644 if ( current
== end
)
1646 /* Found a trailing or duplicate '/'. Remove it. */
1649 else if ( ( end
- current
== 1 ) && ( *( current
+ 1 ) == '.' ) )
1651 /* Found '/.'. Remove them all. */
1653 *(current
+ 1) = '\1';
1655 else if ( ( end
- current
== 2 ) && ( *( current
+ 1 ) == '.' ) &&
1656 ( *( current
+ 2 ) == '.' ) )
1658 /* Found '/..'. Remove them all. */
1660 *(current
+ 1) = '\1';
1661 *(current
+ 2) = '\1';
1666 memset( current
, '\1', end
- current
+ 1 );
1674 /* Now we know that we need to add exactly dotdots '..' path elements to the
1675 * front and that our string is either empty or has a '/' as its first
1676 * significant character. If we have any dotdots remaining then the passed
1677 * path must not have been rooted or else it is invalid we return an empty
1689 string_append( out
, "/.." );
1690 while ( --dotdots
);
1693 /* Now we actually remove all the path characters marked for removal. */
1694 for ( current
= in
->value
; *current
; ++current
)
1695 if ( *current
!= '\1' )
1696 string_push_back( out
, *current
);
1698 /* Here we know that our string contains no '\1' characters and is either
1699 * empty or has a '/' as its initial character. If the original path was not
1700 * rooted and we have a non-empty path we need to drop the initial '/'. If
1701 * the original path was rooted and we have an empty path we need to add
1704 result
= object_new( out
->size
1705 ? out
->value
+ !rooted
1706 : ( rooted
? "/" : "." ) );
1711 return list_new( result
);
1715 LIST
* builtin_native_rule( FRAME
* frame
, int flags
)
1717 LIST
* module_name
= lol_get( frame
->args
, 0 );
1718 LIST
* rule_name
= lol_get( frame
->args
, 1 );
1720 module_t
* module
= bindmodule( list_front( module_name
) );
1723 if ( module
->native_rules
&& (np
= (native_rule_t
*)hash_find(
1724 module
->native_rules
, list_front( rule_name
) ) ) )
1726 new_rule_body( module
, np
->name
, np
->procedure
, 1 );
1730 backtrace_line( frame
->prev
);
1731 out_printf( "error: no native rule \"%s\" defined in module \"%s.\"\n",
1732 object_str( list_front( rule_name
) ), object_str( module
->name
) );
1733 backtrace( frame
->prev
);
1740 LIST
* builtin_has_native_rule( FRAME
* frame
, int flags
)
1742 LIST
* module_name
= lol_get( frame
->args
, 0 );
1743 LIST
* rule_name
= lol_get( frame
->args
, 1 );
1744 LIST
* version
= lol_get( frame
->args
, 2 );
1746 module_t
* module
= bindmodule( list_front( module_name
) );
1749 if ( module
->native_rules
&& (np
= (native_rule_t
*)hash_find(
1750 module
->native_rules
, list_front( rule_name
) ) ) )
1752 int expected_version
= atoi( object_str( list_front( version
) ) );
1753 if ( np
->version
== expected_version
)
1754 return list_new( object_copy( constant_true
) );
1760 LIST
* builtin_user_module( FRAME
* frame
, int flags
)
1762 LIST
* const module_name
= lol_get( frame
->args
, 0 );
1763 LISTITER iter
= list_begin( module_name
);
1764 LISTITER
const end
= list_end( module_name
);
1765 for ( ; iter
!= end
; iter
= list_next( iter
) )
1766 bindmodule( list_item( iter
) )->user_module
= 1;
1771 LIST
* builtin_nearest_user_location( FRAME
* frame
, int flags
)
1773 FRAME
* const nearest_user_frame
= frame
->module
->user_module
1776 if ( !nearest_user_frame
)
1785 get_source_line( nearest_user_frame
, &file
, &line
);
1786 sprintf( buf
, "%d", line
);
1787 result
= list_push_back( result
, object_new( file
) );
1788 result
= list_push_back( result
, object_new( buf
) );
1794 LIST
* builtin_check_if_file( FRAME
* frame
, int flags
)
1796 LIST
* const name
= lol_get( frame
->args
, 0 );
1797 return file_is_file( list_front( name
) ) == 1
1798 ? list_new( object_copy( constant_true
) )
1803 LIST
* builtin_md5( FRAME
* frame
, int flags
)
1805 LIST
* l
= lol_get( frame
->args
, 0 );
1806 char const * s
= object_str( list_front( l
) );
1809 md5_byte_t digest
[ 16 ];
1810 char hex_output
[ 16 * 2 + 1 ];
1815 md5_append( &state
, (md5_byte_t
const *)s
, strlen( s
) );
1816 md5_finish( &state
, digest
);
1818 for ( di
= 0; di
< 16; ++di
)
1819 sprintf( hex_output
+ di
* 2, "%02x", digest
[ di
] );
1821 return list_new( object_new( hex_output
) );
1825 LIST
* builtin_file_open( FRAME
* frame
, int flags
)
1827 char const * name
= object_str( list_front( lol_get( frame
->args
, 0 ) ) );
1828 char const * mode
= object_str( list_front( lol_get( frame
->args
, 1 ) ) );
1830 char buffer
[ sizeof( "4294967295" ) ];
1832 if ( strcmp(mode
, "w") == 0 )
1833 fd
= open( name
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666 );
1835 fd
= open( name
, O_RDONLY
);
1839 sprintf( buffer
, "%d", fd
);
1840 return list_new( object_new( buffer
) );
1846 LIST
* builtin_pad( FRAME
* frame
, int flags
)
1848 OBJECT
* string
= list_front( lol_get( frame
->args
, 0 ) );
1849 char const * width_s
= object_str( list_front( lol_get( frame
->args
, 1 ) ) );
1851 int current
= strlen( object_str( string
) );
1852 int desired
= atoi( width_s
);
1853 if ( current
>= desired
)
1854 return list_new( object_copy( string
) );
1857 char * buffer
= (char *)BJAM_MALLOC( desired
+ 1 );
1861 strcpy( buffer
, object_str( string
) );
1862 for ( i
= current
; i
< desired
; ++i
)
1864 buffer
[ desired
] = '\0';
1865 result
= list_new( object_new( buffer
) );
1866 BJAM_FREE( buffer
);
1872 LIST
* builtin_precious( FRAME
* frame
, int flags
)
1874 LIST
* targets
= lol_get( frame
->args
, 0 );
1875 LISTITER iter
= list_begin( targets
);
1876 LISTITER
const end
= list_end( targets
);
1877 for ( ; iter
!= end
; iter
= list_next( iter
) )
1878 bindtarget( list_item( iter
) )->flags
|= T_FLAG_PRECIOUS
;
1883 LIST
* builtin_self_path( FRAME
* frame
, int flags
)
1885 extern char const * saved_argv0
;
1886 char * p
= executable_path( saved_argv0
);
1889 LIST
* const result
= list_new( object_new( p
) );
1897 LIST
* builtin_makedir( FRAME
* frame
, int flags
)
1899 LIST
* const path
= lol_get( frame
->args
, 0 );
1900 return file_mkdir( object_str( list_front( path
) ) )
1902 : list_new( object_copy( list_front( path
) ) );
1905 LIST
*builtin_readlink( FRAME
* frame
, int flags
)
1907 const char * path
= object_str( list_front( lol_get( frame
->args
, 0 ) ) );
1910 /* This struct is declared in ntifs.h which is
1911 * part of the Windows Driver Kit.
1913 typedef struct _REPARSE_DATA_BUFFER
{
1915 USHORT ReparseDataLength
;
1919 USHORT SubstituteNameOffset
;
1920 USHORT SubstituteNameLength
;
1921 USHORT PrintNameOffset
;
1922 USHORT PrintNameLength
;
1924 WCHAR PathBuffer
[ 1 ];
1925 } SymbolicLinkReparseBuffer
;
1927 USHORT SubstituteNameOffset
;
1928 USHORT SubstituteNameLength
;
1929 USHORT PrintNameOffset
;
1930 USHORT PrintNameLength
;
1931 WCHAR PathBuffer
[ 1 ];
1932 } MountPointReparseBuffer
;
1934 UCHAR DataBuffer
[ 1 ];
1935 } GenericReparseBuffer
;
1937 } REPARSE_DATA_BUFFER
;
1939 HANDLE hLink
= CreateFileA( path
, 0, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT
, NULL
);
1942 REPARSE_DATA_BUFFER reparse
;
1943 char data
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
1945 int okay
= DeviceIoControl(hLink
, FSCTL_GET_REPARSE_POINT
, NULL
, 0, &buf
, sizeof(buf
), &n
, NULL
);
1947 CloseHandle( hLink
);
1949 if (okay
&& buf
.reparse
.ReparseTag
== IO_REPARSE_TAG_SYMLINK
)
1951 int index
= buf
.reparse
.SymbolicLinkReparseBuffer
.SubstituteNameOffset
/ 2;
1952 int length
= buf
.reparse
.SymbolicLinkReparseBuffer
.SubstituteNameLength
/ 2;
1953 char cbuf
[MAX_PATH
+ 1];
1954 int numchars
= WideCharToMultiByte( CP_ACP
, 0, buf
.reparse
.SymbolicLinkReparseBuffer
.PathBuffer
+ index
, length
, cbuf
, sizeof(cbuf
), NULL
, NULL
);
1955 if( numchars
>= int(sizeof(cbuf
)) )
1959 cbuf
[numchars
] = '\0';
1960 return list_new( object_new( cbuf
) );
1962 else if( okay
&& buf
.reparse
.ReparseTag
== IO_REPARSE_TAG_MOUNT_POINT
)
1964 int index
= buf
.reparse
.MountPointReparseBuffer
.SubstituteNameOffset
/ 2;
1965 int length
= buf
.reparse
.MountPointReparseBuffer
.SubstituteNameLength
/ 2;
1966 char cbuf
[MAX_PATH
+ 1];
1967 const char * result
;
1968 int numchars
= WideCharToMultiByte( CP_ACP
, 0, buf
.reparse
.MountPointReparseBuffer
.PathBuffer
+ index
, length
, cbuf
, sizeof(cbuf
), NULL
, NULL
);
1969 if( numchars
>= int(sizeof(cbuf
)) )
1973 cbuf
[numchars
] = '\0';
1974 /* strip off the leading "\??\" */
1976 if ( cbuf
[ 0 ] == '\\' && cbuf
[ 1 ] == '?' &&
1977 cbuf
[ 2 ] == '?' && cbuf
[ 3 ] == '\\' &&
1978 cbuf
[ 4 ] != '\0' && cbuf
[ 5 ] == ':' )
1982 return list_new( object_new( result
) );
1986 char static_buf
[256];
1987 char * buf
= static_buf
;
1988 size_t bufsize
= 256;
1991 ssize_t len
= readlink( path
, buf
, bufsize
);
1996 else if ( size_t(len
) < bufsize
)
1999 result
= list_new( object_new( buf
) );
2002 if ( buf
!= static_buf
)
2005 buf
= (char *)BJAM_MALLOC( bufsize
);
2008 if ( buf
!= static_buf
)
2017 LIST
*builtin_debug_print_helper( FRAME
* frame
, int flags
)
2019 debug_print_result
= list_copy( lol_get( frame
->args
, 0 ) );
2027 LIST
* builtin_python_import_rule( FRAME
* frame
, int flags
)
2029 static int first_time
= 1;
2030 char const * python_module
= object_str( list_front( lol_get( frame
->args
,
2032 char const * python_function
= object_str( list_front( lol_get( frame
->args
,
2034 OBJECT
* jam_module
= list_front( lol_get( frame
->args
, 2 ) );
2035 OBJECT
* jam_rule
= list_front( lol_get( frame
->args
, 3 ) );
2044 /* At the first invocation, we add the value of the global
2045 * EXTRA_PYTHONPATH to the sys.path Python variable.
2048 module_t
* outer_module
= frame
->module
;
2053 extra
= var_get( root_module(), constant_extra_pythonpath
);
2055 iter
= list_begin( extra
), end
= list_end( extra
);
2056 for ( ; iter
!= end
; iter
= list_next( iter
) )
2060 string_append( buf
, "import sys\nsys.path.append(\"" );
2061 string_append( buf
, object_str( list_item( iter
) ) );
2062 string_append( buf
, "\")\n" );
2063 PyRun_SimpleString( buf
->value
);
2068 pName
= PyString_FromString( python_module
);
2069 pModule
= PyImport_Import( pName
);
2072 if ( pModule
!= NULL
)
2074 pDict
= PyModule_GetDict( pModule
);
2075 pFunc
= PyDict_GetItemString( pDict
, python_function
);
2077 if ( pFunc
&& PyCallable_Check( pFunc
) )
2079 module_t
* m
= bindmodule( jam_module
);
2080 new_rule_body( m
, jam_rule
, function_python( pFunc
, 0 ), 0 );
2084 if ( PyErr_Occurred() )
2086 err_printf( "Cannot find function \"%s\"\n", python_function
);
2088 Py_DECREF( pModule
);
2093 err_printf( "Failed to load \"%s\"\n", python_module
);
2099 #endif /* #ifdef HAVE_PYTHON */
2102 void lol_build( LOL
* lol
, char const * * elements
)
2107 while ( elements
&& *elements
)
2109 if ( !strcmp( *elements
, ":" ) )
2116 l
= list_push_back( l
, object_new( *elements
) );
2128 static LIST
*jam_list_from_string(PyObject
*a
)
2130 return list_new( object_new( PyString_AsString( a
) ) );
2133 static LIST
*jam_list_from_sequence(PyObject
*a
)
2138 int s
= PySequence_Size( a
);
2140 for ( ; i
< s
; ++i
)
2142 /* PySequence_GetItem returns new reference. */
2143 PyObject
* e
= PySequence_GetItem( a
, i
);
2144 char * s
= PyString_AsString( e
);
2147 /* try to get the repr() on the object */
2148 PyObject
*repr
= PyObject_Repr(e
);
2151 const char *str
= PyString_AsString(repr
);
2152 PyErr_Format(PyExc_TypeError
, "expecting type <str> got %s", str
);
2154 /* fall back to a dumb error */
2157 PyErr_BadArgument();
2161 l
= list_push_back( l
, object_new( s
) );
2168 static void make_jam_arguments_from_python(FRAME
* inner
, PyObject
*args
)
2173 /* Build up the list of arg lists. */
2174 frame_init( inner
);
2176 inner
->prev_user
= 0;
2177 inner
->module
= bindmodule( constant_python_interface
);
2179 size
= PyTuple_Size( args
);
2180 for (i
= 0 ; i
< size
; ++i
)
2182 PyObject
* a
= PyTuple_GetItem( args
, i
);
2183 if ( PyString_Check( a
) )
2185 lol_add( inner
->args
, jam_list_from_string(a
) );
2187 else if ( PySequence_Check( a
) )
2189 lol_add( inner
->args
, jam_list_from_sequence(a
) );
2196 * Calls the bjam rule specified by name passed in 'args'. The name is looked up
2197 * in the context of bjam's 'python_interface' module. Returns the list of
2198 * strings returned by the rule.
2201 PyObject
* bjam_call( PyObject
* self
, PyObject
* args
)
2207 PyObject
*args_proper
;
2209 /* PyTuple_GetItem returns borrowed reference. */
2210 rulename
= object_new( PyString_AsString( PyTuple_GetItem( args
, 0 ) ) );
2212 args_proper
= PyTuple_GetSlice(args
, 1, PyTuple_Size(args
));
2213 make_jam_arguments_from_python (inner
, args_proper
);
2214 if ( PyErr_Occurred() )
2218 Py_DECREF(args_proper
);
2220 result
= evaluate_rule( bindrule( rulename
, inner
->module
), rulename
, inner
);
2221 object_free( rulename
);
2223 frame_free( inner
);
2225 /* Convert the bjam list into a Python list result. */
2227 PyObject
* const pyResult
= PyList_New( list_length( result
) );
2229 LISTITER iter
= list_begin( result
);
2230 LISTITER
const end
= list_end( result
);
2231 for ( ; iter
!= end
; iter
= list_next( iter
) )
2233 PyList_SetItem( pyResult
, i
, PyString_FromString( object_str(
2234 list_item( iter
) ) ) );
2237 list_free( result
);
2244 * Accepts four arguments:
2247 * - Python callable.
2248 * - (optional) bjam language function signature.
2249 * Creates a bjam rule with the specified name in the specified module, which
2250 * will invoke the Python callable.
2253 PyObject
* bjam_import_rule( PyObject
* self
, PyObject
* args
)
2258 PyObject
* bjam_signature
= NULL
;
2261 OBJECT
* module_name
;
2264 if ( !PyArg_ParseTuple( args
, "ssO|O:import_rule",
2265 &module
, &rule
, &func
, &bjam_signature
) )
2268 if ( !PyCallable_Check( func
) )
2270 PyErr_SetString( PyExc_RuntimeError
, "Non-callable object passed to "
2271 "bjam.import_rule" );
2275 module_name
= *module
? object_new( module
) : 0;
2276 m
= bindmodule( module_name
);
2278 object_free( module_name
);
2279 rule_name
= object_new( rule
);
2280 new_rule_body( m
, rule_name
, function_python( func
, bjam_signature
), 0 );
2281 object_free( rule_name
);
2283 Py_INCREF( Py_None
);
2289 * Accepts four arguments:
2292 * - a list of variable that will be bound inside the action
2294 * Defines an action on bjam side.
2297 PyObject
* bjam_define_action( PyObject
* self
, PyObject
* args
)
2302 PyObject
* bindlist_python
;
2304 LIST
* bindlist
= L0
;
2308 FUNCTION
* body_func
;
2310 if ( !PyArg_ParseTuple( args
, "ssO!i:define_action", &name
, &body
,
2311 &PyList_Type
, &bindlist_python
, &flags
) )
2314 n
= PyList_Size( bindlist_python
);
2315 for ( i
= 0; i
< n
; ++i
)
2317 PyObject
* next
= PyList_GetItem( bindlist_python
, i
);
2318 if ( !PyString_Check( next
) )
2320 PyErr_SetString( PyExc_RuntimeError
, "bind list has non-string "
2324 bindlist
= list_push_back( bindlist
, object_new( PyString_AsString( next
2328 name_str
= object_new( name
);
2329 body_func
= function_compile_actions( body
, constant_builtin
, -1 );
2330 new_rule_actions( root_module(), name_str
, body_func
, bindlist
, flags
);
2331 function_free( body_func
);
2332 object_free( name_str
);
2334 Py_INCREF( Py_None
);
2340 * Returns the value of a variable in root Jam module.
2343 PyObject
* bjam_variable( PyObject
* self
, PyObject
* args
)
2353 if ( !PyArg_ParseTuple( args
, "s", &name
) )
2356 varname
= object_new( name
);
2357 value
= var_get( root_module(), varname
);
2358 object_free( varname
);
2359 iter
= list_begin( value
);
2360 end
= list_end( value
);
2362 result
= PyList_New( list_length( value
) );
2363 for ( i
= 0; iter
!= end
; iter
= list_next( iter
), ++i
)
2364 PyList_SetItem( result
, i
, PyString_FromString( object_str( list_item(
2371 PyObject
* bjam_backtrace( PyObject
* self
, PyObject
* args
)
2373 PyObject
* result
= PyList_New( 0 );
2374 struct frame
* f
= frame_before_python_call
;
2376 for ( ; (f
= f
->prev
); )
2378 PyObject
* tuple
= PyTuple_New( 4 );
2382 string module_name
[ 1 ];
2384 get_source_line( f
, &file
, &line
);
2385 sprintf( buf
, "%d", line
);
2386 string_new( module_name
);
2387 if ( f
->module
->name
)
2389 string_append( module_name
, object_str( f
->module
->name
) );
2390 string_append( module_name
, "." );
2393 /* PyTuple_SetItem steals reference. */
2394 PyTuple_SetItem( tuple
, 0, PyString_FromString( file
) );
2395 PyTuple_SetItem( tuple
, 1, PyString_FromString( buf
) );
2396 PyTuple_SetItem( tuple
, 2, PyString_FromString( module_name
->value
) );
2397 PyTuple_SetItem( tuple
, 3, PyString_FromString( f
->rulename
) );
2399 string_free( module_name
);
2401 PyList_Append( result
, tuple
);
2407 PyObject
* bjam_caller( PyObject
* self
, PyObject
* args
)
2409 return PyString_FromString( frame_before_python_call
->prev
->module
->name
?
2410 object_str( frame_before_python_call
->prev
->module
->name
) : "" );
2413 #endif /* #ifdef HAVE_PYTHON */
2418 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW64__) || defined(__MINGW32__)
2420 #define popen windows_popen_wrapper
2422 #define pclose _pclose
2425 * This wrapper is a workaround for a funny _popen() feature on Windows
2426 * where it eats external quotes in some cases. The bug seems to be related
2427 * to the quote stripping functionality used by the Windows cmd.exe
2428 * interpreter when its /S is not specified.
2430 * Cleaned up quote from the cmd.exe help screen as displayed on Windows XP
2433 * 1. If all of the following conditions are met, then quote characters on
2434 * the command line are preserved:
2437 * - exactly two quote characters
2438 * - no special characters between the two quote characters, where
2439 * special is one of: &<>()@^|
2440 * - there are one or more whitespace characters between the two quote
2442 * - the string between the two quote characters is the name of an
2445 * 2. Otherwise, old behavior is to see if the first character is a quote
2446 * character and if so, strip the leading character and remove the last
2447 * quote character on the command line, preserving any text after the
2448 * last quote character.
2450 * This causes some commands containing quotes not to be executed correctly.
2453 * "\Long folder name\aaa.exe" --name="Jurko" --no-surname
2455 * would get its outermost quotes stripped and would be executed as:
2457 * \Long folder name\aaa.exe" --name="Jurko --no-surname
2459 * which would report an error about '\Long' not being a valid command.
2461 * cmd.exe help seems to indicate it would be enough to add an extra space
2462 * character in front of the command to avoid this but this does not work,
2463 * most likely due to the shell first stripping all leading whitespace
2464 * characters from the command.
2466 * Solution implemented here is to quote the whole command in case it
2467 * contains any quote characters. Note thought this will not work correctly
2468 * should Windows ever 'fix' this feature.
2469 * (03.06.2008.) (Jurko)
2471 static FILE * windows_popen_wrapper( char const * command
,
2474 int const extra_command_quotes_needed
= !!strchr( command
, '"' );
2475 string quoted_command
;
2478 if ( extra_command_quotes_needed
)
2480 string_new( "ed_command
);
2481 string_append( "ed_command
, "\"" );
2482 string_append( "ed_command
, command
);
2483 string_append( "ed_command
, "\"" );
2484 command
= quoted_command
.value
;
2487 result
= _popen( command
, "r" );
2489 if ( extra_command_quotes_needed
)
2490 string_free( "ed_command
);
2494 #endif /* defined(_MSC_VER) || defined(__BORLANDC__) */
2497 LIST
* builtin_shell( FRAME
* frame
, int flags
)
2499 LIST
* command
= lol_get( frame
->args
, 0 );
2503 char buffer
[ 1024 ];
2505 int exit_status
= -1;
2506 int exit_status_opt
= 0;
2507 int no_output_opt
= 0;
2508 int strip_eol_opt
= 0;
2510 /* Process the variable args options. */
2513 LIST
* arg
= lol_get( frame
->args
, a
);
2514 for ( ; !list_empty( arg
); arg
= lol_get( frame
->args
, ++a
) )
2516 if ( !strcmp( "exit-status", object_str( list_front( arg
) ) ) )
2517 exit_status_opt
= 1;
2518 else if ( !strcmp( "no-output", object_str( list_front( arg
) ) ) )
2520 else if ( !strcmp("strip-eol", object_str( list_front( arg
) ) ) )
2525 /* The following fflush() call seems to be indicated as a workaround for a
2526 * popen() bug on POSIX implementations related to synhronizing input
2527 * stream positions for the called and the calling process.
2531 p
= popen( object_str( list_front( command
) ), "r" );
2537 while ( ( ret
= fread( buffer
, sizeof( char ), sizeof( buffer
) - 1, p
) ) >
2541 if ( !no_output_opt
)
2543 string_append( &s
, buffer
);
2546 /* Explicit EOF check for systems with broken fread */
2547 if ( feof( p
) ) break;
2550 if ( strip_eol_opt
)
2553 exit_status
= pclose( p
);
2555 /* The command output is returned first. */
2556 result
= list_new( object_new( s
.value
) );
2559 /* The command exit result next. */
2560 if ( exit_status_opt
)
2562 if ( WIFEXITED( exit_status
) )
2563 exit_status
= WEXITSTATUS( exit_status
);
2568 /* Harmonize VMS success status with POSIX */
2569 if ( exit_status
== 1 ) exit_status
= EXIT_SUCCESS
;
2571 sprintf( buffer
, "%d", exit_status
);
2572 result
= list_push_back( result
, object_new( buffer
) );
2578 #else /* #ifdef HAVE_POPEN */
2580 LIST
* builtin_shell( FRAME
* frame
, int flags
)
2585 #endif /* #ifdef HAVE_POPEN */
2589 * builtin_glob_archive() - GLOB_ARCHIVE rule
2594 LIST
* patterns
[ 2 ];
2596 LIST
* case_insensitive
;
2600 static void builtin_glob_archive_back( void * closure
, OBJECT
* member
,
2601 LIST
* symbols
, int status
, timestamp
const * const time
)
2603 PROFILE_ENTER( BUILTIN_GLOB_ARCHIVE_BACK
);
2605 struct globbing2
* const globbing
= (struct globbing2
*)closure
;
2610 LISTITER iter_symbols
;
2611 LISTITER end_symbols
;
2614 /* Match member name.
2616 path_parse( object_str( member
), &f
);
2618 if ( !strcmp( f
.f_member
.ptr
, "" ) )
2620 PROFILE_EXIT( BUILTIN_GLOB_ARCHIVE_BACK
);
2625 string_append_range( buf
, f
.f_member
.ptr
, f
.f_member
.ptr
+ f
.f_member
.len
);
2627 if ( globbing
->case_insensitive
)
2628 downcase_inplace( buf
->value
);
2630 /* Glob with member patterns. If not matched, then match symbols.
2633 iter
= list_begin( globbing
->patterns
[ 0 ] );
2634 end
= list_end( globbing
->patterns
[ 0 ] );
2635 for ( ; !matched
&& iter
!= end
;
2636 iter
= list_next( iter
) )
2638 const char * pattern
= object_str( list_item( iter
) );
2639 int match_exact
= ( !has_wildcards( pattern
) );
2640 matched
= ( match_exact
?
2641 ( !strcmp( pattern
, buf
->value
) ) :
2642 ( !glob( pattern
, buf
->value
) ) );
2646 /* Glob with symbol patterns, if requested.
2648 iter
= list_begin( globbing
->patterns
[ 1 ] );
2649 end
= list_end( globbing
->patterns
[ 1 ] );
2651 if ( iter
!= end
) matched
= 0;
2653 for ( ; !matched
&& iter
!= end
;
2654 iter
= list_next( iter
) )
2656 const char * pattern
= object_str( list_item( iter
) );
2657 int match_exact
= ( !has_wildcards( pattern
) );
2659 iter_symbols
= list_begin( symbols
);
2660 end_symbols
= list_end( symbols
);
2662 for ( ; !matched
&& iter_symbols
!= end_symbols
;
2663 iter_symbols
= list_next( iter_symbols
) )
2665 const char * symbol
= object_str( list_item( iter_symbols
) );
2667 string_copy( buf
, symbol
);
2668 if ( globbing
->case_insensitive
)
2669 downcase_inplace( buf
->value
);
2671 matched
= ( match_exact
?
2672 ( !strcmp( pattern
, buf
->value
) ) :
2673 ( !glob( pattern
, buf
->value
) ) );
2679 globbing
->results
= list_push_back( globbing
->results
,
2680 object_copy( member
) );
2685 PROFILE_EXIT( BUILTIN_GLOB_ARCHIVE_BACK
);
2689 LIST
* builtin_glob_archive( FRAME
* frame
, int flags
)
2691 LIST
* const l
= lol_get( frame
->args
, 0 );
2692 LIST
* const r1
= lol_get( frame
->args
, 1 );
2693 LIST
* const r3
= lol_get( frame
->args
, 3 );
2697 struct globbing2 globbing
;
2699 globbing
.results
= L0
;
2700 globbing
.patterns
[ 0 ] = r1
;
2701 globbing
.patterns
[ 1 ] = r3
;
2703 globbing
.case_insensitive
=
2704 # if defined( OS_NT ) || defined( OS_CYGWIN ) || defined( OS_VMS )
2705 l
; /* Always case-insensitive. */
2707 lol_get( frame
->args
, 2 ); // r2
2710 if ( globbing
.case_insensitive
)
2712 globbing
.patterns
[ 0 ] = downcase_list( globbing
.patterns
[ 0 ] );
2713 globbing
.patterns
[ 1 ] = downcase_list( globbing
.patterns
[ 1 ] );
2716 iter
= list_begin( l
);
2717 end
= list_end( l
);
2718 for ( ; iter
!= end
; iter
= list_next( iter
) )
2719 file_archivescan( list_item( iter
), builtin_glob_archive_back
, &globbing
);
2721 if ( globbing
.case_insensitive
)
2723 list_free( globbing
.patterns
[ 0 ] );
2724 list_free( globbing
.patterns
[ 1 ] );
2727 return globbing
.results
;