📄 builtins.c
字号:
/*
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "builtins.h"
# include "rules.h"
# include "filesys.h"
# include "newstr.h"
# include "regexp.h"
# include "frames.h"
# include "hash.h"
# include "strings.h"
# include "pwd.h"
# include "pathsys.h"
# include "make.h"
# include "hdrmacro.h"
# include "compile.h"
# include "native.h"
# include "variable.h"
# include <ctype.h>
/*
* builtins.c - builtin jam rules
*
* External routines:
*
* load_builtin() - define builtin rules
*
* Internal routines:
*
* builtin_depends() - DEPENDS/INCLUDES rule
* builtin_echo() - ECHO rule
* builtin_exit() - EXIT rule
* builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
* builtin_glob() - GLOB rule
* builtin_match() - MATCH rule
*
* 01/10/01 (seiwald) - split from compile.c
*/
/*
* compile_builtin() - define builtin rules
*/
# define P0 (PARSE *)0
# define C0 (char *)0
# ifdef OS_NT
LIST* builtin_system_registry( PARSE *parse, FRAME *frame );
# endif
int glob( char *s, char *c );
void lol_build( LOL* lol, char** elements );
void backtrace( FRAME *frame );
void backtrace_line( FRAME *frame );
void print_source_line( PARSE* p );
RULE* bind_builtin( char* name, LIST*(*f)(PARSE*, FRAME*), int flags, char** args )
{
argument_list* arg_list = 0;
if ( args )
{
arg_list = args_new();
lol_build( arg_list->data, args );
}
return new_rule_body( root_module(), name, arg_list,
parse_make( f, P0, P0, P0, C0, C0, flags ), 1 );
}
RULE* duplicate_rule( char* name, RULE* other )
{
return import_rule( other, root_module(), name );
}
void
load_builtins()
{
duplicate_rule( "Always" ,
bind_builtin( "ALWAYS" ,
builtin_flags, T_FLAG_TOUCHED, 0 ) );
duplicate_rule( "Depends" ,
bind_builtin( "DEPENDS" ,
builtin_depends, 0, 0 ) );
duplicate_rule( "echo" ,
duplicate_rule( "Echo" ,
bind_builtin( "ECHO" ,
builtin_echo, 0, 0 ) ) );
duplicate_rule( "exit" ,
duplicate_rule( "Exit" ,
bind_builtin( "EXIT" ,
builtin_exit, 0, 0 ) ) );
{
char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 };
duplicate_rule(
"Glob" ,
bind_builtin( "GLOB" , builtin_glob, 0, args )
);
}
{
char * args[] = { "patterns", "*", 0 };
bind_builtin( "GLOB-RECURSIVELY" , builtin_glob_recursive, 0, args );
}
duplicate_rule( "Includes" ,
bind_builtin( "INCLUDES" ,
builtin_depends, 1, 0 ) );
{
char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 };
bind_builtin( "REBUILDS" ,
builtin_rebuilds, 0, args );
}
duplicate_rule( "Leaves" ,
bind_builtin( "LEAVES" ,
builtin_flags, T_FLAG_LEAVES, 0 ) );
duplicate_rule( "Match" ,
bind_builtin( "MATCH" ,
builtin_match, 0, 0 ) );
duplicate_rule( "NoCare" ,
bind_builtin( "NOCARE" ,
builtin_flags, T_FLAG_NOCARE, 0 ) );
duplicate_rule( "NOTIME" ,
duplicate_rule( "NotFile" ,
bind_builtin( "NOTFILE" ,
builtin_flags, T_FLAG_NOTFILE, 0 ) ) );
duplicate_rule( "NoUpdate" ,
bind_builtin( "NOUPDATE" ,
builtin_flags, T_FLAG_NOUPDATE, 0 ) );
duplicate_rule( "Temporary" ,
bind_builtin( "TEMPORARY" ,
builtin_flags, T_FLAG_TEMP, 0 ) );
{
char * args[] = { "targets", "*", 0 };
bind_builtin(
"ISFILE",
builtin_flags, T_FLAG_ISFILE, 0 );
}
duplicate_rule( "HdrMacro" ,
bind_builtin( "HDRMACRO" ,
builtin_hdrmacro, 0, 0 ) );
/* FAIL_EXPECTED is used to indicate that the result of a target build */
/* action should be inverted (ok <=> fail) this can be useful when */
/* performing test runs from Jamfiles.. */
bind_builtin( "FAIL_EXPECTED" ,
builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
bind_builtin( "RMOLD" , builtin_flags, T_FLAG_RMOLD, 0 );
{
char * args[] = { "targets", "*", 0 };
bind_builtin( "UPDATE", builtin_update, 0, args );
}
{
char * args[] = { "string", "pattern", "replacements", "+", 0 };
duplicate_rule( "subst" ,
bind_builtin( "SUBST" ,
builtin_subst, 0, args ) );
}
{
char * args[] = { "module", "?", 0 };
bind_builtin( "RULENAMES" ,
builtin_rulenames, 0, args );
}
{
char * args[] = { "module", "?", 0 };
bind_builtin( "VARNAMES" ,
builtin_varnames, 0, args );
}
{
char * args[] = { "module", "?", 0 };
bind_builtin( "DELETE_MODULE" ,
builtin_delete_module, 0, args );
}
{
char * args[] = { "source_module", "?",
":", "source_rules", "*",
":", "target_module", "?",
":", "target_rules", "*",
":", "localize", "?", 0 };
bind_builtin( "IMPORT" ,
builtin_import, 0, args );
}
{
char * args[] = { "module", "?", ":", "rules", "*", 0 };
bind_builtin( "EXPORT" ,
builtin_export, 0, args );
}
{
char * args[] = { "levels", "?", 0 };
bind_builtin( "CALLER_MODULE" ,
builtin_caller_module, 0, args );
}
{
char * args[] = { "levels", "?", 0 };
bind_builtin( "BACKTRACE" ,
builtin_backtrace, 0, args );
}
{
char * args[] = { 0 };
bind_builtin( "PWD" ,
builtin_pwd, 0, args );
}
{
char * args[] = { "target", "*", ":", "path", "*", 0 };
bind_builtin( "SEARCH_FOR_TARGET",
builtin_search_for_target, 0, args );
}
{
char * args[] = { "modules_to_import", "+", ":", "target_module", "?", 0 };
bind_builtin( "IMPORT_MODULE",
builtin_import_module, 0, args );
}
{
char * args[] = { "module", "?", 0 };
bind_builtin( "IMPORTED_MODULES",
builtin_imported_modules, 0, args );
}
{
char * args[] = { "instance_module", ":", "class_module", 0 };
bind_builtin( "INSTANCE",
builtin_instance, 0, args );
}
{
char * args[] = { "sequence", "*", 0 };
bind_builtin( "SORT",
builtin_sort, 0, args );
}
{
char * args[] = { "path", 0 };
bind_builtin( "NORMALIZE_PATH",
builtin_normalize_path, 0, args );
}
{
char * args[] = { "args", "*", 0 };
bind_builtin( "CALC",
builtin_calc, 0, args );
}
{
char * args[] = { "module", ":", "rule", 0 };
bind_builtin( "NATIVE_RULE",
builtin_native_rule, 0, args );
}
{
char * args[] = { "module", "*", 0 };
bind_builtin( "USER_MODULE",
builtin_user_module, 0, args );
}
{
char * args[] = { 0 };
bind_builtin( "NEAREST_USER_LOCATION",
builtin_nearest_user_location, 0, args );
}
{
char * args[] = { "file", 0 };
bind_builtin( "CHECK_IF_FILE",
builtin_check_if_file, 0, args );
}
#ifdef HAVE_PYTHON
{
char * args[] = { "python-module", ":", "function", ":",
"jam-module", ":", "rule-name", 0 };
bind_builtin( "PYTHON_IMPORT_RULE",
builtin_python_import_rule, 0, args );
}
#endif
# ifdef OS_NT
{
char * args[] = { "key_path", ":", "data", "?", 0 };
bind_builtin( "W32_GETREG",
builtin_system_registry, 0, args );
}
# endif
{
char * args[] = { "command", 0 };
bind_builtin( "SHELL",
builtin_shell, 0, args );
}
/* Initialize builtin modules */
init_set();
init_path();
init_regex();
init_property_set();
init_sequence();
init_order();
}
/*
* builtin_calc() - CALC rule
*
* The CALC rule performs simple mathematical operations on two arguments.
*/
LIST *
builtin_calc(
PARSE *parse,
FRAME *frame )
{
LIST *arg = lol_get( frame->args, 0 );
LIST *result = 0;
long lhs_value;
long rhs_value;
long result_value;
char buffer [16];
const char* lhs;
const char* op;
const char* rhs;
if (arg == 0) return L0;
lhs = arg->string;
arg = list_next( arg );
if (arg == 0) return L0;
op = arg->string;
arg = list_next( arg );
if (arg == 0) return L0;
rhs = arg->string;
lhs_value = atoi (lhs);
rhs_value = atoi (rhs);
if (strcmp ("+", op) == 0)
{
result_value = lhs_value + rhs_value;
}
else if (strcmp ("-", op) == 0)
{
result_value = lhs_value - rhs_value;
}
else
{
return L0;
}
sprintf (buffer, "%ld", result_value);
result = list_new( result, newstr( buffer ) );
return result;
}
/*
* builtin_depends() - DEPENDS/INCLUDES rule
*
* The DEPENDS builtin rule appends each of the listed sources on the
* dependency list of each of the listed targets. It binds both the
* targets and sources as TARGETs.
*/
LIST *
builtin_depends(
PARSE *parse,
FRAME *frame )
{
LIST *targets = lol_get( frame->args, 0 );
LIST *sources = lol_get( frame->args, 1 );
LIST *l;
for( l = targets; l; l = list_next( l ) )
{
TARGET *t = bindtarget( l->string );
/* If doing INCLUDES, switch to the TARGET's include */
/* TARGET, creating it if needed. The internal include */
/* TARGET shares the name of its parent. */
if( parse->num )
{
if( !t->includes ) {
t->includes = copytarget( t );
t->includes->original_target = t;
}
t = t->includes;
}
t->depends = targetlist( t->depends, sources );
}
/* Enter reverse links */
for( l = sources; l; l = list_next( l ) )
{
TARGET *s = bindtarget( l->string );
s->dependents = targetlist( s->dependents, targets );
}
return L0;
}
/*
* builtin_rebuilds() - REBUILDS rule
*
* The REBUILDS builtin rule appends each of the listed
* rebuild-targets in its 2nd argument on the rebuilds list of each of
* the listed targets in its first argument.
*/
LIST *
builtin_rebuilds(
PARSE *parse,
FRAME *frame )
{
LIST *targets = lol_get( frame->args, 0 );
LIST *rebuilds = lol_get( frame->args, 1 );
LIST *l;
for( l = targets; l; l = list_next( l ) )
{
TARGET *t = bindtarget( l->string );
t->rebuilds = targetlist( t->rebuilds, rebuilds );
}
return L0;
}
/*
* builtin_echo() - ECHO rule
*
* The ECHO builtin rule echoes the targets to the user. No other
* actions are taken.
*/
LIST *
builtin_echo(
PARSE *parse,
FRAME *frame )
{
list_print( lol_get( frame->args, 0 ) );
printf( "\n" );
return L0;
}
/*
* builtin_exit() - EXIT rule
*
* The EXIT builtin rule echoes the targets to the user and exits
* the program with a failure status.
*/
LIST *
builtin_exit(
PARSE *parse,
FRAME *frame )
{
list_print( lol_get( frame->args, 0 ) );
printf( "\n" );
exit( EXITBAD ); /* yeech */
return L0;
}
/*
* builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
*
* Builtin_flags() marks the target with the appropriate flag, for use
* by make0(). It binds each target as a TARGET.
*/
LIST *
builtin_flags(
PARSE *parse,
FRAME *frame )
{
LIST *l = lol_get( frame->args, 0 );
for( ; l; l = list_next( l ) )
bindtarget( l->string )->flags |= parse->num;
return L0;
}
/*
* builtin_globbing() - GLOB rule
*/
struct globbing {
LIST *patterns;
LIST *results;
LIST *case_insensitive;
} ;
static void downcase_inplace( char* p )
{
for ( ; *p; ++p )
{
*p = tolower(*p);
}
}
static void
builtin_glob_back(
void *closure,
char *file,
int status,
time_t time )
{
struct globbing *globbing = (struct globbing *)closure;
LIST *l;
PATHNAME f;
string buf[1];
/* Null out directory for matching. */
/* We wish we had file_dirscan() pass up a PATHNAME. */
path_parse( file, &f );
f.f_dir.len = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -