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:
@@ -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). $(<) and $(>) 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). $(<) and $(>) 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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ; }
|
||||
|
||||
@@ -1445,6 +1445,12 @@ RmTemps Rule
|
||||
<BR>
|
||||
Last updated: Dec 31, 2000
|
||||
<BR>
|
||||
<<<<<<< variant A
|
||||
$Id$
|
||||
>>>>>>> variant B
|
||||
$Id$
|
||||
####### Ancestor
|
||||
$Id$
|
||||
======= end
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
594
src/engine/builtins.c
Normal 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
31
src/engine/builtins.h
Normal 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
|
||||
@@ -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
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
25
src/engine/frames.c
Normal 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 );
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ); }
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -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 ); }
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{ "!", _BANG },
|
||||
{ "!=", _BANG_EQUALS },
|
||||
{ "&", _AMPER },
|
||||
{ "&&", _AMPERAMPER },
|
||||
{ "(", _LPAREN },
|
||||
{ ")", _RPAREN },
|
||||
@@ -37,5 +38,6 @@
|
||||
{ "updated", UPDATED },
|
||||
{ "while", WHILE },
|
||||
{ "{", _LBRACE },
|
||||
{ "|", _BAR },
|
||||
{ "||", _BARBAR },
|
||||
{ "}", _RBRACE },
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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 %*
|
||||
|
||||
@@ -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
57
src/engine/pathsys.h
Normal 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
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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 ) )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
Reference in New Issue
Block a user