2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-03 09:02:11 +00:00

Merge with Perforce 2.4 state

[SVN r13111]
This commit is contained in:
Dave Abrahams
2002-03-06 14:13:29 +00:00
parent 423e65af29
commit 02b986f45b
35 changed files with 2316 additions and 1551 deletions

View File

@@ -248,7 +248,8 @@ jam [ -a ] [ -n ] [ -v ]
with two exceptions: double quotes (") can enclose whitespace
to embed it into a token, and everything between the matching
curly braces ({}) in the definition of a rule action is treated
as a single string. A backslash (\) can escape a double quote.
as a single string. A backslash (\) can escape a double quote,
or any single whitespace character.
<P>
@@ -299,6 +300,17 @@ jam [ -a ] [ -n ] [ -v ]
<P>
Rules can return values, which can be expanded into a list with
"[ <i>rule</i> <i>args</i> ... ]". A rule's value is the value
of its last statement, though only the following statements
have values: 'if' (value of the leg chosen), 'switch' (value of the case
chosen), set (value of the resulting variable), and 'return' (value
of its arguments). Note that 'return' doesn't actually cause a
return, i.e., is a no-op unless it is the last statement
of the last block executed within rule body.
<P>
The <b>jam</b> statements for defining and invoking rules are
as follows:
@@ -325,15 +337,33 @@ jam [ -a ] [ -n ] [ -v ]
<DD> Invoke a rule.
<P> <DT> <CODE>
on <I>target</I> <I>rulename field1</I> : <I>field2</I> : <I>...</I>
: <I>fieldN</I> ;
</CODE>
<DD> Invoke a rule under the influence of <I>target</I>'s specific
variables..
<P> <DT> <CODE>
[ <I>rulename field1</I> : <I>field2</I> : <I>...</I>
: <I>fieldN</I> ] <br>
[ on <I>target</I> <I>rulename field1</I> : <I>field2</I> : <I>...</I>
: <I>fieldN</I> ] <br>
</CODE>
<DD> Used as an argument, expands to the return value of the rule invoked.
</DL></TABLE>
<P>
A rule is invoked with values in <I>field1</I> through
<I>fieldN</I>. They may be referenced in the procedure's
<I>statements</I> as $(1) through $(<I>N</I>), and the first
two only may be referenced in the action's <I>commands</I> as
$(1) and $(2). $(&lt;) and $(&gt;) are synonymous with $(1)
<I>statements</I> as $(1) through $(<I>N</I>) (9 max), and the
first two only may be referenced in the action's <I>commands</I>
as $(1) and $(2). $(&lt;) and $(&gt;) are synonymous with $(1)
and $(2).
<P>
@@ -396,7 +426,7 @@ jam [ -a ] [ -n ] [ -v ]
<DT> <P> <H3> Built-in Rules </H3> <DD>
<P>
<B>Jam</b> has ten built-in rules, all of which are pure
<B>Jam</b> has eleven built-in rules, all of which are pure
procedure rules without updating actions. They are in
three groups: the first builds the dependency graph;
the second modifies it; and the third are just utility
@@ -421,8 +451,8 @@ jam [ -a ] [ -n ] [ -v ]
INCLUDES <I>targets1</I> : <I>targets2</I> ;
</CODE>
<DD> Builds a sibling dependency: makes each of <I>targets2</I>
depend on anything upon which each of <I>targets1</I> depends.
<DD> Builds a sibling dependency: makes any target that depends
on any of <I>targets1</I> also depend on each of <I>targets2</I>.
This reflects the dependencies that arise when one source file
includes another: the object built from the source file depends
both on the original and included source file, but the two
@@ -435,7 +465,7 @@ jam [ -a ] [ -n ] [ -v ]
<P>
"foo.h" depends on "foo.c" and "foo.h" in this example.
"foo.o" depends on "foo.c" and "foo.h" in this example.
</DL></TABLE>
@@ -550,6 +580,31 @@ jam [ -a ] [ -n ] [ -v ]
<DD> Blurts out the message <i>args</I> to stdout and then exits
with a failure status.
<P>
"Echo", "echo", "Exit", and "exit" are accepted as aliases for ECHO
and EXIT, since it is hard to tell that these are built-in
rules and not part of the language, like "include".
</DL></TABLE>
<P>
The GLOB rule does filename globbing.
<P><TABLE WIDTH=75% ALIGN=CENTER><TR><TD><DL>
<P><DT><CODE>
GLOB <i>directories</I> : <I>patterns</I>
</CODE>
<DD> Using the same wildcards as for the patterns in the
<A HREF="#switch">switch</A> statement).
It is invoked by being used as an argument to a rule invocation
inside of `[ ]`. For example: "FILES = [ GLOB dir1 dir2 : *.c *.h ]"
will set the value of A to the list of C source and header files in
dir1 or dir2.
</DL></TABLE>
<DT> <P> <H3> Flow-of-Control </H3> <DD>
@@ -570,7 +625,9 @@ jam [ -a ] [ -n ] [ -v ]
<i>list</i>, setting the variable <i>var</i> to the element
value.
<A name=if>
<P><DT><CODE>
</A>
if <I>cond</I> { <I>statements</I> }
<BR> [ else <I>statements</I> ]
@@ -654,7 +711,21 @@ jam [ -a ] [ -n ] [ -v ]
<P><DT> <CODE>
return <I>values</I> ;
</CODE>
<P><DD> Within a rule body, the return statement sets the return
value for an invocation of the rule. It does <i>not</i> cause the
rule to return; a rule's value is actually the value of the
last statement executed, so a return should be the
last statement executed before the rule "naturally" returns.
<P><DT> <CODE>
<A NAME="switch">
switch <I>value</I>
</A>
<BR> {
<BR> case <I>pattern1</I> : <I>statements</I> ;
<BR> case <I>pattern2</I> : <I>statements</I> ;
@@ -677,9 +748,22 @@ jam [ -a ] [ -n ] [ -v ]
<TD> match zero or more characters </TD>
<TR><TD><CODE> [<i>chars</i>] </CODE></TD>
<TD> match any single character in <i>chars</i> </TD>
<TR><TD><CODE> [^<i>chars</i>] </CODE></TD>
<TD> match any single character not in <i>chars</i> </TD>
<TR><TD><CODE> \<i>x</i> </CODE></TD>
<TD> match <i>x</i> (escapes the other wildcards)</i> </TD>
</TABLE>
<P><DT> <CODE>
while <I>cond</I> { <I>statements</I> }
</CODE>
<P><DD> Repeatedly execute <I>statements</I> while <I>cond</I>
remains true upon entry. (See the description of <I>cond</I>
expression syntax under <a href="#if">if</a>, above).
</DL></TABLE>
<DT> <P> <H3> Variables </H3> <DD>
@@ -876,6 +960,13 @@ jam [ -a ] [ -n ] [ -v ]
<TD>Prepend <I>root</I> to the whole file name, if not
already rooted.
<TR><TD><CODE> :E=<I>value</I> </CODE>
<TD>Assign <I>value</I> to the variable if it is unset.
<TR><TD><CODE> :J=<I>joinval</I> </CODE>
<TD>Concatentate list elements into single
element, separated by <I>joinval</I>.
</TABLE>
<P>
@@ -1188,13 +1279,19 @@ jam [ -a ] [ -n ] [ -v ]
<P>
Copyright 1997, 2000 Perforce Software, Inc.
Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
<BR>
Comments to <A HREF="mailto:info@perforce.com">info@perforce.com</A>
<BR>
Last updated: December 31, 2000
<BR>
<<<<<<< variant A
$Id$
>>>>>>> variant B
$Id$
####### Ancestor
$Id$
======= end
</BODY>
</HTML>

View File

@@ -79,15 +79,31 @@ Jambase Rules
Removes existing <I>targets</I> when <I>clean</I> is built.
clean is not a dependency of all, and must be built
explicitly for targets to be removed.
</BLOCKQUOTE>
<B>FDefines</B> <I>defines</I> ; <BLOCKQUOTE>
Expands a list of definitions into a list of compiler
(or preprocessor) switches (such as
-D<I>symbol</I>=<I>val</I> on Unix)
to pass the definitions.
</BLOCKQUOTE>
<B>File</B> <I>target</I> : <I>source</I> ;
<BLOCKQUOTE>
Copies <I>source</I> into <I>target.</I>
</BLOCKQUOTE>
<B>FIncludes</B> <I>dirs</I> ; <BLOCKQUOTE>
Expands a list of directories into a list of compiler
(or preprocessor) switches (such as -I<I>dir</I> on Unix)
to add the directories to the header inclusion search path.
</BLOCKQUOTE>
<B>Fortran</B> <I>obj.o</I> : <I>source.f</I> ;
<BLOCKQUOTE>
Compile the Fortran source file <I>source.f.</I> Called
by the Object rule.
</BLOCKQUOTE>
<B>FQuote</B> <I>files</I> ; <BLOCKQUOTE>
Returns each of <I>files</I> suitably quoted so as to hide shell
metacharacters (such as whitespace and filename matching wildcards)
from the shell.
</BLOCKQUOTE>
<P>
<B>GenFile</B> <I>target</I> : <I>image</I> <I>sources</I> ;
@@ -221,6 +237,10 @@ Jambase Rules
value of $(CCFLAGS) or $(C++FLAGS) when compiling <I>source.</I>
Any file suffix on <I>source</I> is ignored.
</BLOCKQUOTE>
<B>ObjectDefines</B> <I>object</I> : <I>defines</I> ; <BLOCKQUOTE>
Adds preprocessor symbol definitions to the (gristed)
target-specific $(CCDEFS) for the <I>object</i>.
</BLOCKQUOTE>
<B>ObjectHdrs</B> <I>source</I> : <I>dirs</I> ; <BLOCKQUOTE>
Add <I>dirs</I> to the source-specific value of
$(HDRS) when scanning and compiling <I>source.</I>
@@ -265,10 +285,11 @@ Jambase Rules
Adds <I>flags</I> to the compiler flags for source files
in SubDir's directory.
</BLOCKQUOTE>
<B>SubDirHdrs</B> <I>paths</I> ;
<B>SubDirHdrs</B> <I>d1 ... dn</I> ;
<BLOCKQUOTE>
Adds <I>paths</I> to the header search paths for source files
in SubDir's directory.
Adds the path <I>d1/.../dn/</I> to the header search paths for
source files in SubDir's directory. <I>d1</I> through <I>dn</I>
are elements of a directory path.
</BLOCKQUOTE>
<B>SubInclude</B> <I>VAR d1 ... dn</I> ;
<BLOCKQUOTE>
@@ -466,6 +487,17 @@ Jambase Variables
On Macintosh, the root of the Code Warrior Pro 5 directory.
</BLOCKQUOTE>
DEFINES
<BLOCKQUOTE>
Preprocessor symbol definitions for Cc and C++ rule targets.
The Cc and C++ rules set target-specific $(CCDEFS)
values on their targets, based on $(DEFINES). (The
"indirection" here is required to support compilers,
like VMS, with baroque command line syntax for
setting symbols).
</BLOCKQUOTE>
DOT
<BLOCKQUOTE>
@@ -866,16 +898,28 @@ Jambase Variables
The yacc(1) command flags.
</BLOCKQUOTE>
YACCGEN
<BLOCKQUOTE>
The suffix used on generated yacc(1) output.
</BLOCKQUOTE>
<P>
<HR>
<A HREF="#TOP">Back to top.</A>
<P>
Copyright 1997, 2000 Perforce Software, Inc.
Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
<BR>
Comments to <A HREF="mailto:info@perforce.com">info@perforce.com</A>
<BR>
Last updated: Dec 31, 2000
<BR>
<<<<<<< variant A
$Id$
>>>>>>> variant B
$Id$
####### Ancestor
$Id$
======= end
</BODY>
</HTML>

View File

@@ -116,7 +116,8 @@ Library libjam.a :
command.c compile.c $(code) expand.c glob.c
hash.c headers.c hdrmacro.c lists.c make.c make1.c newstr.c
option.c parse.c regexp.c rules.c scan.c search.c subst.c
timestamp.c variable.c modules.c strings.c filesys.c ;
timestamp.c variable.c modules.c strings.c filesys.c
builtins.c ;
if $(BINDIR) { InstallBin $(BINDIR) : jam ; }

View File

@@ -1445,6 +1445,12 @@ RmTemps Rule
<BR>
Last updated: Dec 31, 2000
<BR>
<<<<<<< variant A
$Id$
>>>>>>> variant B
$Id$
####### Ancestor
$Id$
======= end
</BODY>
</HTML>

View File

@@ -9,7 +9,7 @@ The complete and detailed list of changes is available at:
Jam/MR (aka "jam - make(1) redux")
/+\
+\ Copyright 1993, 2000 Christopher Seiwald.
+\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
\+/
This is Release 2.3 of Jam/MR, a make-like program.
@@ -53,14 +53,12 @@ FEATURES
INFORMATION GUIDE
Jam.html jam command usage
Jam.html jam and language reference.
Jambase.html Reference for the Jambase boilerplate file.
Jamfile.html Easy reading on creating a Jamfile and using jam.
Jamlang.html The Jam language description.
RELNOTES Release 2.3 release notes.
Porting Notes on porting jam to wildcat platforms.

View File

@@ -1,3 +1,4 @@
<<<<<<< variant A
Release notes for FTJam 2.3.5 (previous release was named "20010626")
0. Bugs fixed since 20010626:
@@ -26,6 +27,159 @@ Release notes for FTJam 2.3.5 (previous release was named "20010626")
============================================================================
>>>>>>> variant B
Release notes for Jam/MR [UNRELEASED]
(aka Jam - make(1) redux)
*** Note: These Release notes represent work in progress,
*** not a completed release!
1. Release info: (TENTATIVE)
Jam/MR 2.4 (TENTATIVE, IN PROGRESS!)
Month, dd, 2002
VERSION 2.4 (TENTATIVE, IN PROGRESS!)
2. Compatibility
Jam 2.4 is upward compatible with Jam 2.3
The Jam 2.4 language is a superset of the 2.3 language;
Jamfiles, Jambase, and other rulesets used in 2.3 can be used
with the 2.4 language support.
3. Changes since 2.3.
3.1. Changes to Jam Language
The mechanism for calling rules that return values - "[ rule
args ...]", (and 'return' in the rule body), is now a
documented part of the language.
Add "on <target> <rulename> <field1> ..." syntax, to invoke a
rule under the influence of a target's specific variables.
Add "[ on targ rule ... ]" to call a rule returning a value,
under the influence of a target's specific variables.
New 'Glob' builtin that returns a list of files in a list of
directories, given a list of patterns.
New 'while expr { block }' construct.
New :E=value modifier provides default value if variable unset.
New :J=joinval modifier concatentates list elements into single
element, separated by joinval.
\ can now be used to escape a space (or any single whitespace
character), so that you don't have to resort to quotes.
'Echo' and 'Exit' now have aliases 'echo' and 'exit', since it
is really hard to tell that these are built-in rules and not
part of the language, like 'include'. Real rules continue to
start with a capital.
3.2. Jambase Changes
Support for YACCGEN, the suffix used on generated yacc output.
Fix ups to have jam and p4 build with borland C 5.5,
and minor win98 jam support for jam clean
SubDirHdrs now takes directory names in the same format as
SubInclude : one directory element per word.
More portable support for specifying includes and #defines:
New ASHDRS, CCHDRS, CCDEFS, DEFINES, ObjectDefines, FQuote,
FIncludes, FDefines. Ordering of cc and c++ flags grossly
rearranged.
Jambase has been compacted by applying the new E: and J:
expansion modifiers.
3.3. Jam internal code changes
Optimize rule compilation, with right-recursion instead of left.
Split jam's built-in rules out to builtins.c from compile.c,
so that compile.c only deals with the language.
Split jam's pathsys.h from filesys.h, since they are really
two different pieces.
evaluate_if(), which evaluated the condition tree for 'if' and
returned an int, has been replaced with compile_eval(), which does
essentially the same but returns a LIST.
4. Fixed bugs
Defining a rule within another rule, and invoking the enclosing
rule more than once, would result in giving the first rule a
null definition. Fixed.
$(d:P) now works properly on the mac, climbing up directories.
Thanks to Miklos Fazekas <boga@mac.com>.
No longer (sometimes) treat \ as a directory separator on
UNIX. It isn't supposed to be, but was due to bungled ifdefs.
Applying just :U or :D (or :E, :J) mods no longer causes the
variable value to be treated as a filename (parsed and rebuilt
using the OS specific pathsys routines). Previously, if _any_
mods were present then the value was parsed and rebuilt as if
a filename, and that could in certain cases munge the value.
Only the file modifiers (:GDBSM) treat the value as a
filename.
Four rules makeCommon, makeGrist, makeString, makeSubDir from
jam 2.2 missing in 2.3 have been readded, with apologies to
dtb@cisco.com.
Return status more likely to be correct when using -d0, now that
targets are could as being built even with no debugging output.
Thanks to Miklos Fazekas <boga@mac.com>.
5. Porting
[MACINTOSH] Paths are now downshifted (interally) so as to
handle its case insensitivity. Thanks to Miklos Fazekas
<boga@mac.com>.
[NT] MS changed the macro for the IA64 Windows NT 64bit
compiler.
[CYGWIN] Cygwin jam porting: dance around bison and yyacc.
Use bison's -y flag to use yacc's output file naming
conventions, and don't use yyacc on systems whose SUFEXE is
set.
[VMS] The Jambase itself was not formatting the CCHDRS and
CCDEFS properly: on VMS they can't be appended to, because
multiple /define or /include directives don't work. Instead
now CCHDRS and CCDEFS is reformatted from HDRS and DEFINES
anytime those latter two change. This requires the recent
change to jam to allow access to target-specific variables
when setting other variables.
[VMS] Remove exception call when file_dirscan() can't, for
some reason, scan a directory. Use a better set of #ifdefs to
determine if we're on a vax, rather than relying on the C
compiler being a specific version: we're able to build with
the C++ compiler now.
[VMS] Port new jam to run with just cxx compiler.
(The C compiler being a extra-cost item).
[NT] Add entry for DevStudio when the settings are already in the
system environment.
===============================================================================
===============================================================================
####### Ancestor
======= end
Release notes for Jam/MR 2.3
(aka Jam - make(1) redux)
@@ -233,7 +387,7 @@ Release Notes for Jam 2.2
Documentation rewritten; HTML versions supplied.
3.1 Changes to Jam Language (See Jamlang.html)
3.1 Changes to Jam Language
Rules may now have more fields than just $(<) and $(>).

594
src/engine/builtins.c Normal file
View File

@@ -0,0 +1,594 @@
/*
* 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 "frames.h"
# include "hash.h"
# include "strings.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
*
* 01/10/01 (seiwald) - split from compile.c
*/
/*
* compile_builtin() - define builtin rules
*/
# define P0 (PARSE *)0
# define C0 (char *)0
int glob( char *s, char *c );
static 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, T_DEPS_DEPENDS, 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 ) ) );
duplicate_rule( "Glob" ,
bind_builtin( "GLOB" ,
builtin_glob, 0, 0 ) );
duplicate_rule( "Includes" ,
bind_builtin( "INCLUDES" ,
builtin_depends, T_DEPS_INCLUDES, 0 ) );
duplicate_rule( "Leaves" ,
bind_builtin( "LEAVES" ,
builtin_flags, T_FLAG_LEAVES, 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 ) );
duplicate_rule( "HdrMacro" ,
bind_builtin( "HDRMACRO" ,
builtin_hdrmacro, 0, 0 ) );
/* FAIL_EXPECTED is an experimental built-in that 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.. */
/* */
/* Beware that this rule might disappear or be renamed in the future.. */
/* contact david.turner@freetype.org for more details.. */
bind_builtin( "FAIL_EXPECTED" ,
builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
{
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[] = { "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[] = { 0 };
bind_builtin( "BACKTRACE" ,
builtin_backtrace, 0, args );
}
}
/*
* 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 );
int which = parse->num;
LIST *l;
for( l = targets; l; l = list_next( l ) )
{
TARGET *t = bindtarget( l->string );
t->deps[ which ] = targetlist( t->deps[ which ], sources );
}
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;
} ;
static void
builtin_glob_back(
void *closure,
char *file,
int status,
time_t time )
{
struct globbing *globbing = (struct globbing *)closure;
LIST *l;
for( l = globbing->patterns; l; l = l->next )
if( !glob( l->string, file ) )
{
globbing->results = list_new( globbing->results, newstr( file ) );
break;
}
}
LIST *
builtin_glob(
PARSE *parse,
FRAME *frame )
{
LIST *l = lol_get( frame->args, 0 );
LIST *r = lol_get( frame->args, 1 );
struct globbing globbing;
globbing.results = L0;
globbing.patterns = r;
for( ; l; l = list_next( l ) )
file_dirscan( l->string, builtin_glob_back, &globbing );
return globbing.results;
}
LIST *
builtin_hdrmacro(
PARSE *parse,
FRAME *frame )
{
LIST* l = lol_get( frame->args, 0 );
for ( ; l; l = list_next(l) )
{
TARGET* t = bindtarget( l->string );
/* scan file for header filename macro definitions */
if ( DEBUG_HEADER )
printf( "scanning '%s' for header file macro definitions\n",
l->string );
macro_headers( t );
}
return L0;
}
/* builtin_rulenames() - RULENAMES ( MODULE ? )
*
* Returns a list of the non-local rule names in the given MODULE. If
* MODULE is not supplied, returns the list of rule names in the
* global module.
*/
/* helper function for builtin_rulenames(), below */
static void add_rule_name( void* r_, void* result_ )
{
RULE* r = r_;
LIST** result = result_;
if ( r->exported )
*result = list_new( *result, copystr( r->name ) );
}
LIST *
builtin_rulenames(
PARSE *parse,
FRAME *frame )
{
LIST *arg0 = lol_get( frame->args, 0 );
LIST *result = L0;
module* source_module = bindmodule( arg0 ? arg0->string : 0 );
hashenumerate( source_module->rules, add_rule_name, &result );
return result;
}
static void unknown_rule( FRAME *frame, char* key, char *module_name, char *rule_name )
{
backtrace_line( frame->prev );
printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
backtrace( frame->prev );
exit(1);
}
/*
* builtin_import() - IMPORT ( SOURCE_MODULE ? : SOURCE_RULES * : TARGET_MODULE ? : TARGET_RULES * : LOCALIZE ? )
*
* The IMPORT rule imports rules from the SOURCE_MODULE into the
* TARGET_MODULE as local rules. If either SOURCE_MODULE or
* TARGET_MODULE is not supplied, it refers to the global
* module. SOURCE_RULES specifies which rules from the SOURCE_MODULE
* to import; TARGET_RULES specifies the names to give those rules in
* TARGET_MODULE. If SOURCE_RULES contains a name which doesn't
* correspond to a rule in SOURCE_MODULE, or if it contains a
* different number of items than TARGET_RULES, an error is issued.
* if LOCALIZE is specified, the rules will be executed in
* TARGET_MODULE, with corresponding access to its module local
* variables.
*/
LIST *
builtin_import(
PARSE *parse,
FRAME *frame )
{
LIST *source_module_list = lol_get( frame->args, 0 );
LIST *source_rules = lol_get( frame->args, 1 );
LIST *target_module_list = lol_get( frame->args, 2 );
LIST *target_rules = lol_get( frame->args, 3 );
LIST *localize = lol_get( frame->args, 4 );
module* target_module = bindmodule( target_module_list ? target_module_list->string : 0 );
module* source_module = bindmodule( source_module_list ? source_module_list->string : 0 );
LIST *source_name, *target_name;
for ( source_name = source_rules, target_name = target_rules;
source_name && target_name;
source_name = list_next( source_name )
, target_name = list_next( target_name ) )
{
RULE r_, *r = &r_, *imported;
r_.name = source_name->string;
if ( !hashcheck( source_module->rules, (HASHDATA**)&r ) )
unknown_rule( frame, "IMPORT", source_module->name, r_.name );
imported = import_rule( r, target_module, target_name->string );
if ( localize )
imported->module = target_module;
imported->exported = 0; /* this rule is really part of some other module; just refer to it here, but don't let it out */
}
if ( source_name || target_name )
{
backtrace_line( frame->prev );
printf( "import error: length of source and target rule name lists don't match" );
backtrace( frame->prev );
exit(1);
}
return L0;
}
/*
* builtin_export() - EXPORT ( MODULE ? : RULES * )
*
* The EXPORT rule marks RULES from the SOURCE_MODULE as non-local
* (and thus exportable). If an element of RULES does not name a rule
* in MODULE, an error is issued.
*/
LIST *
builtin_export(
PARSE *parse,
FRAME *frame )
{
LIST *module_list = lol_get( frame->args, 0 );
LIST *rules = lol_get( frame->args, 1 );
module* m = bindmodule( module_list ? module_list->string : 0 );
for ( ; rules; rules = list_next( rules ) )
{
RULE r_, *r = &r_;
r_.name = rules->string;
if ( !hashcheck( m->rules, (HASHDATA**)&r ) )
unknown_rule( frame, "EXPORT", m->name, r_.name );
r->exported = 1;
}
return L0;
}
/* Retrieve the file and line number that should be indicated for a
* given procedure in debug output or an error backtrace
*/
static void get_source_line( PARSE* procedure, char** file, int* line )
{
if ( procedure )
{
char* f = procedure->file;
int l = procedure->line;
if ( !strcmp( f, "+" ) )
{
f = "jambase.c";
l += 3;
}
*file = f;
*line = l;
}
else
{
*file = "(builtin)";
*line = -1;
}
}
void print_source_line( PARSE* p )
{
char* file;
int line;
get_source_line( p, &file, &line );
if ( line < 0 )
printf( "(builtin):" );
else
printf( "%s:%d:", file, line);
}
/* Print a single line of error backtrace for the given frame */
void backtrace_line( FRAME *frame )
{
print_source_line( frame->procedure );
printf( " in %s\n", frame->rulename );
}
/* Print the entire backtrace from the given frame to the Jambase
* which invoked it.
*/
void backtrace( FRAME *frame )
{
while ( frame = frame->prev )
{
backtrace_line( frame );
}
}
/* A Jam version of the backtrace function, taking no arguments and
* returning a list of quadruples: FILENAME LINE MODULE. RULENAME
* describing each frame. Note that the module-name is always
* followed by a period.
*/
LIST *builtin_backtrace( PARSE *parse, FRAME *frame )
{
LIST* result = L0;
while ( frame = frame->prev )
{
char* file;
int line;
char buf[32];
get_source_line( frame->procedure, &file, &line );
sprintf( buf, "%d", line );
result = list_new( result, newstr( file ) );
result = list_new( result, newstr( buf ) );
result = list_new( result, newstr( frame->module->name ) );
result = list_new( result, newstr( frame->rulename ) );
}
return result;
}
/*
* builtin_caller_module() - CALLER_MODULE ( levels ? )
*
* If levels is not supplied, returns the name of the module of the rule which
* called the one calling this one. If levels is supplied, it is interpreted as
* an integer specifying a number of additional levels of call stack to traverse
* in order to locate the module in question. If no such module exists,
* returns the empty list. Also returns the empty list when the module in
* question is the global module. This rule is needed for implementing module
* import behavior.
*/
LIST *builtin_caller_module( PARSE *parse, FRAME *frame )
{
LIST* levels_arg = lol_get( frame->args, 0 );
int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
int i;
for (i = 0; i < levels + 2 && frame->prev; ++i)
frame = frame->prev;
if ( frame->module == root_module() )
{
return L0;
}
else
{
LIST* result;
string name;
string_copy( &name, frame->module->name );
string_pop_back( &name );
result = list_new( L0, newstr(name.value) );
string_free( &name );
return result;
}
}
static void lol_build( LOL* lol, char** elements )
{
LIST* l = L0;
lol_init( lol );
while ( elements && *elements )
{
if ( !strcmp( *elements, ":" ) )
{
lol_add( lol, l );
l = L0 ;
}
else
{
l = list_new( l, newstr( *elements ) );
}
++elements;
}
if ( l != L0 )
lol_add( lol, l );
}

31
src/engine/builtins.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
#ifndef JAM_BUILTINS_H
# define JAM_BUILTINS_H
# include "frames.h"
/*
* builtins.h - compile parsed jam statements
*/
void load_builtins();
LIST *builtin_depends( PARSE *parse, FRAME *args );
LIST *builtin_echo( PARSE *parse, FRAME *args );
LIST *builtin_exit( PARSE *parse, FRAME *args );
LIST *builtin_flags( PARSE *parse, FRAME *args );
LIST *builtin_glob( PARSE *parse, FRAME *args );
LIST *builtin_subst( PARSE *parse, FRAME *args );
LIST *builtin_hdrmacro( PARSE *parse, FRAME *args );
LIST *builtin_rulenames( PARSE *parse, FRAME *args );
LIST *builtin_import( PARSE *parse, FRAME *args );
LIST *builtin_export( PARSE *parse, FRAME *args );
LIST *builtin_caller_module( PARSE *parse, FRAME *args );
LIST *builtin_backtrace( PARSE *parse, FRAME *args );
#endif

View File

@@ -9,7 +9,7 @@ SOURCES = \
hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c \
newstr.c option.c parse.c pathunix.c pathvms.c regexp.c \
rules.c scan.c search.c subst.c timestamp.c variable.c modules.c \
strings.c filesys.c
strings.c filesys.c builtins.c
# the bootstrap "jam0" build tool
#

View File

@@ -44,6 +44,7 @@
* compile_list() - expand and return a list
* compile_local() - declare (and set) local variables
* compile_null() - do nothing -- a stub for parsing
* compile_on() - run rule under influence of on-target variables
* compile_rule() - compile a single user defined rule
* compile_rules() - compile a chain of rules
* compile_set() - compile the "set variable" statement
@@ -51,12 +52,10 @@
* compile_setexec() - support for `actions` - save execution string
* compile_settings() - compile the "on =" (set variable on exec) statement
* compile_switch() - compile 'switch' rule
*
* Internal routines:
*
* debug_compile() - printf with indent to show rule expansion.
*
* evaluate_if() - evaluate if to determine which leg to compile
* evaluate_rule() - execute a rule invocation
*
* builtin_depends() - DEPENDS/INCLUDES rule
@@ -82,32 +81,14 @@
* New compile_append() and compile_list() in
* support of building lists here, rather than
* in jamgram.yy.
* 01/10/00 (seiwald) - built-ins split out to builtin.c.
*/
static void debug_compile( int which, char *s, FRAME* frame );
static int evaluate_if( PARSE *parse, FRAME *frame );
static void backtrace_line( FRAME* frame );
static void backtrace( FRAME* frame );
static void get_source_line( PARSE*, char** file, int* line );
static void print_source_line( PARSE* );
static LIST *builtin_depends( PARSE *parse, FRAME *frame );
static LIST *builtin_echo( PARSE *parse, FRAME *frame );
static LIST *builtin_exit( PARSE *parse, FRAME *frame );
static LIST *builtin_flags( PARSE *parse, FRAME *frame );
static LIST *builtin_hdrmacro( PARSE *parse, FRAME *frame );
static LIST *builtin_rulenames( PARSE *parse, FRAME *frame );
static LIST *builtin_import( PARSE *parse, FRAME *frame );
static LIST *builtin_export( PARSE *parse, FRAME *frame );
static LIST *builtin_caller_module( PARSE *parse, FRAME *frame );
static LIST *builtin_backtrace( PARSE *parse, FRAME *frame );
LIST *builtin_subst( PARSE *parse, FRAME *frame );
int glob( char *s, char *c );
/* Internal functions from builtins.c */
void backtrace_line( FRAME *frame );
void print_source_line( PARSE* p );
void frame_init( FRAME* frame )
@@ -124,127 +105,6 @@ void frame_free( FRAME* frame )
lol_free( frame->args );
}
/*
* compile_builtin() - define builtin rules
*/
# define P0 (PARSE *)0
# define C0 (char *)0
static void lol_build( LOL* lol, char** elements )
{
LIST* l = L0;
lol_init( lol );
while ( elements && *elements )
{
if ( !strcmp( *elements, ":" ) )
{
lol_add( lol, l );
l = L0 ;
}
else
{
l = list_new( l, newstr( *elements ) );
}
++elements;
}
if ( l != L0 )
lol_add( lol, l );
}
static 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 );
}
static RULE* duplicate_rule( char* name, RULE* other )
{
return import_rule( other, root_module(), name );
}
void
compile_builtins()
{
duplicate_rule( "Always", bind_builtin( "ALWAYS", builtin_flags, T_FLAG_TOUCHED, 0 ) );
duplicate_rule( "Depends", bind_builtin( "DEPENDS", builtin_depends, T_DEPS_DEPENDS, 0 ) );
duplicate_rule( "Echo", bind_builtin( "ECHO", builtin_echo, 0, 0 ) );
duplicate_rule( "Exit", bind_builtin( "EXIT", builtin_exit, 0, 0 ) );
duplicate_rule( "Includes", bind_builtin( "INCLUDES", builtin_depends, T_DEPS_INCLUDES, 0 ) );
duplicate_rule( "HdrMacro", bind_builtin( "HDRMACRO", builtin_hdrmacro, 0, 0 ) );
duplicate_rule( "Leaves", bind_builtin( "LEAVES", builtin_flags, T_FLAG_LEAVES, 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 ) );
/* FAIL_EXPECTED is an experimental built-in that 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.. */
/* */
/* Beware that this rule might disappear or be renamed in the future.. */
/* contact david.turner@freetype.org for more details.. */
bind_builtin( "FAIL_EXPECTED", builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
{
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[] = {
"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[] = { 0 };
bind_builtin( "BACKTRACE", builtin_backtrace, 0, args );
}
}
/*
* compile_append() - append list results of two statements
*
@@ -264,6 +124,124 @@ compile_append(
parse_evaluate( parse->right, frame ) );
}
/*
* compile_eval() - evaluate if to determine which leg to compile
*
* Returns:
* list if expression true - compile 'then' clause
* L0 if expression false - compile 'else' clause
*/
static int
lcmp( LIST *t, LIST *s )
{
int status = 0;
while( !status && ( t || s ) )
{
char *st = t ? t->string : "";
char *ss = s ? s->string : "";
status = strcmp( st, ss );
t = t ? list_next( t ) : t;
s = s ? list_next( s ) : s;
}
return status;
}
LIST *
compile_eval(
PARSE *parse,
FRAME *frame )
{
LIST *ll = parse_evaluate( parse->left, frame );
LIST *lr = parse->right ? parse_evaluate( parse->right, frame ) : 0;
LIST *s, *t;
int status = 0;
switch( parse->num )
{
case EXPR_EXISTS:
if( ll && ll->string[0] ) status = 1;
break;
case EXPR_NOT:
if( !ll ) status = 1;
break;
case EXPR_AND:
if ( ll )
{
if ( parse->third ) lr = parse_evaluate( parse->third, frame );
if ( lr ) status = 1;
}
break;
case EXPR_OR:
if ( ll )
{
status = 1;
}
else
{
if ( parse->third ) lr = parse_evaluate( parse->third, frame );
if ( lr ) status = 1;
}
break;
case EXPR_IN:
/* "a in b": make sure each of */
/* ll is equal to something in lr. */
for( t = ll; t; t = list_next( t ) )
{
for( s = lr; s; s = list_next( s ) )
if( !strcmp( t->string, s->string ) )
break;
if( !s ) break;
}
/* No more ll? Success */
if( !t ) status = 1;
break;
case EXPR_EQUALS: if( lcmp( ll, lr ) == 0 ) status = 1; break;
case EXPR_NOTEQ: if( lcmp( ll, lr ) != 0 ) status = 1; break;
case EXPR_LESS: if( lcmp( ll, lr ) < 0 ) status = 1; break;
case EXPR_LESSEQ: if( lcmp( ll, lr ) <= 0 ) status = 1; break;
case EXPR_MORE: if( lcmp( ll, lr ) > 0 ) status = 1; break;
case EXPR_MOREEQ: if( lcmp( ll, lr ) >= 0 ) status = 1; break;
}
if( DEBUG_IF )
{
debug_compile( 0, "if", frame );
list_print( ll );
printf( "(%d) ", status );
list_print( lr );
printf( "\n" );
}
/* Find something to return. */
/* In odd circumstances (like "" = "") */
/* we'll have to return a new string. */
if( !status ) t = 0;
else if( ll ) t = ll, ll = 0;
else if( lr ) t = lr, lr = 0;
else t = list_new( L0, newstr( "1" ) );
if( ll ) list_free( ll );
if( lr ) list_free( lr );
return t;
}
/*
* compile_foreach() - compile the "for x in y" statement
*
@@ -322,8 +300,10 @@ compile_if(
PARSE *p,
FRAME *frame )
{
if( evaluate_if( p->left, frame ) )
LIST *l = parse_evaluate( p->left, frame );
if( l )
{
list_free( l );
return parse_evaluate( p->right, frame );
}
else
@@ -337,127 +317,17 @@ compile_while(
PARSE *p,
FRAME *frame )
{
while ( evaluate_if( p->left, frame ) )
LIST *r = 0;
LIST *l;
while ( l = parse_evaluate( p->left, frame ) )
{
list_free( parse_evaluate( p->right, frame ) );
list_free( l );
if( r ) list_free( r );
r = parse_evaluate( p->right, frame );
}
return L0;
return r;
}
/*
* evaluate_if() - evaluate if to determine which leg to compile
*
* Returns:
* !0 if expression true - compile 'then' clause
* 0 if expression false - compile 'else' clause
*/
static int
evaluate_if(
PARSE *parse,
FRAME *frame )
{
int status;
if( parse->num <= COND_OR )
{
/* Handle one of the logical operators */
switch( parse->num )
{
case COND_NOT:
status = !evaluate_if( parse->left, frame );
break;
case COND_AND:
status = evaluate_if( parse->left, frame ) &&
evaluate_if( parse->right, frame );
break;
case COND_OR:
status = evaluate_if( parse->left, frame ) ||
evaluate_if( parse->right, frame );
break;
default:
status = 0; /* can't happen */
}
}
else
{
/* Handle one of the comparison operators */
/* Expand targets and sources */
LIST *nt = parse_evaluate( parse->left, frame );
LIST *ns = parse_evaluate( parse->right, frame );
/* "a in b" make sure each of a is equal to something in b. */
/* Otherwise, step through pairwise comparison. */
if( parse->num == COND_IN )
{
LIST *s, *t;
/* Try each t until failure. */
for( status = 1, t = nt; status && t; t = list_next( t ) )
{
int stat1;
/* Try each s until success */
for( stat1 = 0, s = ns; !stat1 && s; s = list_next( s ) )
stat1 = !strcmp( t->string, s->string );
status = stat1;
}
}
else
{
LIST *s = ns, *t = nt;
status = 0;
while( !status && ( t || s ) )
{
char *st = t ? t->string : "";
char *ss = s ? s->string : "";
status = strcmp( st, ss );
t = t ? list_next( t ) : t;
s = s ? list_next( s ) : s;
}
}
switch( parse->num )
{
case COND_EXISTS: status = status > 0 ; break;
case COND_EQUALS: status = !status; break;
case COND_NOTEQ: status = status != 0; break;
case COND_LESS: status = status < 0; break;
case COND_LESSEQ: status = status <= 0; break;
case COND_MORE: status = status > 0; break;
case COND_MOREEQ: status = status >= 0; break;
case COND_IN: /* status = status */ break;
}
if( DEBUG_IF )
{
debug_compile( 0, "if", frame);
list_print( nt );
printf( "(%d)", status );
list_print( ns );
printf( "\n" );
}
list_free( nt );
list_free( ns );
}
return status;
}
/*
* compile_include() - support for 'include' - call include() on file
@@ -614,6 +484,48 @@ compile_null(
return L0;
}
/*
* compile_on() - run rule under influence of on-target variables
*
* parse->left list of files to include (can only do 1)
* parse->right rule to run
*
* EXPERIMENTAL!
*/
LIST *
compile_on(
PARSE *parse,
FRAME *frame )
{
LIST *nt = parse_evaluate( parse->left, frame );
LIST *result = 0;
PARSE *p;
if( DEBUG_COMPILE )
{
debug_compile( 0, "on", frame );
list_print( nt );
printf( "\n" );
}
if( nt )
{
TARGET *t = bindtarget( nt->string );
pushsettings( t->settings );
result = parse_evaluate( parse->right, frame );
t->boundname = search( t->name, &t->time );
popsettings( t->settings );
}
list_free( nt );
return result;
}
/*
* compile_rule() - compile a single user defined rule
*
@@ -952,8 +864,8 @@ evaluate_rule(
/*
* compile_rules() - compile a chain of rules
*
* parse->left more compile_rules() by left-recursion
* parse->right single rule
* parse->left single rule
* parse->right more compile_rules() by right-recursion
*/
LIST *
@@ -962,9 +874,12 @@ compile_rules(
FRAME *frame )
{
/* Ignore result from first statement; return the 2nd. */
/* Optimize recursion on the right by looping. */
list_free( parse_evaluate( parse->left, frame ) );
return parse_evaluate( parse->right, frame );
do list_free( parse_evaluate( parse->left, frame ) );
while( (parse = parse->right)->func == compile_rules );
return parse_evaluate( parse, frame );
}
/*
@@ -1211,360 +1126,6 @@ compile_switch(
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.
*/
static LIST *
builtin_depends(
PARSE *parse,
FRAME *frame )
{
LIST *targets = lol_get( frame->args, 0 );
LIST *sources = lol_get( frame->args, 1 );
int which = parse->num;
LIST *l;
for( l = targets; l; l = list_next( l ) )
{
TARGET *t = bindtarget( l->string );
t->deps[ which ] = targetlist( t->deps[ which ], sources );
}
return L0;
}
/*
* builtin_echo() - ECHO rule
*
* The ECHO builtin rule echoes the targets to the user. No other
* actions are taken.
*/
static 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.
*/
static 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.
*/
static 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;
}
static LIST *
builtin_hdrmacro(
PARSE *parse,
FRAME *frame )
{
LIST* l = lol_get( frame->args, 0 );
for ( ; l; l = list_next(l) )
{
TARGET* t = bindtarget( l->string );
/* scan file for header filename macro definitions */
if ( DEBUG_HEADER )
printf( "scanning '%s' for header file macro definitions\n",
l->string );
macro_headers( t );
}
return L0;
}
/* builtin_rulenames() - RULENAMES ( MODULE ? )
*
* Returns a list of the non-local rule names in the given MODULE. If
* MODULE is not supplied, returns the list of rule names in the
* global module.
*/
/* helper function for builtin_rulenames(), below */
static void add_rule_name( void* r_, void* result_ )
{
RULE* r = r_;
LIST** result = result_;
if ( r->exported )
*result = list_new( *result, copystr( r->name ) );
}
static LIST *
builtin_rulenames(
PARSE *parse,
FRAME *frame )
{
LIST *arg0 = lol_get( frame->args, 0 );
LIST *result = L0;
module* source_module = bindmodule( arg0 ? arg0->string : 0 );
hashenumerate( source_module->rules, add_rule_name, &result );
return result;
}
static void unknown_rule( FRAME *frame, char* key, char *module_name, char *rule_name )
{
backtrace_line( frame->prev );
printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name );
backtrace( frame->prev );
exit(1);
}
/*
* builtin_import() - IMPORT ( SOURCE_MODULE ? : SOURCE_RULES * : TARGET_MODULE ? : TARGET_RULES * : LOCALIZE ? )
*
* The IMPORT rule imports rules from the SOURCE_MODULE into the
* TARGET_MODULE as local rules. If either SOURCE_MODULE or
* TARGET_MODULE is not supplied, it refers to the global
* module. SOURCE_RULES specifies which rules from the SOURCE_MODULE
* to import; TARGET_RULES specifies the names to give those rules in
* TARGET_MODULE. If SOURCE_RULES contains a name which doesn't
* correspond to a rule in SOURCE_MODULE, or if it contains a
* different number of items than TARGET_RULES, an error is issued.
* if LOCALIZE is specified, the rules will be executed in
* TARGET_MODULE, with corresponding access to its module local
* variables.
*/
static LIST *
builtin_import(
PARSE *parse,
FRAME *frame )
{
LIST *source_module_list = lol_get( frame->args, 0 );
LIST *source_rules = lol_get( frame->args, 1 );
LIST *target_module_list = lol_get( frame->args, 2 );
LIST *target_rules = lol_get( frame->args, 3 );
LIST *localize = lol_get( frame->args, 4 );
module* target_module = bindmodule( target_module_list ? target_module_list->string : 0 );
module* source_module = bindmodule( source_module_list ? source_module_list->string : 0 );
LIST *source_name, *target_name;
for ( source_name = source_rules, target_name = target_rules;
source_name && target_name;
source_name = list_next( source_name )
, target_name = list_next( target_name ) )
{
RULE r_, *r = &r_, *imported;
r_.name = source_name->string;
if ( !hashcheck( source_module->rules, (HASHDATA**)&r ) )
unknown_rule( frame, "IMPORT", source_module->name, r_.name );
imported = import_rule( r, target_module, target_name->string );
if ( localize )
imported->module = target_module;
imported->exported = 0; /* this rule is really part of some other module; just refer to it here, but don't let it out */
}
if ( source_name || target_name )
{
backtrace_line( frame->prev );
printf( "import error: length of source and target rule name lists don't match" );
backtrace( frame->prev );
exit(1);
}
return L0;
}
/*
* builtin_export() - EXPORT ( MODULE ? : RULES * )
*
* The EXPORT rule marks RULES from the SOURCE_MODULE as non-local
* (and thus exportable). If an element of RULES does not name a rule
* in MODULE, an error is issued.
*/
static LIST *
builtin_export(
PARSE *parse,
FRAME *frame )
{
LIST *module_list = lol_get( frame->args, 0 );
LIST *rules = lol_get( frame->args, 1 );
module* m = bindmodule( module_list ? module_list->string : 0 );
for ( ; rules; rules = list_next( rules ) )
{
RULE r_, *r = &r_;
r_.name = rules->string;
if ( !hashcheck( m->rules, (HASHDATA**)&r ) )
unknown_rule( frame, "EXPORT", m->name, r_.name );
r->exported = 1;
}
return L0;
}
/* Retrieve the file and line number that should be indicated for a
* given procedure in debug output or an error backtrace
*/
static void get_source_line( PARSE* procedure, char** file, int* line )
{
if ( procedure )
{
char* f = procedure->file;
int l = procedure->line;
if ( !strcmp( f, "+" ) )
{
f = "jambase.c";
l += 3;
}
*file = f;
*line = l;
}
else
{
*file = "(builtin)";
*line = -1;
}
}
static void print_source_line( PARSE* p )
{
char* file;
int line;
get_source_line( p, &file, &line );
if ( line < 0 )
printf( "(builtin):" );
else
printf( "%s:%d:", file, line);
}
/* Print a single line of error backtrace for the given frame */
static void backtrace_line( FRAME *frame )
{
print_source_line( frame->procedure );
printf( " in %s\n", frame->rulename );
}
/* Print the entire backtrace from the given frame to the Jambase
* which invoked it.
*/
static void backtrace( FRAME *frame )
{
while ( frame = frame->prev )
{
backtrace_line( frame );
}
}
/* A Jam version of the backtrace function, taking no arguments and
* returning a list of quadruples: FILENAME LINE MODULE. RULENAME
* describing each frame. Note that the module-name is always
* followed by a period.
*/
static LIST *builtin_backtrace( PARSE *parse, FRAME *frame )
{
LIST* result = L0;
while ( frame = frame->prev )
{
char* file;
int line;
char buf[32];
get_source_line( frame->procedure, &file, &line );
sprintf( buf, "%d", line );
result = list_new( result, newstr( file ) );
result = list_new( result, newstr( buf ) );
result = list_new( result, newstr( frame->module->name ) );
result = list_new( result, newstr( frame->rulename ) );
}
return result;
}
/*
* builtin_caller_module() - CALLER_MODULE ( levels ? )
*
* If levels is not supplied, returns the name of the module of the rule which
* called the one calling this one. If levels is supplied, it is interpreted as
* an integer specifying a number of additional levels of call stack to traverse
* in order to locate the module in question. If no such module exists,
* returns the empty list. Also returns the empty list when the module in
* question is the global module. This rule is needed for implementing module
* import behavior.
*/
static LIST *builtin_caller_module( PARSE *parse, FRAME *frame )
{
LIST* levels_arg = lol_get( frame->args, 0 );
int levels = levels_arg ? atoi( levels_arg->string ) : 0 ;
int i;
for (i = 0; i < levels + 2 && frame->prev; ++i)
frame = frame->prev;
if ( frame->module == root_module() )
{
return L0;
}
else
{
LIST* result;
string name;
string_copy( &name, frame->module->name );
string_pop_back( &name );
result = list_new( L0, newstr(name.value) );
string_free( &name );
return result;
}
}
/*
* debug_compile() - printf with indent to show rule expansion.
*/

View File

@@ -28,11 +28,13 @@ void compile_builtins();
LIST *compile_append( PARSE *parse, FRAME *frame );
LIST *compile_foreach( PARSE *parse, FRAME *frame );
LIST *compile_if( PARSE *parse, FRAME *frame );
LIST *compile_eval( PARSE *parse, FRAME *args );
LIST *compile_include( PARSE *parse, FRAME *frame );
LIST *compile_list( PARSE *parse, FRAME *frame );
LIST *compile_local( PARSE *parse, FRAME *frame );
LIST *compile_module( PARSE *parse, FRAME *frame );
LIST *compile_null( PARSE *parse, FRAME *frame );
LIST *compile_on( PARSE *parse, FRAME *frame );
LIST *compile_rule( PARSE *parse, FRAME *frame );
LIST *compile_rules( PARSE *parse, FRAME *frame );
LIST *compile_set( PARSE *parse, FRAME *frame );
@@ -66,18 +68,18 @@ void profile_dump();
/* Conditions for compile_if() */
# define COND_NOT 0 /* ! cond */
# define COND_AND 1 /* cond && cond */
# define COND_OR 2 /* cond || cond */
# define EXPR_NOT 0 /* ! cond */
# define EXPR_AND 1 /* cond && cond */
# define EXPR_OR 2 /* cond || cond */
# define COND_EXISTS 3 /* arg */
# define COND_EQUALS 4 /* arg = arg */
# define COND_NOTEQ 5 /* arg != arg */
# define COND_LESS 6 /* arg < arg */
# define COND_LESSEQ 7 /* arg <= arg */
# define COND_MORE 8 /* arg > arg */
# define COND_MOREEQ 9 /* arg >= arg */
# define COND_IN 10 /* arg in arg */
# define EXPR_EXISTS 3 /* arg */
# define EXPR_EQUALS 4 /* arg = arg */
# define EXPR_NOTEQ 5 /* arg != arg */
# define EXPR_LESS 6 /* arg < arg */
# define EXPR_LESSEQ 7 /* arg <= arg */
# define EXPR_MORE 8 /* arg > arg */
# define EXPR_MOREEQ 9 /* arg >= arg */
# define EXPR_IN 10 /* arg in arg */
#endif // COMPILE_DWA20011022_H

View File

@@ -1,53 +1,43 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
/* This file is ALSO:
* (C) Copyright David Abrahams 2001. Permission to copy, use,
* modify, sell and distribute this software is granted provided this
* copyright notice appears in all copies. This software is provided
* "as is" without express or implied warranty, and with no claim as
* to its suitability for any purpose.
*/
# include "jam.h"
# include "lists.h"
# include "variable.h"
# include "expand.h"
# include "filesys.h"
# include "pathsys.h"
# include "newstr.h"
# include "strings.h"
# include <assert.h>
# include <string.h>
/*
* expand.c - expand a buffer, given variable values
*
* External routines:
*
* var_expand() - variable-expand input string into list of strings
* var_expand() - variable-expand input string into list of strings
*
* Internal routines:
*
* var_edit() - copy input target name to output, performing : modifiers
* var_mods() - parse : modifiers into FILENAME structure
* var_edit_parse() - parse : modifiers into PATHNAME structure
* var_edit_file() - copy input target name to output, modifying filename
* var_edit_shift() - do upshift/downshift mods
*
* 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
* 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval
*/
typedef struct {
char downshift; /* :L -- downshift result */
char upshift; /* :U -- upshift result */
char parent; /* :P -- go to parent directory */
char to_slashes; /* :T -- convert "\" to "/" */
} VAR_ACTS ;
PATHNAME f; /* :GDBSMR -- pieces */
char parent; /* :P -- go to parent directory */
char filemods; /* one of the above applied */
char downshift; /* :L -- downshift result */
char upshift; /* :U -- upshift result */
char to_slashes; /* :T -- convert "\" to "/" */
PATHPART empty; /* :E -- default for empties */
PATHPART join; /* :J -- join list with char */
} VAR_EDITS ;
static void var_edit( char *in, char *mods, string *out );
static void var_mods( char *mods, FILENAME *f, VAR_ACTS *acts );
static int adjust_index( int index, int length );
static void var_edit_parse( char *mods, VAR_EDITS *edits );
static void var_edit_file( char *in, string *out, VAR_EDITS *edits );
static void var_edit_shift( string *out, VAR_EDITS *edits );
# define MAGIC_COLON '\001'
# define MAGIC_LEFT '\002'
@@ -73,9 +63,11 @@ var_expand(
LOL *lol,
int cancopyin )
{
string buf[1];
size_t prefix_length;
char *out;
char out_buf[ MAXSYM ];
string buf[1];
string out1; /* Temporary buffer */
size_t prefix_length;
char *out;
char *inp = in;
char *ov; /* for temp copy of variable in outbuf */
int depth;
@@ -99,10 +91,10 @@ var_expand(
}
}
/* See if we can use a simple copy of in to out. */
/* Just try simple copy of in to out. */
while ( in < end )
if ( *in++ == '$' && *in == '(' )
while( in < end )
if( *in++ == '$' && *in == '(' )
goto expand;
/* No variables expanded - just add copy of input string to list. */
@@ -111,47 +103,47 @@ var_expand(
/* item, we can use the copystr() to put it on the new list. */
/* Otherwise, we use the slower newstr(). */
if ( cancopyin )
{
if( cancopyin )
{
return list_new( l, copystr( inp ) );
}
}
else
{
LIST* r;
string_new( buf );
string_append_range( buf, inp, in );
r = list_new( l, newstr( buf->value ) );
string_free( buf );
return r;
}
{
LIST* r;
string_new( buf );
string_append_range( buf, inp, end );
r = list_new( l, newstr( buf->value) );
string_free( buf );
return r;
}
expand:
string_new( buf );
string_append_range( buf, inp, in - 1 ); /* copy in initial stuff */
string_new( buf );
string_append_range( buf, inp, in - 1); /* copy the part before '$'. */
/*
* Input so far (ignore blanks):
*
* stuff-in-outbuf $(variable) remainder
* ^ ^
* in end
* Output so far:
*
* stuff-in-outbuf $
* ^ ^
* out_buf out
*
*
* We just copied the $ of $(...), so back up one on the output.
* We now find the matching close paren, copying the variable and
* modifiers between the $( and ) temporarily into out_buf, so that
* we can replace :'s with MAGIC_COLON. This is necessary to avoid
* being confused by modifier values that are variables containing
* :'s. Ugly.
*/
* Input so far (ignore blanks):
*
* stuff-in-outbuf $(variable) remainder
* ^ ^
* in end
* Output so far:
*
* stuff-in-outbuf $
* ^ ^
* out_buf out
*
*
* We just copied the $ of $(...), so back up one on the output.
* We now find the matching close paren, copying the variable and
* modifiers between the $( and ) temporarily into out_buf, so that
* we can replace :'s with MAGIC_COLON. This is necessary to avoid
* being confused by modifier values that are variables containing
* :'s. Ugly.
*/
depth = 1;
inp = ++in; /* skip over the '(' */
inp = ++in; /* skip over the '(' */
while( in < end && depth )
{
@@ -219,103 +211,198 @@ var_expand(
for( vars = variables; vars; vars = list_next( vars ) )
{
LIST *value;
LIST *value, *evalue = 0;
char *colon;
char *bracket;
int i, sub1, sub2;
string variable;
char *varname;
string variable;
char *varname;
int sub1 = 0, sub2 = -1;
VAR_EDITS edits;
/* Look for a : modifier in the variable name */
/* Must copy into varname so we can modify it */
string_copy( &variable, vars->string );
varname = variable.value;
string_copy( &variable, vars->string );
varname = variable.value;
if( colon = strchr( varname, MAGIC_COLON ) )
{
string_truncate( &variable, colon - varname );
}
if( bracket = strchr( varname, MAGIC_LEFT ) )
{
char *dash = 0;
string_truncate( &variable, colon - varname );
var_edit_parse( colon + 1, &edits );
}
if( bracket[1] && ( dash = strchr( bracket + 2, '-' ) ) )
{
if( dash == bracket + 2 && *( bracket + 1 ) == '-')
--dash;
string_truncate( &variable, dash - varname );
sub1 = atoi( bracket + 1 );
sub2 = atoi( dash + 1 );
}
else
{
sub1 = sub2 = atoi( bracket + 1 );
}
/* Look for [x-y] subscripting */
/* sub1 and sub2 are x and y. */
if ( bracket = strchr( varname, MAGIC_LEFT ) )
{
/*
** Make all syntax errors in [] subscripting
** result in the same behavior: silenty return an empty
** expansion (by setting sub2 = 0). Brute force parsing;
** May get moved into yacc someday.
*/
char *s = bracket + 1;
string_truncate( &variable, bracket - varname );
}
else
{
sub1 = sub2 = 0; /* not needed */
}
do /* so we can use "break" */
{
/* Allow negative indexes. */
if (! isdigit( *s ) && ! ( *s == '-') )
{
sub2 = 0;
break;
}
sub1 = atoi(s);
/* Skip over the first symbol, which is either a digit or dash. */
s++;
while ( isdigit( *s ) ) s++;
if ( *s == MAGIC_RIGHT )
{
sub2 = sub1;
break;
}
if ( *s != '-')
{
sub2 = 0;
break;
}
s++;
if ( *s == MAGIC_RIGHT )
{
sub2 = -1;
break;
}
if (! isdigit( *s ) && ! ( *s == '-') )
{
sub2 = 0;
break;
}
/* First, compute the index of the last element. */
sub2 = atoi(s);
s++;
while ( isdigit( *s ) ) s++;
if ( *s != MAGIC_RIGHT)
sub2 = 0;
} while (0);
/*
** Anything but the end of the string, or the colon
** introducing a modifier is a syntax error.
*/
s++;
if (*s && *s != MAGIC_COLON)
sub2 = 0;
*bracket = '\0';
}
/* Get variable value, specially handling $(<), $(>), $(n) */
if( varname[0] == '<' && !varname[1] )
{
value = lol_get( lol, 0 );
}
else if( varname[0] == '>' && !varname[1] )
{
value = lol_get( lol, 1 );
}
else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] )
{
value = lol_get( lol, varname[0] - '1' );
}
else
{
value = var_get( varname );
}
/* The fast path: $(x) - just copy the variable value. */
if( out == buf->value && !bracket && !colon && in == end )
/* Handle negitive indexes: part two. */
{
int length = list_length( value );
if (sub1 < 0)
sub1 = length + sub1;
else
sub1 -= 1;
if (sub2 < 0)
sub2 = length + 1 + sub2 - sub1;
else
sub2 -= sub1;
/*
** The "sub2 < 0" test handles the semantic error
** of sub2 < sub1.
*/
if ( sub2 < 0 )
sub2 = 0;
}
/* The fast path: $(x) - just copy the variable value. */
/* This is only an optimization */
if( out == out_buf && !bracket && !colon && in == end )
{
string_free( &variable );
string_free( &variable );
l = list_copy( l, value );
continue;
}
/* Adjust negative indices */
if ( sub1 < 0 || sub2 < 0 )
{
int length = list_length( value );
sub1 = adjust_index( sub1, length );
sub2 = adjust_index( sub2, length );
}
/* Handle start subscript */
while( sub1 > 0 && value )
--sub1, value = list_next( value );
/* Empty w/ :E=default? */
if( !value && colon && edits.empty.ptr )
evalue = value = list_new( L0, newstr( edits.empty.ptr ) );
/* For each variable value */
for( i = 1; value; i++, value = list_next( value ) )
string_new( &out1 );
for( ; value; value = list_next( value ) )
{
LIST *rem;
size_t postfix_start;
size_t postfix_start;
/* Skip members not in subscript */
/* Handle end subscript (length actually) */
if( bracket && ( i < sub1 || sub2 && i > sub2 ) )
continue;
if( sub2 >= 0 && --sub2 < 0 )
break;
string_truncate( buf, prefix_length );
string_truncate( buf, prefix_length );
/* Apply : mods, if present */
if( colon )
var_edit( value->string, colon + 1, buf );
if( colon && edits.filemods )
var_edit_file( value->string, &out1, &edits );
else
string_append( buf, value->string );
string_append( &out1, value->string );
if( colon && ( edits.upshift || edits.downshift || edits.to_slashes ) )
var_edit_shift( &out1, &edits );
/* Handle :J=joinval */
/* If we have more values for this var, just */
/* keep appending them (with the join value) */
/* rather than creating separate LIST elements. */
if( colon && edits.join.ptr &&
( list_next( value ) || list_next( vars ) ) )
{
string_append( &out1, edits.join.ptr );
continue;
}
string_append( buf, out1.value );
string_free( &out1 );
string_new( &out1 );
/* If no remainder, append result to output chain. */
@@ -325,22 +412,27 @@ var_expand(
continue;
}
/* For each remainder, append the complete string */
/* to the output chain. */
/* Remember the end of the variable expansion so */
/* we can just tack on each instance of 'remainder' */
postfix_start = buf->size;
/* For each remainder, or just once if no remainder, */
/* append the complete string to the output chain */
postfix_start = buf->size;
for( rem = remainder; rem; rem = list_next( rem ) )
{
string_truncate( buf, postfix_start );
string_append( buf, rem->string );
string_truncate( buf, postfix_start );
string_append( buf, rem->string );
l = list_new( l, newstr( buf->value ) );
}
string_free( &variable );
}
string_free( &variable );
string_new( &out1 );
/* Toss used empty */
if( evalue )
list_free( evalue );
}
/* variables & remainder were gifts from var_expand */
@@ -358,92 +450,17 @@ var_expand(
printf( "\n" );
}
string_free( buf );
string_free( buf );
return l;
}
}
/*
* var_edit() - copy input target name to output, performing : modifiers
*/
static void
var_edit(
char *in,
char *mods,
string *out)
{
FILENAME oldf, newf;
VAR_ACTS acts;
/* Parse apart original filename, putting parts into "oldf" */
file_parse( in, &oldf );
/* Parse apart modifiers, putting them into "newf" */
var_mods( mods, &newf, &acts );
/* Replace any oldf with newf */
if( newf.f_grist.ptr )
oldf.f_grist = newf.f_grist;
if( newf.f_root.ptr )
oldf.f_root = newf.f_root;
if( newf.f_dir.ptr )
oldf.f_dir = newf.f_dir;
if( newf.f_base.ptr )
oldf.f_base = newf.f_base;
if( newf.f_suffix.ptr )
oldf.f_suffix = newf.f_suffix;
if( newf.f_member.ptr )
oldf.f_member = newf.f_member;
/* If requested, modify oldf to point to parent */
if( acts.parent )
file_parent( &oldf );
/* Put filename back together */
file_build( &oldf, out, 0 );
/* Handle upshifting, downshifting now */
/* Handle conversion of "\" to "/" */
{
char* p;
for ( p = out->value; *p; ++p)
{
if( acts.upshift )
{
*p = toupper( *p );
}
else if( acts.downshift )
{
*p = tolower( *p );
}
if ( acts.to_slashes )
{
if ( *p == '\\' )
*p = '/';
}
}
out->size = p - out->value;
}
}
/*
* var_mods() - parse : modifiers into FILENAME structure
* var_edit_parse() - parse : modifiers into PATHNAME structure
*
* The : modifiers in a $(varname:modifier) currently support replacing
* or omitting elements of a filename, and so they are parsed into a
* FILENAME structure (which contains pointers into the original string).
* PATHNAME structure (which contains pointers into the original string).
*
* Modifiers of the form "X=value" replace the component X with
* the given value. Modifiers without the "=value" cause everything
@@ -470,109 +487,164 @@ var_edit(
* f->f_xxx.len = 0
* -> omit component xxx
*
* var_edit() above and file_build() obligingly follow this convention.
* var_edit_file() below and path_build() obligingly follow this convention.
*/
static void
var_mods(
var_edit_parse(
char *mods,
FILENAME *f,
VAR_ACTS *acts )
VAR_EDITS *edits )
{
char *flags = "GRDBSMT";
int havezeroed = 0;
memset( (char *)f, 0, sizeof( *f ) );
memset( (char *)acts, 0, sizeof( *acts ) );
memset( (char *)edits, 0, sizeof( *edits ) );
while( *mods )
{
char *fl;
FILEPART *fp;
char *p;
PATHPART *fp;
/* First take care of :U or :L (upshift, downshift) */
if( *mods == 'L' )
switch( *mods++ )
{
acts->downshift = 1;
++mods;
continue;
case 'L': edits->downshift = 1; continue;
case 'U': edits->upshift = 1; continue;
case 'P': edits->parent = edits->filemods = 1; continue;
case 'E': fp = &edits->empty; goto strval;
case 'J': fp = &edits->join; goto strval;
case 'G': fp = &edits->f.f_grist; goto fileval;
case 'R': fp = &edits->f.f_root; goto fileval;
case 'D': fp = &edits->f.f_dir; goto fileval;
case 'B': fp = &edits->f.f_base; goto fileval;
case 'S': fp = &edits->f.f_suffix; goto fileval;
case 'M': fp = &edits->f.f_member; goto fileval;
case 'T': edits->to_slashes = 1; continue;
default: return; /* should complain, but so what... */
}
else if( *mods == 'U' )
fileval:
/* Handle :CHARS, where each char (without a following =) */
/* selects a particular file path element. On the first such */
/* char, we deselect all others (by setting ptr = "", len = 0) */
/* and for each char we select that element (by setting ptr = 0) */
edits->filemods = 1;
if( *mods != '=' )
{
acts->upshift = 1;
++mods;
continue;
}
else if( *mods == 'P' )
{
acts->parent = 1;
++mods;
continue;
}
else if ( *mods == 'T' )
{
acts->to_slashes = 1;
++mods;
continue;
}
/* Now handle the file component flags */
if( !( fl = strchr( flags, *mods++ ) ) )
break; /* should complain, but so what... */
fp = &f->part[ fl - flags ];
if( *mods++ != '=' )
{
/* :X - turn everything but X off */
int i;
mods--;
if( !havezeroed++ )
for( i = 0; i < 6; i++ )
{
f->part[ i ].len = 0;
f->part[ i ].ptr = "";
edits->f.part[ i ].len = 0;
edits->f.part[ i ].ptr = "";
}
fp->ptr = 0;
continue;
}
strval:
/* Handle :X=value, or :X */
if( *mods != '=' )
{
fp->ptr = "";
fp->len = 0;
}
else if( p = strchr( mods, MAGIC_COLON ) )
{
*p = 0;
fp->ptr = ++mods;
fp->len = p - mods;
mods = p + 1;
}
else
{
/* :X=value - set X to value */
char *p;
if( p = strchr( mods, MAGIC_COLON ) )
{
fp->ptr = mods;
fp->len = p - mods;
mods = p + 1;
}
else
{
fp->ptr = mods;
fp->len = strlen( mods );
mods += fp->len;
}
fp->ptr = ++mods;
fp->len = strlen( mods );
mods += fp->len;
}
}
}
static int adjust_index( int index, int length )
/*
* var_edit_file() - copy input target name to output, modifying filename
*/
static void
var_edit_file(
char *in,
string *out,
VAR_EDITS *edits )
{
if ( index < 0 )
index = length + 1 + index;
/** For first range index negative values are ok.
For second return value of 0 means don't use second bound.
We need to make it -1 so that all elements are skipped.
*/
if ( index == 0 )
index = -1;
return index;
PATHNAME pathname;
/* Parse apart original filename, putting parts into "pathname" */
path_parse( in, &pathname );
/* Replace any pathname with edits->f */
if( edits->f.f_grist.ptr )
pathname.f_grist = edits->f.f_grist;
if( edits->f.f_root.ptr )
pathname.f_root = edits->f.f_root;
if( edits->f.f_dir.ptr )
pathname.f_dir = edits->f.f_dir;
if( edits->f.f_base.ptr )
pathname.f_base = edits->f.f_base;
if( edits->f.f_suffix.ptr )
pathname.f_suffix = edits->f.f_suffix;
if( edits->f.f_member.ptr )
pathname.f_member = edits->f.f_member;
/* If requested, modify pathname to point to parent */
if( edits->parent )
path_parent( &pathname );
/* Put filename back together */
path_build( &pathname, out, 0 );
}
/*
* var_edit_shift() - do upshift/downshift mods
*/
static void
var_edit_shift(
string *out,
VAR_EDITS *edits )
{
/* Handle upshifting, downshifting and slash translation now */
char *p;
for ( p = out->value; *p; ++p)
{
if (edits->upshift)
{
*p = toupper( *p );
}
else if ( edits->downshift )
{
*p = tolower( *p );
}
if ( edits->to_slashes )
{
if ( *p == '\\')
*p = '/';
}
}
out->size = p - out->value;
}
#ifndef NDEBUG

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -14,6 +14,7 @@
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# ifdef OS_MAC
@@ -61,9 +62,10 @@ void CopyC2PStr(const char * cstr, StringPtr pstr)
void
file_dirscan(
char *dir,
void (*func)( char *file, int s, time_t t ) )
scanback func,
void *closure )
{
FILENAME f;
PATHNAME f;
string filename[1];
unsigned char fullPath[ 512 ];
@@ -86,7 +88,7 @@ file_dirscan(
/* Special case ":" - enter it */
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == ':' )
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
/* Now enter contents of directory */
@@ -131,8 +133,8 @@ file_dirscan(
f.f_base.len = *fullPath;
string_truncate( filename, 0 );
file_build( &f, filename, 0 );
(*func)( filename->value, 0 /* not stat()'ed */, (time_t)0 );
path_build( &f, filename, 0 );
(*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
}
string_free( filename );
}
@@ -163,8 +165,8 @@ file_time(
void
file_archscan(
char *archive,
void (*func)( char *file, int s, time_t t ) )
scanback func,
void *closure )
{
}

View File

@@ -14,6 +14,7 @@
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# include "strings.h"
# ifdef OS_NT
@@ -56,9 +57,10 @@
void
file_dirscan(
char *dir,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
FILENAME f;
PATHNAME f;
string filespec[1];
string filename[1];
long handle;
@@ -77,9 +79,9 @@ file_dirscan(
/* Special case \ or d:\ : enter it */
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
/* Now enter contents of directory */
@@ -106,9 +108,9 @@ file_dirscan(
f.f_base.len = strlen( finfo->ff_name );
string_truncate( filename, 0 );
file_build( &f, filename );
path_build( &f, filename );
(*func)( filename->value, 1 /* stat()'ed */, time_write );
(*func)( closure, filename->value, 1 /* stat()'ed */, time_write );
ret = findnext( finfo );
}
@@ -128,9 +130,9 @@ file_dirscan(
f.f_base.len = strlen( finfo->name );
string_truncate( filename, 0 );
file_build( &f, filename, 0 );
path_build( &f, filename, 0 );
(*func)( filename->value, 1 /* stat()'ed */, finfo->time_write );
(*func)( closure, filename->value, 1 /* stat()'ed */, finfo->time_write );
ret = _findnext( handle, finfo );
}
@@ -189,7 +191,8 @@ struct ar_hdr {
void
file_archscan(
char *archive,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
struct ar_hdr ar_hdr;
char *string_table = 0;
@@ -271,7 +274,7 @@ file_archscan(
name = c + 1;
sprintf( buf, "%s(%.*s)", archive, endname - name, name );
(*func)( buf, 1 /* time valid */, (time_t)lar_date );
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
offset += SARHDR + lar_size;
lseek( fd, offset, 0 );

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -14,6 +14,7 @@
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
/* note that we use "fileunix.c" when compiling with EMX on OS/2 */
# if defined(OS_OS2) && !defined(__EMX__)
@@ -48,9 +49,10 @@
void
file_dirscan(
char *dir,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
FILENAME f;
PATHNAME f;
string filespec[1];
long handle;
int ret;
@@ -69,9 +71,9 @@ file_dirscan(
string_copy( filespec, dir );
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
else
string_push_back( filespec, '/' );
@@ -97,8 +99,8 @@ file_dirscan(
f.f_base.len = strlen( finfo->name );
string_truncate( filename, 0 );
file_build( &f, filename, 0 );
(*func)( filename->value, 0 /* not stat()'ed */, (time_t)0 );
path_build( &f, filename, 0 );
(*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
}
while( !_dos_findnext( finfo ) );
string_free( filename );
@@ -130,7 +132,8 @@ file_time(
void
file_archscan(
char *archive,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
}

View File

@@ -1,10 +1,10 @@
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# include "strings.h"
void
file_build1(
FILENAME *f,
PATHNAME *f,
string* file)
{
if( DEBUG_SEARCH )

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -13,57 +13,16 @@
*/
/*
* filesys.h - FILENAME struct and OS specific file routines
*/
/*
* FILENAME - a name of a file, broken into <grist>dir/base/suffix(member)
*
* <grist> is salt to distinguish between targets that otherwise would
* have the same name: it never appears in the bound name of a target.
* (member) is an archive member name: the syntax is arbitrary, but must
* agree in file_parse(), file_build() and the Jambase.
*
* On VMS, we keep track of whether the original path was a directory
* (without a file), so that $(VAR:D) can climb to the parent.
* filesys.h - OS specific file routines
*/
#ifndef FILESYS_DWA20011025_H
# define FILESYS_DWA20011025_H
# include "strings.h"
typedef void (*scanback)( void *closure, char *file, int found, time_t t );
typedef struct _filename FILENAME;
typedef struct _filepart FILEPART;
struct _filepart {
char *ptr;
int len;
};
struct _filename {
FILEPART part[6];
# ifdef OS_VMS
int parent;
# endif
# define f_grist part[0]
# define f_root part[1]
# define f_dir part[2]
# define f_base part[3]
# define f_suffix part[4]
# define f_member part[5]
} ;
void file_build( FILENAME *f, string *file, int binding );
void file_build1( FILENAME *f, string *file );
void file_parse( char *file, FILENAME *f );
void file_parent( FILENAME *f );
void file_dirscan( char *dir, void (*func)( char *f, int s, time_t t ) );
void file_archscan( char *arch, void (*func)( char *f, int s, time_t t ) );
void file_dirscan( char *dir, scanback func, void *closure );
void file_archscan( char *arch, scanback func, void *closure );
int file_time( char *filename, time_t *time );

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -15,6 +15,7 @@
# include "jam.h"
# include "filesys.h"
# include "strings.h"
# include "pathsys.h"
# ifdef USE_FILEUNIX
@@ -48,7 +49,7 @@
# endif
# if defined( OS_MVS ) || \
defined( OS_INTERIX )
defined( OS_INTERIX ) || defined(OS_AIX)
#define ARMAG "!<arch>\n"
#define SARMAG 8
@@ -108,9 +109,10 @@ struct ar_hdr /* archive file member header - printable ascii */
void
file_dirscan(
char *dir,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
FILENAME f;
PATHNAME f;
DIR *d;
STRUCT_DIRENT *dirent;
string filename[1];
@@ -127,7 +129,7 @@ file_dirscan(
/* Special case / : enter it */
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' )
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
/* Now enter contents of directory */
@@ -149,9 +151,9 @@ file_dirscan(
f.f_base.len = strlen( f.f_base.ptr );
string_truncate( filename, 0 );
file_build( &f, filename, 0 );
path_build( &f, filename, 0 );
(*func)( filename->value, 0 /* not stat()'ed */, (time_t)0 );
(*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
}
string_free( filename );
@@ -188,7 +190,8 @@ file_time(
void
file_archscan(
char *archive,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
# ifndef NO_AR
struct ar_hdr ar_hdr;
@@ -266,7 +269,7 @@ file_archscan(
sprintf( buf, "%s(%s)", archive, lar_name );
(*func)( buf, 1 /* time valid */, (time_t)lar_date );
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
lseek( fd, offset, 0 );
@@ -286,7 +289,8 @@ file_archscan(
void
file_archscan(
char *archive,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
struct fl_hdr fl_hdr;
@@ -332,7 +336,7 @@ file_archscan(
sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
(*func)( buf, 1 /* time valid */, (time_t)lar_date );
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
}
close( fd );

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -14,6 +14,7 @@
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# ifdef OS_VMS
@@ -52,25 +53,41 @@
#include <starlet.h>
/* Supply missing prototypes for lbr$-routines*/
int lbr$close();
int lbr$get_index();
int lbr$ini_control();
int lbr$open();
int lbr$set_module();
/*
* unlink() - remove a file
*/
extern "C" {
#if __CRTL_VER < 70000000
int lbr$set_module(
void **,
unsigned long *,
struct dsc$descriptor_s *,
unsigned short *,
void * );
int lbr$open( void **,
struct dsc$descriptor_s *,
void *,
void *,
void *,
void *,
void * );
int lbr$ini_control(
void **,
unsigned long *,
unsigned long *,
void * );
int lbr$get_index(
void **,
unsigned long *,
int (*func)( struct dsc$descriptor_s *, unsigned long *),
void * );
int lbr$close(
void ** );
unlink( char *f )
{
remove( f );
}
#endif
static void
file_cvttime(
unsigned int *curtime,
@@ -91,7 +108,8 @@ file_cvttime(
void
file_dirscan(
char *dir,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
struct FAB xfab;
@@ -102,7 +120,7 @@ file_dirscan(
string filename2[1];
char dirname[256];
register int status;
FILENAME f;
PATHNAME f;
memset( (char *)&f, '\0', sizeof( f ) );
@@ -145,15 +163,15 @@ file_dirscan(
if( !strcmp( dir, "[000000]" ) )
{
(*func)( "[000000]", 1 /* time valid */, 1 /* old but true */ );
(*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
}
/* Add bogus directory for [] */
if( !strcmp( dir, "[]" ) )
{
(*func)( "[]", 1 /* time valid */, 1 /* old but true */ );
(*func)( "[-]", 1 /* time valid */, 1 /* old but true */ );
(*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
(*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
}
string_new( filename2 );
@@ -199,7 +217,7 @@ file_dirscan(
}
string_truncate( filename2, 0 );
file_build( &f, filename2, 0 );
path_build( &f, filename2, 0 );
/*
if( DEBUG_SEARCH )
@@ -210,12 +228,9 @@ file_dirscan(
filename2);
*/
(*func)( filename2->value, 1 /* time valid */, time );
(*func)( closure, filename2->value, 1 /* time valid */, time );
}
string_free( filename2 );
if ( status != RMS$_NMF && status != RMS$_FNF )
lib$signal( xfab.fab$l_sts, xfab.fab$l_stv );
}
int
@@ -229,7 +244,8 @@ file_time(
}
static char *VMS_archive = 0;
static void (*VMS_func)( char *file, int status, time_t t ) = 0;
static scanback VMS_func;
static void *VMS_closure;
static void *context;
static int
@@ -254,6 +270,7 @@ file_archmember(
bufdsc.dsc$w_length = sizeof( filename );
status = lbr$set_module( &context, rfa, &bufdsc,
&bufdsc.dsc$w_length, NULL );
if ( !(status & 1) )
return ( 1 );
@@ -268,7 +285,7 @@ file_archmember(
sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
(*VMS_func)( buf, 1 /* time valid */, (time_t)library_date );
(*VMS_func)( VMS_closure, buf, 1 /* time valid */, (time_t)library_date );
return ( 1 );
}
@@ -276,7 +293,8 @@ file_archmember(
void
file_archscan(
char *archive,
void (*func)( char *file, int status, time_t t ) )
scanback func,
void *closure )
{
static struct dsc$descriptor_s library =
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
@@ -289,6 +307,7 @@ file_archscan(
VMS_archive = archive;
VMS_func = func;
VMS_closure = closure;
status = lbr$ini_control( &context, &lfunc, &typ, NULL );
if ( !( status & 1 ) )

25
src/engine/frames.c Normal file
View File

@@ -0,0 +1,25 @@
/*
* (C) Copyright David Abrahams 2001. Permission to copy, use,
* modify, sell and distribute this software is granted provided this
* copyright notice appears in all copies. This software is provided
* "as is" without express or implied warranty, and with no claim as
* to its suitability for any purpose.
*/
# include "frames.h"
# include "lists.h"
void frame_init( FRAME* frame )
{
frame->prev = 0;
lol_init(frame->args);
frame->module = root_module();
frame->rulename = "module scope";
frame->procedure = 0;
}
void frame_free( FRAME* frame )
{
lol_free( frame->args );
}

View File

@@ -1,6 +1,6 @@
/*
* /+\
* +\ Copyright 1993, 2000 Christopher Seiwald.
* +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
* \+/
*
* This file is part of jam.
@@ -23,7 +23,7 @@
/*
* jam.c - make redux
*
* See Jam.html and Jamlang.html for usage information.
* See Jam.html for usage information.
*
* These comments document the code.
*
@@ -38,14 +38,18 @@
* / | \ \
* / | \ |
* scan | compile make
* | | / \ / | \
* | | / \ / | \
* | | / \ / | \
* jambase parse rules search make1
* | | \
* | | \
* | | \
* timestamp command execute
* | | / | \ / | \
* | | / | \ / | \
* | | / | \ / | \
* jambase parse | rules search make1
* | | | \
* | | | \
* | | | \
* builtins timestamp command execute
* |
* |
* |
* filesys
*
*
* The support routines are called by all of the above, but themselves
@@ -55,7 +59,7 @@
* / | | |
* / | | |
* / | | |
* lists | | filesys
* lists | | pathsys
* \ | |
* \ | |
* \ | |
@@ -67,15 +71,13 @@
*
* Roughly, the modules are:
*
* builtins.c - jam's built-in rules
* command.c - maintain lists of commands
* compile.c - compile parsed jam statements
* execunix.c - execute a shell script on UNIX
* execvms.c - execute a shell script, ala VMS
* expand.c - expand a buffer, given variable values
* fileunix.c - manipulate file names and scan directories on UNIX
* filevms.c - manipulate file names and scan directories on VMS
* fileos2.c - manipulate file names and scan directories on OS/2
* filent.c - manipulate file names and scan directories on Windows
* file*.c - scan directories and archives on *
* hash.c - simple in-memory hashing routines
* hdrmacro.c - handle header file parsing for filename macro definitions
* headers.c - handle #includes in source files
@@ -87,6 +89,8 @@
* newstr.c - string manipulation routines
* option.c - command line option processing
* parse.c - make and destroy parse trees as driven by the parser
* path*.c - manipulate file names on *
* hash.c - simple in-memory hashing routines
* regexp.c - Henry Spencer's regexp
* rules.c - access to RULEs, TARGETs, and ACTIONs
* scan.c - the jam yacc scanner
@@ -98,6 +102,7 @@
* 02/08/95 (seiwald) - -n implies -d2.
* 02/22/95 (seiwald) - -v for version info.
* 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION.
* 01/10/01 (seiwald) - pathsys.h split from filesys.h
*/
# include "jam.h"
@@ -110,6 +115,7 @@
# include "parse.h"
# include "variable.h"
# include "compile.h"
# include "builtins.h"
# include "rules.h"
# include "newstr.h"
# include "scan.h"
@@ -226,9 +232,9 @@ int main( int argc, char **argv, char **arg_environ )
printf( "Boost.Jam " );
printf( "Version %s. ", VERSION );
printf( "%s.\n", OSMINOR );
printf( " Copyright 1993, 2000 Christopher Seiwald.\n" );
printf( " Copyright 2001 David Turner.\n" );
printf( " Copyright 2001 David Abrahams.\n" );
printf( " Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. \n" );
printf( " Copyright 2001 David Turner.\n" );
printf( " Copyright 2001 David Abrahams.\n" );
return EXITOK;
}
@@ -343,10 +349,9 @@ int main( int argc, char **argv, char **arg_environ )
var_defines( symv );
}
/* Initialize builtins */
/* Initialize built-in rules */
compile_builtins();
load_builtins();
/* Parse ruleset */

View File

@@ -13,7 +13,7 @@ yyrcsid[] = "$FreeBSD: src/usr.bin/yacc/skeleton.c,v 1.28 2000/01/17 02:04:06 bd
#define YYRECOVERING() (yyerrflag!=0)
static int yygrowstack();
#define YYPREFIX "yy"
#line 94 "jamgram.y"
#line 99 "jamgram.y"
#include "jam.h"
#include "lists.h"
@@ -27,6 +27,8 @@ static int yygrowstack();
# define S0 (char *)0
# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
# define pshortcircuiteval( c,l,r ) parse_make( compile_eval,l,P0,r,S0,S0,c )
# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
@@ -35,6 +37,7 @@ static int yygrowstack();
# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
@@ -45,203 +48,211 @@ static int yygrowstack();
# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
# define pcnode( c,l,r ) parse_make( F0,l,r,P0,S0,S0,c )
# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
#line 52 "y.tab.c"
#line 54 "y.tab.c"
#define YYERRCODE 256
#define _BANG 257
#define _BANG_EQUALS 258
#define _AMPERAMPER 259
#define _LPAREN 260
#define _RPAREN 261
#define _PLUS_EQUALS 262
#define _COLON 263
#define _SEMIC 264
#define _LANGLE 265
#define _LANGLE_EQUALS 266
#define _EQUALS 267
#define _RANGLE 268
#define _RANGLE_EQUALS 269
#define _QUESTION_EQUALS 270
#define _LBRACKET 271
#define _RBRACKET 272
#define ACTIONS 273
#define BIND 274
#define CASE 275
#define DEFAULT 276
#define ELSE 277
#define EXISTING 278
#define FOR 279
#define IF 280
#define IGNORE 281
#define IN 282
#define INCLUDE 283
#define LOCAL 284
#define MODULE 285
#define ON 286
#define PIECEMEAL 287
#define QUIETLY 288
#define RETURN 289
#define RULE 290
#define SWITCH 291
#define TOGETHER 292
#define UPDATED 293
#define WHILE 294
#define _LBRACE 295
#define _BARBAR 296
#define _RBRACE 297
#define ARG 298
#define STRING 299
#define _AMPER 259
#define _AMPERAMPER 260
#define _LPAREN 261
#define _RPAREN 262
#define _PLUS_EQUALS 263
#define _COLON 264
#define _SEMIC 265
#define _LANGLE 266
#define _LANGLE_EQUALS 267
#define _EQUALS 268
#define _RANGLE 269
#define _RANGLE_EQUALS 270
#define _QUESTION_EQUALS 271
#define _LBRACKET 272
#define _RBRACKET 273
#define ACTIONS 274
#define BIND 275
#define CASE 276
#define DEFAULT 277
#define ELSE 278
#define EXISTING 279
#define FOR 280
#define IF 281
#define IGNORE 282
#define IN 283
#define INCLUDE 284
#define LOCAL 285
#define MODULE 286
#define ON 287
#define PIECEMEAL 288
#define QUIETLY 289
#define RETURN 290
#define RULE 291
#define SWITCH 292
#define TOGETHER 293
#define UPDATED 294
#define WHILE 295
#define _LBRACE 296
#define _BAR 297
#define _BARBAR 298
#define _RBRACE 299
#define ARG 300
#define STRING 301
const short yylhs[] = { -1,
0, 0, 2, 2, 1, 1, 1, 3, 6, 6,
7, 7, 9, 9, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 16, 17,
4, 11, 11, 11, 11, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 12, 12, 18,
8, 8, 5, 19, 19, 10, 10, 14, 14, 20,
20, 20, 20, 20, 20, 15, 15,
4, 4, 4, 4, 4, 4, 4, 4, 4, 16,
17, 4, 11, 11, 11, 11, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
12, 12, 18, 8, 8, 5, 19, 19, 10, 21,
10, 20, 20, 20, 14, 14, 22, 22, 22, 22,
22, 22, 15, 15,
};
const short yylen[] = { 2,
0, 1, 1, 1, 1, 2, 5, 0, 2, 1,
3, 0, 1, 0, 3, 3, 3, 4, 5, 6,
3, 8, 5, 5, 5, 5, 7, 5, 0, 0,
9, 1, 1, 1, 2, 1, 3, 3, 3, 3,
3, 3, 3, 2, 3, 3, 3, 0, 2, 4,
1, 3, 1, 0, 2, 1, 4, 0, 2, 1,
1, 1, 1, 1, 1, 0, 2,
3, 8, 5, 5, 5, 5, 7, 5, 3, 0,
0, 9, 1, 1, 1, 2, 1, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 2, 3,
0, 2, 4, 1, 3, 1, 0, 2, 1, 0,
4, 2, 4, 4, 0, 2, 1, 1, 1, 1,
1, 1, 0, 2,
};
const short yydefred[] = { 0,
0, 58, 0, 0, 54, 0, 0, 54, 54, 0,
0, 0, 0, 2, 0, 0, 0, 54, 0, 13,
0, 0, 0, 56, 0, 0, 0, 0, 0, 54,
0, 0, 0, 0, 4, 0, 3, 0, 0, 6,
0, 33, 32, 34, 0, 54, 54, 0, 65, 62,
64, 63, 61, 60, 0, 59, 0, 44, 0, 0,
0, 0, 0, 0, 0, 54, 0, 0, 0, 16,
55, 54, 10, 0, 0, 0, 21, 0, 0, 15,
54, 17, 0, 35, 0, 0, 57, 54, 0, 54,
47, 38, 39, 40, 37, 41, 42, 43, 45, 0,
0, 9, 0, 0, 0, 0, 0, 0, 0, 52,
54, 0, 54, 18, 67, 29, 0, 0, 7, 19,
25, 0, 23, 49, 26, 0, 28, 0, 0, 0,
0, 0, 11, 20, 30, 0, 27, 50, 0, 22,
31,
60, 65, 0, 0, 57, 0, 0, 0, 57, 57,
0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
13, 0, 0, 0, 59, 0, 0, 0, 0, 0,
57, 0, 0, 0, 0, 0, 4, 0, 3, 0,
0, 6, 0, 34, 33, 35, 0, 57, 57, 0,
57, 0, 72, 69, 71, 70, 68, 67, 0, 66,
0, 49, 0, 0, 0, 0, 0, 0, 0, 57,
0, 0, 0, 0, 0, 16, 58, 57, 10, 0,
0, 0, 29, 21, 0, 0, 15, 57, 17, 0,
36, 0, 0, 0, 62, 61, 57, 0, 57, 50,
39, 40, 41, 38, 42, 43, 48, 44, 45, 0,
0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
55, 57, 0, 57, 18, 57, 57, 74, 30, 0,
0, 7, 19, 25, 0, 23, 52, 26, 0, 28,
0, 64, 63, 0, 0, 0, 0, 11, 20, 31,
0, 27, 53, 0, 22, 32,
};
const short yydgoto[] = { 13,
35, 36, 37, 15, 38, 74, 112, 39, 16, 17,
47, 107, 26, 19, 89, 129, 139, 108, 28, 56,
const short yydgoto[] = { 14,
37, 38, 39, 16, 40, 80, 123, 41, 17, 18,
49, 118, 27, 20, 98, 144, 154, 119, 29, 52,
19, 60,
};
const short yysindex[] = { -120,
-282, 0, -267, -234, 0, 0, -259, 0, 0, -234,
-120, 0, 0, 0, -120, -261, -83, 0, -131, 0,
-236, -234, -234, 0, -69, -250, -181, -244, -188, 0,
-210, -175, -204, -209, 0, -205, 0, -157, -154, 0,
-184, 0, 0, 0, -152, 0, 0, -156, 0, 0,
0, 0, 0, 0, -153, 0, -158, 0, -185, -244,
-244, -244, -244, -244, -244, 0, -234, -120, -234, 0,
0, 0, 0, -135, -188, -120, 0, -144, -120, 0,
0, 0, -128, 0, -150, -124, 0, 0, -149, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, -155,
-118, 0, -120, -110, -139, -143, -125, -144, -114, 0,
0, -103, 0, 0, 0, 0, -129, -104, 0, 0,
0, -78, 0, 0, 0, -71, 0, -70, -98, -120,
-103, -120, 0, 0, 0, -95, 0, 0, -93, 0,
0,
const short yysindex[] = { -88,
0, 0, -269, -248, 0, 0, -257, -229, 0, 0,
-248, -88, 0, 0, 0, -88, -254, -160, -267, -44,
0, -258, -248, -248, 0, -36, -212, -219, -229, -200,
0, -222, -71, -188, -215, -209, 0, -203, 0, -166,
-155, 0, -201, 0, 0, 0, -168, 0, 0, -229,
0, -152, 0, 0, 0, 0, 0, 0, -170, 0,
-159, 0, -153, -229, -229, -229, -229, -229, -229, 0,
-248, -248, -88, -248, -248, 0, 0, 0, 0, -140,
-200, -88, 0, 0, -146, -88, 0, 0, 0, -135,
0, -20, -124, -245, 0, 0, 0, -147, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, -141,
-165, -165, 0, -88, -105, -137, -148, -136, -146, -133,
0, 0, -71, 0, 0, 0, 0, 0, 0, -132,
-109, 0, 0, 0, -94, 0, 0, 0, -87, 0,
-84, 0, 0, -112, -88, -71, -88, 0, 0, 0,
-108, 0, 0, -104, 0, 0,
};
const short yyrindex[] = { 7,
0, 0, -92, 0, 0, -162, -201, 0, 0, 0,
-275, -163, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, -229, 0, 0, -223, -59, 0,
0, 0, 0, 0, 0, 0, 0, -142, 0, 0,
0, 0, -110, 0, 0, -115, -238, 0, 0, 0,
0, -198, -149, 0, 0, 3, 0, 0, 0, 0,
0, 0, 0, 0, 0, -237, 0, 0, -233, -60,
0, 0, -97, 0, 0, 0, 0, 0, 0, -45,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -88, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, -275, 0, 0,
0, 0, 0, 0, -59, -275, 0, -89, -275, 0,
0, 0, -146, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -96, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-253, 0, 4, 0, 0, 0, 0, -89, 0, 0,
0, -81, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, -275,
-81, -194, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, -198, 0, 0, 0, 0, 0, 0, 0,
-60, -198, 0, 0, -93, -198, 0, 0, 0, -113,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-150, -142, 0, 4, 0, 0, 0, 0, -93, 0,
0, 0, -97, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -198, -97, -111, 0, 0, 0,
0, 0, 0, 0, 0, 0,
};
const short yygindex[] = { 0,
75, -48, -27, -43, 5, 135, 0, -13, 208, -4,
127, 106, 11, 0, 0, 0, 0, 0, 0, 0,
41, -65, -25, -33, 5, 130, 0, -49, 215, 68,
131, 107, -5, 0, 0, 0, 0, 0, 0, 0,
0, 0,
};
#define YYTABLESIZE 301
const short yytable[] = { 25,
24, 73, 5, 8, 48, 25, 1, 46, 67, 27,
29, 31, 32, 33, 14, 18, 20, 25, 25, 100,
34, 8, 22, 71, 30, 23, 1, 105, 41, 36,
109, 36, 58, 59, 75, 53, 1, 53, 53, 53,
53, 46, 46, 53, 68, 69, 53, 73, 53, 67,
85, 86, 53, 24, 119, 92, 93, 94, 95, 96,
97, 57, 25, 24, 25, 36, 36, 110, 127, 54,
98, 53, 53, 67, 14, 91, 102, 99, 72, 101,
8, 136, 70, 138, 76, 79, 69, 137, 77, 40,
78, 80, 115, 54, 117, 14, 54, 126, 56, 54,
54, 54, 8, 56, 54, 81, 56, 54, 54, 82,
69, 42, 56, 83, 84, 87, 43, 128, 51, 44,
88, 51, 56, 90, 12, 45, 12, 13, 103, 51,
106, 111, 12, 12, 54, 54, 12, 12, 12, 114,
67, 118, 12, 12, 12, 116, 49, 12, 12, 50,
1, 12, 2, 120, 122, 51, 52, 121, 3, 4,
53, 54, 5, 6, 7, 130, 55, 1, 8, 2,
9, 123, 131, 10, 11, 3, 4, 12, 42, 5,
20, 7, 125, 43, 132, 8, 44, 9, 60, 133,
10, 11, 45, 134, 12, 61, 62, 63, 64, 65,
135, 140, 46, 141, 8, 14, 66, 48, 14, 104,
21, 113, 66, 124, 0, 0, 0, 0, 0, 0,
#define YYTABLESIZE 303
const short yytable[] = { 83,
24, 95, 5, 8, 79, 36, 1, 110, 23, 28,
30, 32, 24, 34, 35, 21, 116, 62, 63, 50,
120, 37, 37, 1, 37, 56, 56, 31, 56, 56,
56, 56, 51, 57, 56, 81, 43, 56, 121, 56,
15, 61, 1, 56, 126, 76, 71, 72, 132, 71,
72, 25, 92, 93, 127, 79, 42, 57, 37, 37,
37, 57, 56, 56, 56, 108, 109, 78, 111, 112,
25, 26, 139, 82, 107, 33, 84, 143, 26, 151,
85, 153, 113, 73, 74, 75, 86, 74, 75, 140,
26, 26, 14, 71, 72, 87, 77, 88, 90, 91,
8, 128, 44, 130, 97, 71, 72, 45, 100, 89,
46, 46, 152, 59, 57, 57, 47, 94, 59, 47,
96, 59, 57, 99, 114, 122, 48, 59, 141, 117,
142, 101, 102, 103, 104, 105, 106, 59, 26, 26,
125, 26, 26, 74, 75, 46, 46, 46, 129, 57,
57, 135, 57, 47, 47, 47, 57, 131, 12, 133,
12, 134, 136, 145, 8, 138, 12, 12, 146, 147,
12, 12, 12, 12, 148, 13, 12, 12, 12, 14,
149, 12, 12, 1, 57, 2, 12, 8, 150, 14,
155, 3, 4, 14, 156, 5, 6, 7, 8, 73,
1, 9, 2, 10, 8, 51, 11, 12, 3, 4,
115, 13, 5, 21, 7, 8, 54, 22, 9, 54,
10, 64, 124, 11, 12, 137, 0, 54, 13, 65,
66, 67, 68, 69, 53, 0, 0, 54, 0, 0,
0, 0, 44, 55, 56, 0, 70, 45, 57, 58,
46, 0, 0, 0, 0, 59, 47, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 24, 0, 24, 0, 24, 0, 5, 8, 24,
24, 0, 0, 24, 24, 24, 0, 0, 0, 24,
24, 24, 14, 14, 24, 24, 14, 24, 24, 5,
8,
0, 0, 24, 0, 24, 0, 24, 0, 5, 8,
24, 24, 0, 0, 24, 24, 24, 24, 0, 0,
24, 24, 24, 14, 14, 24, 24, 14, 0, 24,
24, 5, 8,
};
const short yycheck[] = { 4,
0, 29, 0, 0, 18, 10, 0, 261, 259, 5,
6, 7, 8, 9, 290, 298, 284, 22, 23, 68,
10, 297, 257, 28, 284, 260, 271, 76, 290, 259,
79, 261, 22, 23, 30, 259, 271, 261, 262, 263,
264, 295, 296, 267, 295, 296, 270, 75, 272, 259,
46, 47, 276, 298, 103, 60, 61, 62, 63, 64,
65, 298, 67, 298, 69, 295, 296, 81, 112, 271,
66, 295, 296, 259, 0, 261, 72, 67, 267, 69,
275, 130, 264, 132, 295, 295, 296, 131, 264, 15,
295, 297, 88, 295, 90, 290, 298, 111, 262, 263,
264, 264, 297, 267, 267, 263, 270, 271, 271, 264,
296, 262, 276, 298, 267, 272, 267, 113, 261, 270,
274, 264, 286, 282, 271, 276, 273, 290, 264, 272,
275, 260, 279, 280, 298, 298, 283, 284, 285, 264,
259, 297, 289, 290, 291, 295, 278, 294, 295, 281,
271, 298, 273, 264, 298, 287, 288, 297, 279, 280,
292, 293, 283, 284, 285, 295, 298, 271, 289, 273,
291, 297, 277, 294, 295, 279, 280, 298, 262, 283,
284, 285, 297, 267, 263, 289, 270, 291, 258, 261,
294, 295, 276, 264, 298, 265, 266, 267, 268, 269,
299, 297, 286, 297, 264, 298, 295, 297, 290, 75,
3, 85, 282, 108, -1, -1, -1, -1, -1, -1,
const short yycheck[] = { 33,
0, 51, 0, 0, 30, 11, 0, 73, 257, 5,
6, 7, 261, 9, 10, 285, 82, 23, 24, 287,
86, 259, 260, 272, 262, 259, 260, 285, 262, 263,
264, 265, 300, 272, 268, 31, 291, 271, 88, 273,
0, 300, 272, 277, 290, 265, 259, 260, 114, 259,
260, 300, 48, 49, 300, 81, 16, 296, 296, 297,
298, 300, 296, 297, 298, 71, 72, 268, 74, 75,
300, 4, 122, 296, 70, 8, 265, 127, 11, 145,
296, 147, 78, 296, 297, 298, 296, 297, 298, 123,
23, 24, 291, 259, 260, 299, 29, 264, 300, 268,
299, 97, 263, 99, 275, 259, 260, 268, 262, 265,
271, 262, 146, 263, 264, 265, 277, 50, 268, 262,
273, 271, 272, 283, 265, 261, 287, 277, 124, 276,
126, 64, 65, 66, 67, 68, 69, 287, 71, 72,
265, 74, 75, 297, 298, 296, 297, 298, 296, 265,
300, 300, 268, 296, 297, 298, 272, 299, 272, 265,
274, 299, 299, 296, 276, 299, 280, 281, 278, 264,
284, 285, 286, 287, 262, 291, 290, 291, 292, 291,
265, 295, 296, 272, 300, 274, 300, 299, 301, 300,
299, 280, 281, 291, 299, 284, 285, 286, 287, 296,
272, 290, 274, 292, 265, 299, 295, 296, 280, 281,
81, 300, 284, 285, 286, 287, 262, 3, 290, 265,
292, 258, 92, 295, 296, 119, -1, 273, 300, 266,
267, 268, 269, 270, 279, -1, -1, 282, -1, -1,
-1, -1, 263, 288, 289, -1, 283, 268, 293, 294,
271, -1, -1, -1, -1, 300, 277, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 271, -1, 273, -1, 275, -1, 275, 275, 279,
280, -1, -1, 283, 284, 285, -1, -1, -1, 289,
290, 291, 290, 290, 294, 295, 290, 297, 298, 297,
297,
-1, -1, 272, -1, 274, -1, 276, -1, 276, 276,
280, 281, -1, -1, 284, 285, 286, 287, -1, -1,
290, 291, 292, 291, 291, 295, 296, 291, -1, 299,
300, 299, 299,
};
#define YYFINAL 13
#define YYFINAL 14
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 299
#define YYMAXTOKEN 301
#if YYDEBUG
const char * const yyname[] = {
"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -250,13 +261,13 @@ const char * const yyname[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"_BANG","_BANG_EQUALS",
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"_BANG","_BANG_EQUALS","_AMPER",
"_AMPERAMPER","_LPAREN","_RPAREN","_PLUS_EQUALS","_COLON","_SEMIC","_LANGLE",
"_LANGLE_EQUALS","_EQUALS","_RANGLE","_RANGLE_EQUALS","_QUESTION_EQUALS",
"_LBRACKET","_RBRACKET","ACTIONS","BIND","CASE","DEFAULT","ELSE","EXISTING",
"FOR","IF","IGNORE","IN","INCLUDE","LOCAL","MODULE","ON","PIECEMEAL","QUIETLY",
"RETURN","RULE","SWITCH","TOGETHER","UPDATED","WHILE","_LBRACE","_BARBAR",
"_RBRACE","ARG","STRING",
"RETURN","RULE","SWITCH","TOGETHER","UPDATED","WHILE","_LBRACE","_BAR",
"_BARBAR","_RBRACE","ARG","STRING",
};
const char * const yyrule[] = {
"$accept : run",
@@ -283,11 +294,12 @@ const char * const yyrule[] = {
"rule : RETURN list _SEMIC",
"rule : FOR local_opt ARG IN list _LBRACE block _RBRACE",
"rule : SWITCH list _LBRACE cases _RBRACE",
"rule : IF cond _LBRACE block _RBRACE",
"rule : IF expr _LBRACE block _RBRACE",
"rule : MODULE list _LBRACE block _RBRACE",
"rule : WHILE cond _LBRACE block _RBRACE",
"rule : IF cond _LBRACE block _RBRACE ELSE rule",
"rule : WHILE expr _LBRACE block _RBRACE",
"rule : IF expr _LBRACE block _RBRACE ELSE rule",
"rule : local_opt RULE ARG arglist_opt rule",
"rule : ON arg rule",
"$$1 :",
"$$2 :",
"rule : ACTIONS eflags ARG bindlist _LBRACE $$1 STRING $$2 _RBRACE",
@@ -295,18 +307,20 @@ const char * const yyrule[] = {
"assign : _PLUS_EQUALS",
"assign : _QUESTION_EQUALS",
"assign : DEFAULT _EQUALS",
"cond : arg",
"cond : arg _EQUALS arg",
"cond : arg _BANG_EQUALS arg",
"cond : arg _LANGLE arg",
"cond : arg _LANGLE_EQUALS arg",
"cond : arg _RANGLE arg",
"cond : arg _RANGLE_EQUALS arg",
"cond : arg IN list",
"cond : _BANG cond",
"cond : cond _AMPERAMPER cond",
"cond : cond _BARBAR cond",
"cond : _LPAREN cond _RPAREN",
"expr : arg",
"expr : arg _EQUALS arg",
"expr : arg _BANG_EQUALS arg",
"expr : arg _LANGLE arg",
"expr : arg _LANGLE_EQUALS arg",
"expr : arg _RANGLE arg",
"expr : arg _RANGLE_EQUALS arg",
"expr : expr _AMPER expr",
"expr : expr _AMPERAMPER expr",
"expr : expr _BAR expr",
"expr : expr _BARBAR expr",
"expr : arg IN list",
"expr : _BANG expr",
"expr : _LPAREN expr _RPAREN",
"cases :",
"cases : case cases",
"case : CASE ARG _COLON block",
@@ -316,7 +330,11 @@ const char * const yyrule[] = {
"listp :",
"listp : listp arg",
"arg : ARG",
"arg : _LBRACKET ARG lol _RBRACKET",
"$$3 :",
"arg : _LBRACKET $$3 func _RBRACKET",
"func : ARG lol",
"func : ON arg ARG lol",
"func : ON arg RETURN list",
"eflags :",
"eflags : eflags eflag",
"eflag : UPDATED",
@@ -554,270 +572,298 @@ yyreduce:
switch (yyn)
{
case 2:
#line 135 "jamgram.y"
#line 142 "jamgram.y"
{ parse_save( yyvsp[0].parse ); }
break;
case 3:
#line 146 "jamgram.y"
#line 153 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; }
break;
case 4:
#line 148 "jamgram.y"
#line 155 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; }
break;
case 5:
#line 152 "jamgram.y"
#line 159 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; }
break;
case 6:
#line 154 "jamgram.y"
#line 161 "jamgram.y"
{ yyval.parse = prules( yyvsp[-1].parse, yyvsp[0].parse ); }
break;
case 7:
#line 156 "jamgram.y"
#line 163 "jamgram.y"
{ yyval.parse = plocal( yyvsp[-3].parse, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 8:
#line 160 "jamgram.y"
#line 167 "jamgram.y"
{ yyval.parse = pnull(); }
break;
case 9:
#line 164 "jamgram.y"
#line 171 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_SET; }
break;
case 10:
#line 166 "jamgram.y"
#line 173 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; yyval.number = ASSIGN_APPEND; }
break;
case 11:
#line 170 "jamgram.y"
#line 177 "jamgram.y"
{ yyval.parse = yyvsp[-1].parse; }
break;
case 12:
#line 172 "jamgram.y"
#line 179 "jamgram.y"
{ yyval.parse = P0; }
break;
case 13:
#line 176 "jamgram.y"
#line 183 "jamgram.y"
{ yyval.number = 1; }
break;
case 14:
#line 178 "jamgram.y"
#line 185 "jamgram.y"
{ yyval.number = 0; }
break;
case 15:
#line 182 "jamgram.y"
#line 189 "jamgram.y"
{ yyval.parse = yyvsp[-1].parse; }
break;
case 16:
#line 184 "jamgram.y"
#line 191 "jamgram.y"
{ yyval.parse = pincl( yyvsp[-1].parse ); }
break;
case 17:
#line 186 "jamgram.y"
#line 193 "jamgram.y"
{ yyval.parse = prule( yyvsp[-2].string, yyvsp[-1].parse ); }
break;
case 18:
#line 188 "jamgram.y"
#line 195 "jamgram.y"
{ yyval.parse = pset( yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
break;
case 19:
#line 190 "jamgram.y"
#line 197 "jamgram.y"
{ yyval.parse = psetmodule( yyvsp[-2].parse, yyvsp[-1].parse, yyvsp[-1].number ); }
break;
case 20:
#line 192 "jamgram.y"
#line 199 "jamgram.y"
{ yyval.parse = pset1( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-2].number ); }
break;
case 21:
#line 194 "jamgram.y"
#line 201 "jamgram.y"
{ yyval.parse = yyvsp[-1].parse; }
break;
case 22:
#line 196 "jamgram.y"
#line 203 "jamgram.y"
{ yyval.parse = pfor( yyvsp[-5].string, yyvsp[-3].parse, yyvsp[-1].parse, yyvsp[-6].number ); }
break;
case 23:
#line 198 "jamgram.y"
#line 205 "jamgram.y"
{ yyval.parse = pswitch( yyvsp[-3].parse, yyvsp[-1].parse ); }
break;
case 24:
#line 200 "jamgram.y"
#line 207 "jamgram.y"
{ yyval.parse = pif( yyvsp[-3].parse, yyvsp[-1].parse, pnull() ); }
break;
case 25:
#line 202 "jamgram.y"
#line 209 "jamgram.y"
{ yyval.parse = pmodule( yyvsp[-3].parse, yyvsp[-1].parse ); }
break;
case 26:
#line 204 "jamgram.y"
#line 211 "jamgram.y"
{ yyval.parse = pwhile( yyvsp[-3].parse, yyvsp[-1].parse ); }
break;
case 27:
#line 206 "jamgram.y"
#line 213 "jamgram.y"
{ yyval.parse = pif( yyvsp[-5].parse, yyvsp[-3].parse, yyvsp[0].parse ); }
break;
case 28:
#line 208 "jamgram.y"
#line 215 "jamgram.y"
{ yyval.parse = psetc( yyvsp[-2].string, yyvsp[0].parse, yyvsp[-1].parse, yyvsp[-4].number ); }
break;
case 29:
#line 210 "jamgram.y"
{ yymode( SCAN_STRING ); }
#line 217 "jamgram.y"
{ yyval.parse = pon( yyvsp[-1].parse, yyvsp[0].parse ); }
break;
case 30:
#line 212 "jamgram.y"
{ yymode( SCAN_NORMAL ); }
#line 219 "jamgram.y"
{ yymode( SCAN_STRING ); }
break;
case 31:
#line 214 "jamgram.y"
{ yyval.parse = psete( yyvsp[-6].string,yyvsp[-5].parse,yyvsp[-2].string,yyvsp[-7].number ); }
#line 221 "jamgram.y"
{ yymode( SCAN_NORMAL ); }
break;
case 32:
#line 222 "jamgram.y"
{ yyval.number = ASSIGN_SET; }
#line 223 "jamgram.y"
{ yyval.parse = psete( yyvsp[-6].string,yyvsp[-5].parse,yyvsp[-2].string,yyvsp[-7].number ); }
break;
case 33:
#line 224 "jamgram.y"
{ yyval.number = ASSIGN_APPEND; }
#line 231 "jamgram.y"
{ yyval.number = ASSIGN_SET; }
break;
case 34:
#line 226 "jamgram.y"
{ yyval.number = ASSIGN_DEFAULT; }
#line 233 "jamgram.y"
{ yyval.number = ASSIGN_APPEND; }
break;
case 35:
#line 228 "jamgram.y"
#line 235 "jamgram.y"
{ yyval.number = ASSIGN_DEFAULT; }
break;
case 36:
#line 236 "jamgram.y"
{ yyval.parse = pcnode( COND_EXISTS, yyvsp[0].parse, pnull() ); }
#line 237 "jamgram.y"
{ yyval.number = ASSIGN_DEFAULT; }
break;
case 37:
#line 238 "jamgram.y"
{ yyval.parse = pcnode( COND_EQUALS, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 244 "jamgram.y"
{ yyval.parse = peval( EXPR_EXISTS, yyvsp[0].parse, pnull() ); }
break;
case 38:
#line 240 "jamgram.y"
{ yyval.parse = pcnode( COND_NOTEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 246 "jamgram.y"
{ yyval.parse = peval( EXPR_EQUALS, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 39:
#line 242 "jamgram.y"
{ yyval.parse = pcnode( COND_LESS, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 248 "jamgram.y"
{ yyval.parse = peval( EXPR_NOTEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 40:
#line 244 "jamgram.y"
{ yyval.parse = pcnode( COND_LESSEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 250 "jamgram.y"
{ yyval.parse = peval( EXPR_LESS, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 41:
#line 246 "jamgram.y"
{ yyval.parse = pcnode( COND_MORE, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 252 "jamgram.y"
{ yyval.parse = peval( EXPR_LESSEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 42:
#line 248 "jamgram.y"
{ yyval.parse = pcnode( COND_MOREEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 254 "jamgram.y"
{ yyval.parse = peval( EXPR_MORE, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 43:
#line 250 "jamgram.y"
{ yyval.parse = pcnode( COND_IN, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 256 "jamgram.y"
{ yyval.parse = peval( EXPR_MOREEQ, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 44:
#line 252 "jamgram.y"
{ yyval.parse = pcnode( COND_NOT, yyvsp[0].parse, P0 ); }
#line 258 "jamgram.y"
{ yyval.parse = peval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 45:
#line 254 "jamgram.y"
{ yyval.parse = pcnode( COND_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 260 "jamgram.y"
{ yyval.parse = pshortcircuiteval( EXPR_AND, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 46:
#line 256 "jamgram.y"
{ yyval.parse = pcnode( COND_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
#line 262 "jamgram.y"
{ yyval.parse = peval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 47:
#line 258 "jamgram.y"
{ yyval.parse = yyvsp[-1].parse; }
#line 264 "jamgram.y"
{ yyval.parse = pshortcircuiteval( EXPR_OR, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 48:
#line 268 "jamgram.y"
{ yyval.parse = P0; }
#line 266 "jamgram.y"
{ yyval.parse = peval( EXPR_IN, yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 49:
#line 270 "jamgram.y"
{ yyval.parse = pnode( yyvsp[-1].parse, yyvsp[0].parse ); }
#line 268 "jamgram.y"
{ yyval.parse = peval( EXPR_NOT, yyvsp[0].parse, pnull() ); }
break;
case 50:
#line 274 "jamgram.y"
{ yyval.parse = psnode( yyvsp[-2].string, yyvsp[0].parse ); }
#line 270 "jamgram.y"
{ yyval.parse = yyvsp[-1].parse; }
break;
case 51:
#line 283 "jamgram.y"
{ yyval.parse = pnode( P0, yyvsp[0].parse ); }
#line 281 "jamgram.y"
{ yyval.parse = P0; }
break;
case 52:
#line 285 "jamgram.y"
{ yyval.parse = pnode( yyvsp[0].parse, yyvsp[-2].parse ); }
#line 283 "jamgram.y"
{ yyval.parse = pnode( yyvsp[-1].parse, yyvsp[0].parse ); }
break;
case 53:
#line 295 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; yymode( SCAN_NORMAL ); }
#line 287 "jamgram.y"
{ yyval.parse = psnode( yyvsp[-2].string, yyvsp[0].parse ); }
break;
case 54:
#line 299 "jamgram.y"
{ yyval.parse = pnull(); yymode( SCAN_PUNCT ); }
#line 296 "jamgram.y"
{ yyval.parse = pnode( P0, yyvsp[0].parse ); }
break;
case 55:
#line 301 "jamgram.y"
{ yyval.parse = pappend( yyvsp[-1].parse, yyvsp[0].parse ); }
#line 298 "jamgram.y"
{ yyval.parse = pnode( yyvsp[0].parse, yyvsp[-2].parse ); }
break;
case 56:
#line 305 "jamgram.y"
{ yyval.parse = plist( yyvsp[0].string ); }
#line 308 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; yymode( SCAN_NORMAL ); }
break;
case 57:
#line 307 "jamgram.y"
{ yyval.parse = prule( yyvsp[-2].string, yyvsp[-1].parse ); }
#line 312 "jamgram.y"
{ yyval.parse = pnull(); yymode( SCAN_PUNCT ); }
break;
case 58:
#line 317 "jamgram.y"
{ yyval.number = 0; }
#line 314 "jamgram.y"
{ yyval.parse = pappend( yyvsp[-1].parse, yyvsp[0].parse ); }
break;
case 59:
#line 319 "jamgram.y"
{ yyval.number = yyvsp[-1].number | yyvsp[0].number; }
#line 318 "jamgram.y"
{ yyval.parse = plist( yyvsp[0].string ); }
break;
case 60:
#line 323 "jamgram.y"
{ yyval.number = EXEC_UPDATED; }
#line 319 "jamgram.y"
{ yymode( SCAN_NORMAL ); }
break;
case 61:
#line 325 "jamgram.y"
{ yyval.number = EXEC_TOGETHER; }
#line 320 "jamgram.y"
{ yyval.parse = yyvsp[-1].parse; }
break;
case 62:
#line 327 "jamgram.y"
{ yyval.number = EXEC_IGNORE; }
#line 329 "jamgram.y"
{ yyval.parse = prule( yyvsp[-1].string, yyvsp[0].parse ); }
break;
case 63:
#line 329 "jamgram.y"
{ yyval.number = EXEC_QUIETLY; }
#line 331 "jamgram.y"
{ yyval.parse = pon( yyvsp[-2].parse, prule( yyvsp[-1].string, yyvsp[0].parse ) ); }
break;
case 64:
#line 331 "jamgram.y"
{ yyval.number = EXEC_PIECEMEAL; }
#line 333 "jamgram.y"
{ yyval.parse = pon( yyvsp[-2].parse, yyvsp[0].parse ); }
break;
case 65:
#line 333 "jamgram.y"
{ yyval.number = EXEC_EXISTING; }
#line 343 "jamgram.y"
{ yyval.number = 0; }
break;
case 66:
#line 342 "jamgram.y"
{ yyval.parse = pnull(); }
#line 345 "jamgram.y"
{ yyval.number = yyvsp[-1].number | yyvsp[0].number; }
break;
case 67:
#line 344 "jamgram.y"
#line 349 "jamgram.y"
{ yyval.number = EXEC_UPDATED; }
break;
case 68:
#line 351 "jamgram.y"
{ yyval.number = EXEC_TOGETHER; }
break;
case 69:
#line 353 "jamgram.y"
{ yyval.number = EXEC_IGNORE; }
break;
case 70:
#line 355 "jamgram.y"
{ yyval.number = EXEC_QUIETLY; }
break;
case 71:
#line 357 "jamgram.y"
{ yyval.number = EXEC_PIECEMEAL; }
break;
case 72:
#line 359 "jamgram.y"
{ yyval.number = EXEC_EXISTING; }
break;
case 73:
#line 368 "jamgram.y"
{ yyval.parse = pnull(); }
break;
case 74:
#line 370 "jamgram.y"
{ yyval.parse = yyvsp[0].parse; }
break;
#line 821 "y.tab.c"
#line 867 "y.tab.c"
}
yyssp -= yym;
yystate = *yyssp;

View File

@@ -4,44 +4,46 @@
#define _BANG 257
#define _BANG_EQUALS 258
#define _AMPERAMPER 259
#define _LPAREN 260
#define _RPAREN 261
#define _PLUS_EQUALS 262
#define _COLON 263
#define _SEMIC 264
#define _LANGLE 265
#define _LANGLE_EQUALS 266
#define _EQUALS 267
#define _RANGLE 268
#define _RANGLE_EQUALS 269
#define _QUESTION_EQUALS 270
#define _LBRACKET 271
#define _RBRACKET 272
#define ACTIONS 273
#define BIND 274
#define CASE 275
#define DEFAULT 276
#define ELSE 277
#define EXISTING 278
#define FOR 279
#define IF 280
#define IGNORE 281
#define IN 282
#define INCLUDE 283
#define LOCAL 284
#define MODULE 285
#define ON 286
#define PIECEMEAL 287
#define QUIETLY 288
#define RETURN 289
#define RULE 290
#define SWITCH 291
#define TOGETHER 292
#define UPDATED 293
#define WHILE 294
#define _LBRACE 295
#define _BARBAR 296
#define _RBRACE 297
#define ARG 298
#define STRING 299
#define _AMPER 259
#define _AMPERAMPER 260
#define _LPAREN 261
#define _RPAREN 262
#define _PLUS_EQUALS 263
#define _COLON 264
#define _SEMIC 265
#define _LANGLE 266
#define _LANGLE_EQUALS 267
#define _EQUALS 268
#define _RANGLE 269
#define _RANGLE_EQUALS 270
#define _QUESTION_EQUALS 271
#define _LBRACKET 272
#define _RBRACKET 273
#define ACTIONS 274
#define BIND 275
#define CASE 276
#define DEFAULT 277
#define ELSE 278
#define EXISTING 279
#define FOR 280
#define IF 281
#define IGNORE 282
#define IN 283
#define INCLUDE 284
#define LOCAL 285
#define MODULE 286
#define ON 287
#define PIECEMEAL 288
#define QUIETLY 289
#define RETURN 290
#define RULE 291
#define SWITCH 292
#define TOGETHER 293
#define UPDATED 294
#define WHILE 295
#define _LBRACE 296
#define _BAR 297
#define _BARBAR 298
#define _RBRACE 299
#define ARG 300
#define STRING 301

View File

@@ -1,5 +1,6 @@
%token _BANG
%token _BANG_EQUALS
%token _AMPER
%token _AMPERAMPER
%token _LPAREN
%token _RPAREN
@@ -37,6 +38,7 @@
%token UPDATED
%token WHILE
%token _LBRACE
%token _BAR
%token _BARBAR
%token _RBRACE
/*
@@ -86,10 +88,13 @@
%token ARG STRING
%left _BARBAR
%left _AMPERAMPER
%left _BARBAR _BAR
%left _AMPERAMPER _AMPER
%left _EQUALS _BANG_EQUALS IN
%left _LANGLE _LANGLE_EQUALS _RANGLE _RANGLE_EQUALS
%left _BANG
%{
#include "jam.h"
@@ -104,6 +109,8 @@
# define S0 (char *)0
# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
# define pshortcircuiteval( c,l,r ) parse_make( compile_eval,l,P0,r,S0,S0,c )
# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
@@ -112,6 +119,7 @@
# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
@@ -122,7 +130,6 @@
# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
# define pcnode( c,l,r ) parse_make( F0,l,r,P0,S0,S0,c )
# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
%}
@@ -196,16 +203,18 @@ rule : _LBRACE block _RBRACE
{ $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
| SWITCH list _LBRACE cases _RBRACE
{ $$.parse = pswitch( $2.parse, $4.parse ); }
| IF cond _LBRACE block _RBRACE
| IF expr _LBRACE block _RBRACE
{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
| MODULE list _LBRACE block _RBRACE
{ $$.parse = pmodule( $2.parse, $4.parse ); }
| WHILE cond _LBRACE block _RBRACE
| WHILE expr _LBRACE block _RBRACE
{ $$.parse = pwhile( $2.parse, $4.parse ); }
| IF cond _LBRACE block _RBRACE ELSE rule
| IF expr _LBRACE block _RBRACE ELSE rule
{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
| local_opt RULE ARG arglist_opt rule
| local_opt RULE ARG arglist_opt rule
{ $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
| ON arg rule
{ $$.parse = pon( $2.parse, $3.parse ); }
| ACTIONS eflags ARG bindlist _LBRACE
{ yymode( SCAN_STRING ); }
STRING
@@ -229,35 +238,39 @@ assign : _EQUALS
;
/*
* cond - a conditional for 'if'
* expr - an expression for if
*/
cond : arg
{ $$.parse = pcnode( COND_EXISTS, $1.parse, pnull() ); }
expr : arg
{ $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
| arg _EQUALS arg
{ $$.parse = pcnode( COND_EQUALS, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
| arg _BANG_EQUALS arg
{ $$.parse = pcnode( COND_NOTEQ, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
| arg _LANGLE arg
{ $$.parse = pcnode( COND_LESS, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
| arg _LANGLE_EQUALS arg
{ $$.parse = pcnode( COND_LESSEQ, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
| arg _RANGLE arg
{ $$.parse = pcnode( COND_MORE, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
| arg _RANGLE_EQUALS arg
{ $$.parse = pcnode( COND_MOREEQ, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
| expr _AMPER expr
{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
| expr _AMPERAMPER expr
{ $$.parse = pshortcircuiteval( EXPR_AND, $1.parse, $3.parse ); }
| expr _BAR expr
{ $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
| expr _BARBAR expr
{ $$.parse = pshortcircuiteval( EXPR_OR, $1.parse, $3.parse ); }
| arg IN list
{ $$.parse = pcnode( COND_IN, $1.parse, $3.parse ); }
| _BANG cond
{ $$.parse = pcnode( COND_NOT, $2.parse, P0 ); }
| cond _AMPERAMPER cond
{ $$.parse = pcnode( COND_AND, $1.parse, $3.parse ); }
| cond _BARBAR cond
{ $$.parse = pcnode( COND_OR, $1.parse, $3.parse ); }
| _LPAREN cond _RPAREN
{ $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
| _BANG expr
{ $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
| _LPAREN expr _RPAREN
{ $$.parse = $2.parse; }
;
/*
* cases - action elements inside a 'switch'
* case - a single action element inside a 'switch'
@@ -303,8 +316,21 @@ listp : /* empty */
arg : ARG
{ $$.parse = plist( $1.string ); }
| _LBRACKET ARG lol _RBRACKET
{ $$.parse = prule( $2.string, $3.parse ); }
| _LBRACKET { yymode( SCAN_NORMAL ); } func _RBRACKET
{ $$.parse = $3.parse; }
;
/*
* func - a function call (inside [])
* This needs to be split cleanly out of 'rule'
*/
func : ARG lol
{ $$.parse = prule( $1.string, $2.parse ); }
| ON arg ARG lol
{ $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
| ON arg RETURN list
{ $$.parse = pon( $2.parse, $4.parse ); }
;

View File

@@ -45,10 +45,13 @@
%token ARG STRING
%left `||`
%left `&&`
%left `||` `|`
%left `&&` `&`
%left `=` `!=` `in`
%left `<` `<=` `>` `>=`
%left `!`
%{
#include "jam.h"
@@ -63,6 +66,8 @@
# define S0 (char *)0
# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
# define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
# define pshortcircuiteval( c,l,r ) parse_make( compile_eval,l,P0,r,S0,S0,c )
# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
@@ -71,6 +76,7 @@
# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
# define pon( l,r ) parse_make( compile_on,l,r,P0,S0,S0,0 )
# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
@@ -81,7 +87,6 @@
# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
# define pcnode( c,l,r ) parse_make( F0,l,r,P0,S0,S0,c )
# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
%}
@@ -155,16 +160,18 @@ rule : `{` block `}`
{ $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
| `switch` list `{` cases `}`
{ $$.parse = pswitch( $2.parse, $4.parse ); }
| `if` cond `{` block `}`
| `if` expr `{` block `}`
{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
| `module` list `{` block `}`
{ $$.parse = pmodule( $2.parse, $4.parse ); }
| `while` cond `{` block `}`
| `while` expr `{` block `}`
{ $$.parse = pwhile( $2.parse, $4.parse ); }
| `if` cond `{` block `}` `else` rule
| `if` expr `{` block `}` `else` rule
{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
| local_opt `rule` ARG arglist_opt rule
| local_opt `rule` ARG arglist_opt rule
{ $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
| `on` arg rule
{ $$.parse = pon( $2.parse, $3.parse ); }
| `actions` eflags ARG bindlist `{`
{ yymode( SCAN_STRING ); }
STRING
@@ -188,35 +195,39 @@ assign : `=`
;
/*
* cond - a conditional for 'if'
* expr - an expression for if
*/
cond : arg
{ $$.parse = pcnode( COND_EXISTS, $1.parse, pnull() ); }
expr : arg
{ $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
| arg `=` arg
{ $$.parse = pcnode( COND_EQUALS, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
| arg `!=` arg
{ $$.parse = pcnode( COND_NOTEQ, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
| arg `<` arg
{ $$.parse = pcnode( COND_LESS, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
| arg `<=` arg
{ $$.parse = pcnode( COND_LESSEQ, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
| arg `>` arg
{ $$.parse = pcnode( COND_MORE, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
| arg `>=` arg
{ $$.parse = pcnode( COND_MOREEQ, $1.parse, $3.parse ); }
{ $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
| expr `&` expr
{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
| expr `&&` expr
{ $$.parse = pshortcircuiteval( EXPR_AND, $1.parse, $3.parse ); }
| expr `|` expr
{ $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
| expr `||` expr
{ $$.parse = pshortcircuiteval( EXPR_OR, $1.parse, $3.parse ); }
| arg `in` list
{ $$.parse = pcnode( COND_IN, $1.parse, $3.parse ); }
| `!` cond
{ $$.parse = pcnode( COND_NOT, $2.parse, P0 ); }
| cond `&&` cond
{ $$.parse = pcnode( COND_AND, $1.parse, $3.parse ); }
| cond `||` cond
{ $$.parse = pcnode( COND_OR, $1.parse, $3.parse ); }
| `(` cond `)`
{ $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
| `!` expr
{ $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
| `(` expr `)`
{ $$.parse = $2.parse; }
;
/*
* cases - action elements inside a 'switch'
* case - a single action element inside a 'switch'
@@ -262,8 +273,21 @@ listp : /* empty */
arg : ARG
{ $$.parse = plist( $1.string ); }
| `[` ARG lol `]`
{ $$.parse = prule( $2.string, $3.parse ); }
| `[` { yymode( SCAN_NORMAL ); } func `]`
{ $$.parse = $3.parse; }
;
/*
* func - a function call (inside [])
* This needs to be split cleanly out of 'rule'
*/
func : ARG lol
{ $$.parse = prule( $1.string, $2.parse ); }
| `on` arg ARG lol
{ $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
| `on` arg `return` list
{ $$.parse = pon( $2.parse, $4.parse ); }
;

View File

@@ -1,5 +1,6 @@
{ "!", _BANG },
{ "!=", _BANG_EQUALS },
{ "&", _AMPER },
{ "&&", _AMPERAMPER },
{ "(", _LPAREN },
{ ")", _RPAREN },
@@ -37,5 +38,6 @@
{ "updated", UPDATED },
{ "while", WHILE },
{ "{", _LBRACE },
{ "|", _BAR },
{ "||", _BARBAR },
{ "}", _RBRACE },

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/

View File

@@ -2,4 +2,7 @@ call c:\tools\msvc6\vc98\bin\vcvars32.bat
set VISUALC=c:\tools\msvc6\vc98
set JAM_TOOLSET=VISUALC
rm -rf bin.ntx86/jam.exe bin.ntx86/*.obj bin.ntx86/*.lib
set BOOST_ROOT=
set BOOST_BUILD_PATH=
set JAMBASE=
nmake -fbuilds/win32-visualc.mk JAMBASE= BOOST_ROOT= BOOST_BUILD_PATH= CFLAGS="/GZ /Zi /MLd -DNT" CCFLAGS="/GZ /Zi /MLd" LINKLIBS="c:\tools\msvc6\vc98\lib\advapi32.lib c:\tools\msvc6\vc98\lib\oldnames.lib c:\tools\msvc6\vc98\lib\gdi32.lib c:\tools\msvc6\vc98\lib\user32.lib c:\tools\msvc6\vc98\lib\kernel32.lib" LINKFLAGS="/DEBUG" YACC="byacc" YACCFILES="y.tab" YACCFLAGS=-vd %*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -13,7 +13,7 @@
*/
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# ifdef OS_MAC
@@ -24,15 +24,15 @@
*
* External routines:
*
* file_parse() - split a file name into dir/base/suffix/member
* file_build() - build a filename given dir/base/suffix/member
* file_parent() - make a FILENAME point to its parent dir
* path_parse() - split a file name into dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
* path_parent() - make a PATHNAME point to its parent dir
*
* File_parse() and file_build() just manipuate a string and a structure;
* File_parse() and path_build() just manipuate a string and a structure;
* they do not make system calls.
*
* 04/08/94 (seiwald) - Coherent/386 support added.
* 12/26/93 (seiwald) - handle dir/.suffix properly in file_build()
* 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
* 12/19/94 (mikem) - solaris string table insanity support
* 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
* 02/14/95 (seiwald) - parse and build /xxx properly
@@ -44,16 +44,19 @@
* 05/03/96 (seiwald) - split from filent.c, fileunix.c
* 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
* don't include the archive member name.
* 01/10/01 (seiwald) - path_parse now strips the trailing : from the
* directory name, unless the directory name is all
* :'s, so that $(d:P) works.
*/
/*
* file_parse() - split a file name into dir/base/suffix/member
* path_parse() - split a file name into dir/base/suffix/member
*/
void
file_parse(
path_parse(
char *file,
FILENAME *f )
PATHNAME *f )
{
char *p, *q;
char *end;
@@ -71,16 +74,19 @@ file_parse(
/* Look for dir: */
p = strrchr( file, DELIM );
if( p )
if( p = strrchr( file, DELIM ) )
{
f->f_dir.ptr = file;
f->f_dir.len = p - file;
/* Dir of : is : */
f->f_dir.len++;
file = p + 1;
/* All :'s? Include last : as part of directory name */
while( p > f->f_dir.ptr && *--p == DELIM )
;
if( p == f->f_dir.ptr )
f->f_dir.len++;
}
end = file + strlen( file );
@@ -117,7 +123,7 @@ file_parse(
}
/*
* file_build() - build a filename given dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
*/
# define DIR_EMPTY 0 /* "" */
@@ -159,8 +165,8 @@ file_flags(
}
void
file_build(
FILENAME *f,
path_build(
PATHNAME *f,
string* file,
int binding )
{
@@ -237,11 +243,11 @@ file_build(
}
/*
* file_parent() - make a FILENAME point to its parent dir
* path_parent() - make a PATHNAME point to its parent dir
*/
void
file_parent( FILENAME *f )
path_parent( PATHNAME *f )
{
/* just set everything else to nothing */

57
src/engine/pathsys.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
/*
* pathsys.h - PATHNAME struct
*/
/*
* PATHNAME - a name of a file, broken into <grist>dir/base/suffix(member)
*
* <grist> is salt to distinguish between targets that otherwise would
* have the same name: it never appears in the bound name of a target.
* (member) is an archive member name: the syntax is arbitrary, but must
* agree in path_parse(), path_build() and the Jambase.
*
* On VMS, we keep track of whether the original path was a directory
* (without a file), so that $(VAR:D) can climb to the parent.
*/
#ifndef PATHSYS_VP_20020211_H
# define PATHSYS_VP_20020211_H
#include "strings.h"
typedef struct _pathname PATHNAME;
typedef struct _pathpart PATHPART;
struct _pathpart {
char *ptr;
int len;
};
struct _pathname {
PATHPART part[6];
# ifdef OS_VMS
int parent;
# endif
# define f_grist part[0]
# define f_root part[1]
# define f_dir part[2]
# define f_base part[3]
# define f_suffix part[4]
# define f_member part[5]
} ;
void path_build( PATHNAME *f, string *file, int binding );
void path_build1( PATHNAME *f, string *file );
void path_parse( char *file, PATHNAME *f );
void path_parent( PATHNAME *f );
#endif // PATHSYS_VP_20020211_H

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -13,7 +13,7 @@
*/
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# include "strings.h"
# ifdef USE_PATHUNIX
@@ -23,15 +23,15 @@
*
* External routines:
*
* file_parse() - split a file name into dir/base/suffix/member
* file_build() - build a filename given dir/base/suffix/member
* file_parent() - make a FILENAME point to its parent dir
* path_parse() - split a file name into dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
* path_parent() - make a PATHNAME point to its parent dir
*
* File_parse() and file_build() just manipuate a string and a structure;
* File_parse() and path_build() just manipuate a string and a structure;
* they do not make system calls.
*
* 04/08/94 (seiwald) - Coherent/386 support added.
* 12/26/93 (seiwald) - handle dir/.suffix properly in file_build()
* 12/26/93 (seiwald) - handle dir/.suffix properly in path_build()
* 12/19/94 (mikem) - solaris string table insanity support
* 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
* 02/14/95 (seiwald) - parse and build /xxx properly
@@ -43,16 +43,17 @@
* 05/03/96 (seiwald) - split from filent.c, fileunix.c
* 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
* don't include the archive member name.
* 01/13/01 (seiwald) - turn on \ handling on UNIX, on by accident
*/
/*
* file_parse() - split a file name into dir/base/suffix/member
* path_parse() - split a file name into dir/base/suffix/member
*/
void
file_parse(
path_parse(
char *file,
FILENAME *f )
PATHNAME *f )
{
char *p, *q;
char *end;
@@ -72,14 +73,12 @@ file_parse(
p = strrchr( file, '/' );
# ifndef UNIX
# ifndef AMIGA
# if PATH_DELIM == '\\'
/* On NT, look for dir\ as well */
{
char *p1 = strrchr( file, '\\' );
p = p1 > p ? p1 : p;
}
# endif
# endif
if( p )
@@ -92,13 +91,11 @@ file_parse(
if( !f->f_dir.len )
f->f_dir.len = 1;
# ifndef UNIX
# ifndef AMIGA
# if PATH_DELIM == '\\'
/* Special case for D:/ - dirname is D:/, not "D:" */
if( f->f_dir.len == 2 && file[1] == ':' )
f->f_dir.len = 3;
# endif
# endif
file = p + 1;
@@ -138,12 +135,12 @@ file_parse(
}
/*
* file_build() - build a filename given dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
*/
void
file_build(
FILENAME *f,
path_build(
PATHNAME *f,
string *file,
int binding )
{
@@ -210,11 +207,11 @@ file_build(
}
/*
* file_parent() - make a FILENAME point to its parent dir
* path_parent() - make a PATHNAME point to its parent dir
*/
void
file_parent( FILENAME *f )
path_parent( PATHNAME *f )
{
/* just set everything else to nothing */

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -13,7 +13,7 @@
*/
# include "jam.h"
# include "filesys.h"
# include "pathsys.h"
# ifdef OS_VMS
@@ -24,11 +24,11 @@
*
* External routines:
*
* file_parse() - split a file name into dir/base/suffix/member
* file_build() - build a filename given dir/base/suffix/member
* file_parent() - make a FILENAME point to its parent dir
* path_parse() - split a file name into dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
* path_parent() - make a PATHNAME point to its parent dir
*
* File_parse() and file_build() just manipuate a string and a structure;
* File_parse() and path_build() just manipuate a string and a structure;
* they do not make system calls.
*
* WARNING! This file contains voodoo logic, as black magic is
@@ -40,13 +40,13 @@
*/
/*
* file_parse() - split a file name into dir/base/suffix/member
* path_parse() - split a file name into dir/base/suffix/member
*/
void
file_parse(
path_parse(
char *file,
FILENAME *f )
PATHNAME *f )
{
char *p, *q;
char *end;
@@ -88,7 +88,7 @@ file_parse(
p = 0;
q = file;
while( q = memchr( q, '.', end - q ) )
while( q = (char *)memchr( q, '.', end - q ) )
p = q++;
if( p )
@@ -233,12 +233,12 @@ dir_flags(
}
/*
* file_build() - build a filename given dir/base/suffix/member
* path_build() - build a filename given dir/base/suffix/member
*/
void
file_build(
FILENAME *f,
path_build(
PATHNAME *f,
string *file,
int binding )
{
@@ -393,11 +393,11 @@ file_build(
}
/*
* file_parent() - make a FILENAME point to its parent dir
* path_parent() - make a PATHNAME point to its parent dir
*/
void
file_parent( FILENAME *f )
path_parent( PATHNAME *f )
{
if( f->f_base.len )
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -251,10 +251,9 @@ yylex()
else
{
char *b = buf;
int inquote = 0;
int literal = 0;
int hasquote = 0;
struct keyword *k;
int inquote = 0;
int notkeyword;
/* Eat white space */
@@ -281,22 +280,44 @@ yylex()
yylval.file = incp->fname;
yylval.line = incp->line;
/* While scanning the word, disqualify it for (expensive) */
/* keyword lookup when we can: $anything, "anything", \anything */
notkeyword = c == '$';
/* look for white space to delimit word */
/* "'s get stripped but preserve white space */
/* \ protects next character */
while( b < buf + sizeof( buf ) )
while(
c != EOF &&
b < buf + sizeof( buf ) &&
( inquote || !isspace( c ) ) )
{
if( literal )
*b++ = c, literal = 0;
else if( c == '\\' )
literal++;
else if( c == '"' )
inquote = !inquote, hasquote++;
else
if( c == '"' )
{
/* begin or end " */
inquote = !inquote;
notkeyword = 1;
}
else if( c != '\\' )
{
/* normal char */
*b++ = c;
if( ( c = yychar() ) == EOF || !inquote && isspace( c ) )
}
else if( ( c = yychar()) != EOF )
{
/* \c */
*b++ = c;
notkeyword = 1;
}
else
{
/* \EOF */
break;
}
c = yychar();
}
/* Check obvious errors. */
@@ -319,15 +340,13 @@ yylex()
yyprev();
/* scan token table */
/* don't scan if it's "anything", $anything, */
/* or an alphabetic when were looking for punctuation */
/* don't scan if it's obviously not a keyword or if its */
/* an alphabetic when were looking for punctuation */
*b = 0;
yylval.type = ARG;
if( !hasquote &&
*buf != '$' &&
!( isalpha( *buf ) && scanmode == SCAN_PUNCT ) )
if( !notkeyword && !( isalpha( *buf ) && scanmode == SCAN_PUNCT ) )
{
for( k = keywords; k->word; k++ )
if( *buf == *k->word && !strcmp( k->word, buf ) )

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -16,7 +16,7 @@
# include "lists.h"
# include "search.h"
# include "timestamp.h"
# include "filesys.h"
# include "pathsys.h"
# include "variable.h"
# include "newstr.h"
# include "compile.h"
@@ -72,7 +72,7 @@ search(
char *target,
time_t *time )
{
FILENAME f[1];
PATHNAME f[1];
LIST *varlist;
string buf[1];
int found = 0;
@@ -81,7 +81,7 @@ search(
string_new( buf );
/* Parse the filename */
file_parse( target, f );
path_parse( target, f );
f->f_grist.ptr = 0;
f->f_grist.len = 0;
@@ -91,7 +91,7 @@ search(
f->f_root.ptr = varlist->string;
f->f_root.len = strlen( varlist->string );
file_build( f, buf, 1 );
path_build( f, buf, 1 );
if( DEBUG_SEARCH )
printf( "locate %s: %s\n", target, buf->value );
@@ -107,7 +107,7 @@ search(
f->f_root.len = strlen( varlist->string );
string_truncate( buf, 0 );
file_build( f, buf, 1 );
path_build( f, buf, 1 );
if( DEBUG_SEARCH )
printf( "search %s: %s\n", target, buf->value );
@@ -134,7 +134,7 @@ search(
f->f_root.len = 0;
string_truncate( buf, 0 );
file_build( f, buf, 1 );
path_build( f, buf, 1 );
if( DEBUG_SEARCH )
printf( "search %s: %s\n", target, buf->value );

View File

@@ -1,5 +1,5 @@
/*
* Copyright 1993, 1995 Christopher Seiwald.
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
@@ -15,6 +15,7 @@
# include "jam.h"
# include "hash.h"
# include "filesys.h"
# include "pathsys.h"
# include "timestamp.h"
# include "newstr.h"
# include "strings.h"
@@ -49,7 +50,7 @@ struct _binding {
} ;
static struct hash *bindhash = 0;
static void time_enter( char *target, int found, time_t time );
static void time_enter( void *, char *, int , time_t );
static char *time_progress[] =
{
@@ -70,7 +71,7 @@ timestamp(
char *target,
time_t *time )
{
FILENAME f1, f2;
PATHNAME f1, f2;
BINDING binding, *b = &binding;
string buf[1];
@@ -108,7 +109,7 @@ timestamp(
/* Not found - have to scan for it */
file_parse( target, &f1 );
path_parse( target, &f1 );
/* Scan directory if not already done so */
@@ -117,8 +118,8 @@ timestamp(
f2 = f1;
f2.f_grist.len = 0;
file_parent( &f2 );
file_build( &f2, buf, 0 );
path_parent( &f2 );
path_build( &f2, buf, 0 );
b->name = buf->value;
b->time = b->flags = 0;
@@ -129,7 +130,7 @@ timestamp(
if( !( b->flags & BIND_SCANNED ) )
{
file_dirscan( buf->value, time_enter );
file_dirscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
}
}
@@ -144,7 +145,7 @@ timestamp(
f2.f_grist.len = 0;
f2.f_member.len = 0;
string_truncate( buf, 0 );
file_build( &f2, buf, 0 );
path_build( &f2, buf, 0 );
b->name = buf->value;
b->time = b->flags = 0;
@@ -155,7 +156,7 @@ timestamp(
if( !( b->flags & BIND_SCANNED ) )
{
file_archscan( buf->value, time_enter );
file_archscan( buf->value, time_enter, bindhash );
b->flags |= BIND_SCANNED;
}
}
@@ -179,11 +180,13 @@ timestamp(
static void
time_enter(
void *closure,
char *target,
int found,
time_t time )
{
BINDING binding, *b = &binding;
struct hash *bindhash = (struct hash *)closure;
# ifdef DOWNSHIFT_PATHS
char path[ MAXJPATH ];