Initial Import from SVN

This commit is contained in:
Matt Jenkins
2014-04-09 14:27:18 +01:00
parent 8976e834c4
commit 895f96d2f7
3153 changed files with 748589 additions and 0 deletions

28
src/cmd/m4/Makefile Normal file
View File

@@ -0,0 +1,28 @@
# @(#)Makefile 1.0 (2.11BSD GTE) 4/5/94
DEFS= -DEXTENDED -I.
CFLAGS= -O ${DEFS}
DESTDIR=
SEPFLAG= -i
SRCS= eval.c expr.c look.c main.c misc.c
OBJS= eval.o expr.o look.o main.o misc.o
all: m4 tags
m4: ${OBJS}
cc ${SEPFLAG} -o m4 ${OBJS}
install: all
install -s -m 755 m4 ${DESTDIR}/usr/bin/m4
lint:
lint -hax ${DEFS} ${SRCS}
tags:
ctags -t *.h ${SRCS}
clean:
-rm -f *.o m4 core
depend: ${SRCS}
mkdep -p ${CFLAGS} ${SRCS}

64
src/cmd/m4/NOTES Normal file
View File

@@ -0,0 +1,64 @@
m4 - macro processor
PD m4 is based on the macro tool distributed with the software
tools (VOS) package, and described in the "SOFTWARE TOOLS" and
"SOFTWARE TOOLS IN PASCAL" books. It has been expanded to include
most of the command set of SysV m4, the standard UN*X macro processor.
Since both PD m4 and UN*X m4 are based on SOFTWARE TOOLS macro,
there may be certain implementation similarities between
the two. The PD m4 was produced without ANY references to m4
sources.
written by: Ozan S. Yigit
References:
Software Tools distribution: macro
Kernighan, Brian W. and P. J. Plauger, SOFTWARE
TOOLS IN PASCAL, Addison-Wesley, Mass. 1981
Kernighan, Brian W. and P. J. Plauger, SOFTWARE
TOOLS, Addison-Wesley, Mass. 1976
Kernighan, Brian W. and Dennis M. Ritchie,
THE M4 MACRO PROCESSOR, Unix Programmer's Manual,
Seventh Edition, Vol. 2, Bell Telephone Labs, 1979
System V man page for M4
Implementation Notes:
[1] PD m4 uses a different (and simpler) stack mechanism than the one
described in Software Tools and Software Tools in Pascal books.
The triple stack thing is replaced with a single stack containing
the call frames and the arguments. Each frame is back-linked to a
previous stack frame, which enables us to rewind the stack after
each nested call is completed. Each argument is a character pointer
to the beginning of the argument string within the string space.
The only exceptions to this are (*) arg 0 and arg 1, which are
the macro definition and macro name strings, stored dynamically
for the hash table.
. .
| . | <-- sp | . |
+-------+ +-----+
| arg 3 ------------------------------->| str |
+-------+ | . |
| arg 2 --------------+ .
+-------+ |
* | | |
+-------+ | +-----+
| plev | <-- fp +---------------->| str |
+-------+ | . |
| type | .
+-------+
| prcf -----------+ plev: paren level
+-------+ | type: call type
| . | | prcf: prev. call frame
. |
+-------+ |
| <----------+
+-------+

40
src/cmd/m4/TEST/ack.m4 Normal file
View File

@@ -0,0 +1,40 @@
#
# Copyright (c) 1989, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Ozan Yigit.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)ack.m4 8.1 (Berkeley) 6/6/93
#
define(ack, `ifelse($1,0,incr($2),$2,0,`ack(DECR($1),1)',
`ack(DECR($1), ack($1,DECR($2)))')')

45
src/cmd/m4/TEST/hanoi.m4 Normal file
View File

@@ -0,0 +1,45 @@
#
# Copyright (c) 1989, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Ozan Yigit.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)hanoi.m4 8.1 (Berkeley) 6/6/93
#
define(hanoi, `trans(A, B, C, $1)')
define(moved,`move disk from $1 to $2
')
define(trans, `ifelse($4,1,`moved($1,$2)',
`trans($1,$3,$2,DECR($4))moved($1,$2)trans($3,$2,$1,DECR($4))')')

55
src/cmd/m4/TEST/hash.m4 Normal file
View File

@@ -0,0 +1,55 @@
#
# Copyright (c) 1989, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Ozan Yigit.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)hash.m4 8.1 (Berkeley) 6/6/93
#
dnl This probably will not run on any m4 that cannot
dnl handle char constants in eval.
dnl
changequote(<,>) define(HASHVAL,99) dnl
define(hash,<eval(str(substr($1,1),0)%HASHVAL)>) dnl
define(str,
<ifelse($1,",$2,
<str(substr(<$1>,1),<eval($2+'substr($1,0,1)')>)>)
>) dnl
define(KEYWORD,<$1,hash($1),>) dnl
define(TSTART,
<struct prehash {
char *keyword;
int hashval;
} keytab[] = {>) dnl
define(TEND,< "",0
};>) dnl

45
src/cmd/m4/TEST/sqroot.m4 Normal file
View File

@@ -0,0 +1,45 @@
#
# Copyright (c) 1989, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Ozan Yigit.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)sqroot.m4 8.1 (Berkeley) 6/6/93
#
define(square_root,
`ifelse(eval($1<0),1,negative-square-root,
`square_root_aux($1, 1, eval(($1+1)/2))')')
define(square_root_aux,
`ifelse($3, $2, $3,
$3, eval($1/$2), $3,
`square_root_aux($1, $3, eval(($3+($1/$3))/2))')')

45
src/cmd/m4/TEST/string.m4 Normal file
View File

@@ -0,0 +1,45 @@
#
# Copyright (c) 1989, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Ozan Yigit.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)string.m4 8.1 (Berkeley) 6/6/93
#
define(string,`integer $1(len(substr($2,1)))
str($1,substr($2,1),0)
data $1(len(substr($2,1)))/EOS/
')
define(str,`ifelse($2,",,data $1(incr($3))/`LET'substr($2,0,1)/
`str($1,substr($2,1),incr($3))')')

243
src/cmd/m4/TEST/test.m4 Normal file
View File

@@ -0,0 +1,243 @@
#
# Copyright (c) 1989, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Ozan Yigit.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)test.m4 8.1 (Berkeley) 6/6/93
#
# test file for mp (not comprehensive)
#
# v7 m4 does not have `decr'.
#
define(DECR,`eval($1-1)')
#
# include string macros
#
include(string.m4)
#
# create some fortrash strings for an even uglier language
#
string(TEXT, "text")
string(DATA, "data")
string(BEGIN, "begin")
string(END, "end")
string(IF, "if")
string(THEN, "then")
string(ELSE, "else")
string(CASE, "case")
string(REPEAT, "repeat")
string(WHILE, "while")
string(DEFAULT, "default")
string(UNTIL, "until")
string(FUNCTION, "function")
string(PROCEDURE, "procedure")
string(EXTERNAL, "external")
string(FORWARD, "forward")
string(TYPE, "type")
string(VAR, "var")
string(CONST, "const")
string(PROGRAM, "program")
string(INPUT, "input")
string(OUTPUT, "output")
#
divert(2)
diversion #1
divert(3)
diversion #2
divert(4)
diversion #3
divert(5)
diversion #4
divert(0)
define(abc,xxx)
ifdef(`abc',defined,undefined)
#
# v7 m4 does this wrong. The right output is
# this is A vEry lon sEntEnCE
# see m4 documentation for translit.
#
translit(`this is a very long sentence', abcdefg, ABCDEF)
#
# include towers-of-hanoi
#
include(hanoi.m4)
#
# some reasonable set of disks
#
hanoi(6)
#
# include ackermann's function
#
include(ack.m4)
#
# something like (3,3) will blow away un*x m4.
#
ack(2,3)
#
# include a square_root function for fixed nums
#
include(sqroot.m4)
#
# some square roots.
#
square_root(15)
square_root(100)
square_root(-4)
square_root(21372)
#
# some textual material for enjoyment.
#
[taken from the 'Clemson University Computer Newsletter',
September 1981, pp. 6-7]
I am a wizard in the magical Kingdom of Transformation and I
slay dragons for a living. Actually, I am a systems programmer.
One of the problems with systems programming is explaining to
non-computer enthusiasts what that is. All of the terms I use to
describe my job are totally meaningless to them. Usually my response
to questions about my work is to say as little as possible. For
instance, if someone asks what happened at work this week, I say
"Nothing much" and then I change the subject.
With the assistance of my brother, a mechanical engineer, I have devised
an analogy that everyone can understand. The analogy describes the
"Kingdom of Transformation" where travelers wander and are magically
transformed. This kingdom is the computer and the travelers are information.
The purpose of the computer is to change information to a more meaningful
forma. The law of conservation applies here: The computer never creates
and never intentionally destroys data. With no further ado, let us travel
to the Kingdom of Transformation:
In a land far, far away, there is a magical kingdom called the Kingdom of
Transformation. A king rules over this land and employs a Council of
Wizardry. The main purpose of this kingdom is to provide a way for
neighboring kingdoms to transform citizens into more useful citizens. This
is done by allowing the citizens to enter the kingdom at one of its ports
and to travel any of the many routes in the kingdom. They are magically
transformed along the way. The income of the Kingdom of Transformation
comes from the many toll roads within its boundaries.
The Kingdom of Transformation was created when several kingdoms got
together and discovered a mutual need for new talents and abilities for
citizens. They employed CTK, Inc. (Creators of Transformation, Inc.) to
create this kingdom. CTK designed the country, its transportation routes,
and its laws of transformation, and created the major highway system.
Hazards
=======
Because magic is not truly controllable, CTK invariably, but unknowingly,
creates dragons. Dragons are huge fire-breathing beasts which sometimes
injure or kill travelers. Fortunately, they do not travel, but always
remain near their den.
Other hazards also exist which are potentially harmful. As the roads
become older and more weatherbeaten, pot-holes will develop, trees will
fall on travelers, etc. CTK maintenance men are called to fix these
problems.
Wizards
=======
The wizards play a major role in creating and maintaining the kingdom but
get little credit for their work because it is performed secretly. The
wizards do not wan the workers or travelers to learn their incantations
because many laws would be broken and chaos would result.
CTK's grand design is always general enough to be applicable in many
different situations. As a result, it is often difficult to use. The
first duty of the wizards is to tailor the transformation laws so as to be
more beneficial and easier to use in their particular environment.
After creation of the kingdom, a major duty of the wizards is to search for
and kill dragons. If travelers do not return on time or if they return
injured, the ruler of the country contacts the wizards. If the wizards
determine that the injury or death occurred due to the traveler's
negligence, they provide the traveler's country with additional warnings.
If not, they must determine if the cause was a road hazard or a dragon. If
the suspect a road hazard, they call in a CTK maintenance man to locate the
hazard and to eliminate it, as in repairing the pothole in the road. If
they think that cause was a dragon, then they must find and slay it.
The most difficult part of eliminating a dragon is finding it. Sometimes
the wizard magically knows where the dragon's lair it, but often the wizard
must send another traveler along the same route and watch to see where he
disappears. This sounds like a failsafe method for finding dragons (and a
suicide mission for thr traveler) but the second traveler does not always
disappear. Some dragons eat any traveler who comes too close; others are
very picky.
The wizards may call in CTK who designed the highway system and
transformation laws to help devise a way to locate the dragon. CTK also
helps provide the right spell or incantation to slay the dragon. (There is
no general spell to slay dragons; each dragon must be eliminated with a
different spell.)
Because neither CTK nor wizards are perfect, spells to not always work
correctly. At best, nothing happens when the wrong spell is uttered. At
worst, the dragon becomes a much larger dragon or multiplies into several
smaller ones. In either case, new spells must be found.
If all existing dragons are quiet (i.e. have eaten sufficiently), wizards
have time to do other things. They hide in castles and practice spells and
incatations. They also devise shortcuts for travelers and new laws of
transformation.
Changes in the Kingdom
======================
As new transformation kingdoms are created and old ones are maintained,
CTK, Inc. is constantly learning new things. It learns ways to avoid
creating some of the dragons that they have previously created. It also
discovers new and better laws of transformation. As a result, CTK will
periodically create a new grand design which is far better than the old.
The wizards determine when is a good time to implement this new design.
This is when the tourist season is slow or when no important travelers
(VIPs) are to arrive. The kingdom must be closed for the actual
implementation and is leter reopened as a new and better place to go.
A final question you might ask is what happens when the number of tourists
becomes too great for the kingdom to handle in a reasonable period of time
(i.e., the tourist lines at the ports are too long). The Kingdom of
Transformation has three options: (1) shorten the paths that a tourist must
travel, or (2) convince CTK to develop a faster breed of horses so that the
travelers can finish sooner, or (3) annex more territories so that the
kingdom can handle more travelers.
Thus ends the story of the Kingdom of Transformation. I hope this has
explained my job to you: I slay dragons for a living.
#
#should do an automatic undivert..
#

787
src/cmd/m4/eval.c Normal file
View File

@@ -0,0 +1,787 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)eval.c 8.1 (Berkeley) 6/6/93";
#endif
/*
* eval.c
* Facility: m4 macro processor
* by: oz
*/
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "mdef.h"
#include "stdd.h"
#include "extern.h"
#include "pathnames.h"
/*
* eval - evaluate built-in macros.
* argc - number of elements in argv.
* argv - element vector :
* argv[0] = definition of a user
* macro or nil if built-in.
* argv[1] = name of the macro or
* built-in.
* argv[2] = parameters to user-defined
* . macro or built-in.
* .
*
* Note that the minimum value for argc is 3. A call in the form
* of macro-or-builtin() will result in:
* argv[0] = nullstr
* argv[1] = macro-or-builtin
* argv[2] = nullstr
*/
void
eval(argv, argc, td)
register char *argv[];
register int argc;
register int td;
{
register int c, n;
static int sysval = 0;
#ifdef DEBUG
printf("argc = %d\n", argc);
for (n = 0; n < argc; n++)
printf("argv[%d] = %s\n", n, argv[n]);
#endif
/*
* if argc == 3 and argv[2] is null, then we
* have macro-or-builtin() type call. We adjust
* argc to avoid further checking..
*/
if (argc == 3 && !*(argv[2]))
argc--;
switch (td & ~STATIC) {
case DEFITYPE:
if (argc > 2)
dodefine(argv[2], (argc > 3) ? argv[3] : null);
break;
case PUSDTYPE:
if (argc > 2)
dopushdef(argv[2], (argc > 3) ? argv[3] : null);
break;
case DUMPTYPE:
dodump(argv, argc);
break;
case EXPRTYPE:
/*
* doexpr - evaluate arithmetic
* expression
*/
if (argc > 2)
pbnum(expr(argv[2]));
break;
case IFELTYPE:
if (argc > 4)
doifelse(argv, argc);
break;
case IFDFTYPE:
/*
* doifdef - select one of two
* alternatives based on the existence of
* another definition
*/
if (argc > 3) {
if (lookup(argv[2]) != nil)
pbstr(argv[3]);
else if (argc > 4)
pbstr(argv[4]);
}
break;
case LENGTYPE:
/*
* dolen - find the length of the
* argument
*/
if (argc > 2)
pbnum((argc > 2) ? strlen(argv[2]) : 0);
break;
case INCRTYPE:
/*
* doincr - increment the value of the
* argument
*/
if (argc > 2)
pbnum(atoi(argv[2]) + 1);
break;
case DECRTYPE:
/*
* dodecr - decrement the value of the
* argument
*/
if (argc > 2)
pbnum(atoi(argv[2]) - 1);
break;
case SYSCTYPE:
/*
* dosys - execute system command
*/
if (argc > 2)
sysval = system(argv[2]);
break;
case SYSVTYPE:
/*
* dosysval - return value of the last
* system call.
*
*/
pbnum(sysval);
break;
case INCLTYPE:
if (argc > 2)
if (!doincl(argv[2]))
oops("%s: %s", argv[2], strerror(errno));
break;
case SINCTYPE:
if (argc > 2)
(void) doincl(argv[2]);
break;
#ifdef EXTENDED
case PASTTYPE:
if (argc > 2)
if (!dopaste(argv[2]))
oops("%s: %s", argv[2], strerror(errno));
break;
case SPASTYPE:
if (argc > 2)
(void) dopaste(argv[2]);
break;
#endif
case CHNQTYPE:
dochq(argv, argc);
break;
case CHNCTYPE:
dochc(argv, argc);
break;
case SUBSTYPE:
/*
* dosub - select substring
*
*/
if (argc > 3)
dosub(argv, argc);
break;
case SHIFTYPE:
/*
* doshift - push back all arguments
* except the first one (i.e. skip
* argv[2])
*/
if (argc > 3) {
for (n = argc - 1; n > 3; n--) {
putback(rquote);
pbstr(argv[n]);
putback(lquote);
putback(',');
}
putback(rquote);
pbstr(argv[3]);
putback(lquote);
}
break;
case DIVRTYPE:
if (argc > 2 && (n = atoi(argv[2])) != 0)
dodiv(n);
else {
active = stdout;
oindex = 0;
}
break;
case UNDVTYPE:
doundiv(argv, argc);
break;
case DIVNTYPE:
/*
* dodivnum - return the number of
* current output diversion
*/
pbnum(oindex);
break;
case UNDFTYPE:
/*
* doundefine - undefine a previously
* defined macro(s) or m4 keyword(s).
*/
if (argc > 2)
for (n = 2; n < argc; n++)
remhash(argv[n], ALL);
break;
case POPDTYPE:
/*
* dopopdef - remove the topmost
* definitions of macro(s) or m4
* keyword(s).
*/
if (argc > 2)
for (n = 2; n < argc; n++)
remhash(argv[n], TOP);
break;
case MKTMTYPE:
/*
* dotemp - create a temporary file
*/
if (argc > 2)
pbstr(mktemp(argv[2]));
break;
case TRNLTYPE:
/*
* dotranslit - replace all characters in
* the source string that appears in the
* "from" string with the corresponding
* characters in the "to" string.
*/
if (argc > 3) {
char temp[MAXTOK];
if (argc > 4)
map(temp, argv[2], argv[3], argv[4]);
else
map(temp, argv[2], argv[3], null);
pbstr(temp);
}
else if (argc > 2)
pbstr(argv[2]);
break;
case INDXTYPE:
/*
* doindex - find the index of the second
* argument string in the first argument
* string. -1 if not present.
*/
pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
break;
case ERRPTYPE:
/*
* doerrp - print the arguments to stderr
* file
*/
if (argc > 2) {
for (n = 2; n < argc; n++)
fprintf(stderr, "%s ", argv[n]);
fprintf(stderr, "\n");
}
break;
case DNLNTYPE:
/*
* dodnl - eat-up-to and including
* newline
*/
while ((c = gpbc()) != '\n' && c != EOF)
;
break;
case M4WRTYPE:
/*
* dom4wrap - set up for
* wrap-up/wind-down activity
*/
m4wraps = (argc > 2) ? xstrdup(argv[2]) : null;
break;
case EXITTYPE:
/*
* doexit - immediate exit from m4.
*/
exit((argc > 2) ? atoi(argv[2]) : 0);
break;
case DEFNTYPE:
if (argc > 2)
for (n = 2; n < argc; n++)
dodefn(argv[n]);
break;
default:
oops("%s: major botch.", "eval");
break;
}
}
char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef */
/*
* expand - user-defined macro expansion
*/
void
expand(argv, argc)
register char *argv[];
register int argc;
{
register char *t;
register char *p;
register int n;
register int argno;
t = argv[0]; /* defn string as a whole */
p = t;
while (*p)
p++;
p--; /* last character of defn */
while (p > t) {
if (*(p - 1) != ARGFLAG)
putback(*p);
else {
switch (*p) {
case '#':
pbnum(argc - 2);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if ((argno = *p - '0') < argc - 1)
pbstr(argv[argno + 1]);
break;
case '*':
for (n = argc - 1; n > 2; n--) {
pbstr(argv[n]);
putback(',');
}
pbstr(argv[2]);
break;
default:
putback(*p);
putback('$');
break;
}
p--;
}
p--;
}
if (p == t) /* do last character */
putback(*p);
}
/*
* dodefine - install definition in the table
*/
void
dodefine(name, defn)
register char *name;
register char *defn;
{
register ndptr p;
if (!*name)
oops("null definition.");
if (STREQ(name, defn))
oops("%s: recursive definition.", name);
if ((p = lookup(name)) == nil)
p = addent(name);
else if (p->defn != null)
free((char *) p->defn);
if (!*defn)
p->defn = null;
else
p->defn = xstrdup(defn);
p->type = MACRTYPE;
}
/*
* dodefn - push back a quoted definition of
* the given name.
*/
void
dodefn(name)
char *name;
{
register ndptr p;
if ((p = lookup(name)) != nil && p->defn != null) {
putback(rquote);
pbstr(p->defn);
putback(lquote);
}
}
/*
* dopushdef - install a definition in the hash table
* without removing a previous definition. Since
* each new entry is entered in *front* of the
* hash bucket, it hides a previous definition from
* lookup.
*/
void
dopushdef(name, defn)
register char *name;
register char *defn;
{
register ndptr p;
if (!*name)
oops("null definition");
if (STREQ(name, defn))
oops("%s: recursive definition.", name);
p = addent(name);
if (!*defn)
p->defn = null;
else
p->defn = xstrdup(defn);
p->type = MACRTYPE;
}
/*
* dodumpdef - dump the specified definitions in the hash
* table to stderr. If nothing is specified, the entire
* hash table is dumped.
*/
void
dodump(argv, argc)
register char *argv[];
register int argc;
{
register int n;
ndptr p;
if (argc > 2) {
for (n = 2; n < argc; n++)
if ((p = lookup(argv[n])) != nil)
fprintf(stderr, dumpfmt, p->name,
p->defn);
}
else {
for (n = 0; n < HASHSIZE; n++)
for (p = hashtab[n]; p != nil; p = p->nxtptr)
fprintf(stderr, dumpfmt, p->name,
p->defn);
}
}
/*
* doifelse - select one of two alternatives - loop.
*/
void
doifelse(argv, argc)
register char *argv[];
register int argc;
{
cycle {
if (STREQ(argv[2], argv[3]))
pbstr(argv[4]);
else if (argc == 6)
pbstr(argv[5]);
else if (argc > 6) {
argv += 3;
argc -= 3;
continue;
}
break;
}
}
/*
* doinclude - include a given file.
*/
int
doincl(ifile)
char *ifile;
{
if (ilevel + 1 == MAXINP)
oops("too many include files.");
if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) {
ilevel++;
bbase[ilevel] = bufbase = bp;
return (1);
}
else
return (0);
}
#ifdef EXTENDED
/*
* dopaste - include a given file without any
* macro processing.
*/
int
dopaste(pfile)
char *pfile;
{
FILE *pf;
register int c;
if ((pf = fopen(pfile, "r")) != NULL) {
while ((c = getc(pf)) != EOF)
putc(c, active);
(void) fclose(pf);
return (1);
}
else
return (0);
}
#endif
/*
* dochq - change quote characters
*/
void
dochq(argv, argc)
register char *argv[];
register int argc;
{
if (argc > 2) {
if (*argv[2])
lquote = *argv[2];
if (argc > 3) {
if (*argv[3])
rquote = *argv[3];
}
else
rquote = lquote;
}
else {
lquote = LQUOTE;
rquote = RQUOTE;
}
}
/*
* dochc - change comment characters
*/
void
dochc(argv, argc)
register char *argv[];
register int argc;
{
if (argc > 2) {
if (*argv[2])
scommt = *argv[2];
if (argc > 3) {
if (*argv[3])
ecommt = *argv[3];
}
else
ecommt = ECOMMT;
}
else {
scommt = SCOMMT;
ecommt = ECOMMT;
}
}
/*
* dodivert - divert the output to a temporary file
*/
void
dodiv(n)
register int n;
{
if (n < 0 || n >= MAXOUT)
n = 0; /* bitbucket */
if (outfile[n] == NULL) {
m4temp[UNIQUE] = n + '0';
if ((outfile[n] = fopen(m4temp, "w")) == NULL)
oops("%s: cannot divert.", m4temp);
}
oindex = n;
active = outfile[n];
}
/*
* doundivert - undivert a specified output, or all
* other outputs, in numerical order.
*/
void
doundiv(argv, argc)
register char *argv[];
register int argc;
{
register int ind;
register int n;
if (argc > 2) {
for (ind = 2; ind < argc; ind++) {
n = atoi(argv[ind]);
if (n > 0 && n < MAXOUT && outfile[n] != NULL)
getdiv(n);
}
}
else
for (n = 1; n < MAXOUT; n++)
if (outfile[n] != NULL)
getdiv(n);
}
/*
* dosub - select substring
*/
void
dosub(argv, argc)
register char *argv[];
register int argc;
{
register char *ap, *fc, *k;
register int nc;
if (argc < 5)
nc = MAXTOK;
else
#ifdef EXPR
nc = expr(argv[4]);
#else
nc = atoi(argv[4]);
#endif
ap = argv[2]; /* target string */
#ifdef EXPR
fc = ap + expr(argv[3]); /* first char */
#else
fc = ap + atoi(argv[3]); /* first char */
#endif
if (fc >= ap && fc < ap + strlen(ap))
for (k = fc + min(nc, strlen(fc)) - 1; k >= fc; k--)
putback(*k);
}
/*
* map:
* map every character of s1 that is specified in from
* into s3 and replace in s. (source s1 remains untouched)
*
* This is a standard implementation of map(s,from,to) function of ICON
* language. Within mapvec, we replace every character of "from" with
* the corresponding character in "to". If "to" is shorter than "from",
* than the corresponding entries are null, which means that those
* characters dissapear altogether. Furthermore, imagine
* map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
* `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
* ultimately maps to `*'. In order to achieve this effect in an efficient
* manner (i.e. without multiple passes over the destination string), we
* loop over mapvec, starting with the initial source character. if the
* character value (dch) in this location is different than the source
* character (sch), sch becomes dch, once again to index into mapvec, until
* the character value stabilizes (i.e. sch = dch, in other words
* mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
* character, it will stabilize, since mapvec[0] == 0 at all times. At the
* end, we restore mapvec* back to normal where mapvec[n] == n for
* 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
* about 5 times faster than any algorithm that makes multiple passes over
* destination string.
*/
void
map(dest, src, from, to)
register char *dest;
register char *src;
register char *from;
register char *to;
{
register char *tmp;
register char sch, dch;
static char mapvec[128] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127
};
if (*src) {
tmp = from;
/*
* create a mapping between "from" and
* "to"
*/
while (*from)
mapvec[*from++] = (*to) ? *to++ : (char) 0;
while (*src) {
sch = *src++;
dch = mapvec[sch];
while (dch != sch) {
sch = dch;
dch = mapvec[sch];
}
if (*dest = dch)
dest++;
}
/*
* restore all the changed characters
*/
while (*tmp) {
mapvec[*tmp] = *tmp;
tmp++;
}
}
*dest = (char) 0;
}

626
src/cmd/m4/expr.c Normal file
View File

@@ -0,0 +1,626 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)expr.c 8.1 (Berkeley) 6/6/93";
#endif
#include <stdio.h>
#include "stdd.h"
/*
* expression evaluator: performs a standard recursive
* descent parse to evaluate any expression permissible
* within the following grammar:
*
* expr : query EOS
* query : lor
* | lor "?" query ":" query
* lor : land { "||" land }
* land : bor { "&&" bor }
* bor : bxor { "|" bxor }
* bxor : band { "^" band }
* band : eql { "&" eql }
* eql : relat { eqrel relat }
* relat : shift { rel shift }
* shift : primary { shop primary }
* primary : term { addop term }
* term : unary { mulop unary }
* unary : factor
* | unop unary
* factor : constant
* | "(" query ")"
* constant: num
* | "'" CHAR "'"
* num : DIGIT
* | DIGIT num
* shop : "<<"
* | ">>"
* eqlrel : "="
* | "=="
* | "!="
* rel : "<"
* | ">"
* | "<="
* | ">="
*
*
* This expression evaluator is lifted from a public-domain
* C Pre-Processor included with the DECUS C Compiler distribution.
* It is hacked somewhat to be suitable for m4.
*
* Originally by: Mike Lutz
* Bob Harper
*/
#define TRUE 1
#define FALSE 0
#define EOS (char) 0
#define EQL 0
#define NEQ 1
#define LSS 2
#define LEQ 3
#define GTR 4
#define GEQ 5
#define OCTAL 8
#define DECIMAL 10
static char *nxtch; /* Parser scan pointer */
static int query __P((void));
static int lor __P((void));
static int land __P((void));
static int bor __P((void));
static int bxor __P((void));
static int band __P((void));
static int eql __P((void));
static int relat __P((void));
static int shift __P((void));
static int primary __P((void));
static int term __P((void));
static int unary __P((void));
static int factor __P((void));
static int constant __P((void));
static int num __P((void));
static int geteql __P((void));
static int getrel __P((void));
static int skipws __P((void));
static void experr __P((char *));
/*
* For longjmp
*/
#include <setjmp.h>
static jmp_buf expjump;
/*
* macros:
* ungetch - Put back the last character examined.
* getch - return the next character from expr string.
*/
#define ungetch() nxtch--
#define getch() *nxtch++
int
expr(expbuf)
char *expbuf;
{
register int rval;
nxtch = expbuf;
if (setjmp(expjump) != 0)
return FALSE;
rval = query();
if (skipws() == EOS)
return rval;
printf("m4: ill-formed expression.\n");
return FALSE;
}
/*
* query : lor | lor '?' query ':' query
*/
static int
query()
{
register int bool, true_val, false_val;
bool = lor();
if (skipws() != '?') {
ungetch();
return bool;
}
true_val = query();
if (skipws() != ':')
experr("bad query");
false_val = query();
return bool ? true_val : false_val;
}
/*
* lor : land { '||' land }
*/
static int
lor()
{
register int c, vl, vr;
vl = land();
while ((c = skipws()) == '|' && getch() == '|') {
vr = land();
vl = vl || vr;
}
if (c == '|')
ungetch();
ungetch();
return vl;
}
/*
* land : bor { '&&' bor }
*/
static int
land()
{
register int c, vl, vr;
vl = bor();
while ((c = skipws()) == '&' && getch() == '&') {
vr = bor();
vl = vl && vr;
}
if (c == '&')
ungetch();
ungetch();
return vl;
}
/*
* bor : bxor { '|' bxor }
*/
static int
bor()
{
register int vl, vr, c;
vl = bxor();
while ((c = skipws()) == '|' && getch() != '|') {
ungetch();
vr = bxor();
vl |= vr;
}
if (c == '|')
ungetch();
ungetch();
return vl;
}
/*
* bxor : band { '^' band }
*/
static int
bxor()
{
register int vl, vr;
vl = band();
while (skipws() == '^') {
vr = band();
vl ^= vr;
}
ungetch();
return vl;
}
/*
* band : eql { '&' eql }
*/
static int
band()
{
register int vl, vr, c;
vl = eql();
while ((c = skipws()) == '&' && getch() != '&') {
ungetch();
vr = eql();
vl &= vr;
}
if (c == '&')
ungetch();
ungetch();
return vl;
}
/*
* eql : relat { eqrel relat }
*/
static int
eql()
{
register int vl, vr, rel;
vl = relat();
while ((rel = geteql()) != -1) {
vr = relat();
switch (rel) {
case EQL:
vl = (vl == vr);
break;
case NEQ:
vl = (vl != vr);
break;
}
}
return vl;
}
/*
* relat : shift { rel shift }
*/
static int
relat()
{
register int vl, vr, rel;
vl = shift();
while ((rel = getrel()) != -1) {
vr = shift();
switch (rel) {
case LEQ:
vl = (vl <= vr);
break;
case LSS:
vl = (vl < vr);
break;
case GTR:
vl = (vl > vr);
break;
case GEQ:
vl = (vl >= vr);
break;
}
}
return vl;
}
/*
* shift : primary { shop primary }
*/
static int
shift()
{
register int vl, vr, c;
vl = primary();
while (((c = skipws()) == '<' || c == '>') && c == getch()) {
vr = primary();
if (c == '<')
vl <<= vr;
else
vl >>= vr;
}
if (c == '<' || c == '>')
ungetch();
ungetch();
return vl;
}
/*
* primary : term { addop term }
*/
static int
primary()
{
register int c, vl, vr;
vl = term();
while ((c = skipws()) == '+' || c == '-') {
vr = term();
if (c == '+')
vl += vr;
else
vl -= vr;
}
ungetch();
return vl;
}
/*
* <term> := <unary> { <mulop> <unary> }
*/
static int
term()
{
register int c, vl, vr;
vl = unary();
while ((c = skipws()) == '*' || c == '/' || c == '%') {
vr = unary();
switch (c) {
case '*':
vl *= vr;
break;
case '/':
vl /= vr;
break;
case '%':
vl %= vr;
break;
}
}
ungetch();
return vl;
}
/*
* unary : factor | unop unary
*/
static int
unary()
{
register int val, c;
if ((c = skipws()) == '!' || c == '~' || c == '-') {
val = unary();
switch (c) {
case '!':
return !val;
case '~':
return ~val;
case '-':
return -val;
}
}
ungetch();
return factor();
}
/*
* factor : constant | '(' query ')'
*/
static int
factor()
{
register int val;
if (skipws() == '(') {
val = query();
if (skipws() != ')')
experr("bad factor");
return val;
}
ungetch();
return constant();
}
/*
* constant: num | 'char'
* Note: constant() handles multi-byte constants
*/
static int
constant()
{
register int i;
register int value;
register char c;
int v[sizeof(int)];
if (skipws() != '\'') {
ungetch();
return num();
}
for (i = 0; i < sizeof(int); i++) {
if ((c = getch()) == '\'') {
ungetch();
break;
}
if (c == '\\') {
switch (c = getch()) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
ungetch();
c = num();
break;
case 'n':
c = 012;
break;
case 'r':
c = 015;
break;
case 't':
c = 011;
break;
case 'b':
c = 010;
break;
case 'f':
c = 014;
break;
}
}
v[i] = c;
}
if (i == 0 || getch() != '\'')
experr("illegal character constant");
for (value = 0; --i >= 0;) {
value <<= 8;
value += v[i];
}
return value;
}
/*
* num : digit | num digit
*/
static int
num()
{
register int rval, c, base;
int ndig;
base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
rval = 0;
ndig = 0;
while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
rval *= base;
rval += (c - '0');
c = getch();
ndig++;
}
ungetch();
if (ndig == 0)
experr("bad constant");
return rval;
}
/*
* eqlrel : '=' | '==' | '!='
*/
static int
geteql()
{
register int c1, c2;
c1 = skipws();
c2 = getch();
switch (c1) {
case '=':
if (c2 != '=')
ungetch();
return EQL;
case '!':
if (c2 == '=')
return NEQ;
ungetch();
ungetch();
return -1;
default:
ungetch();
ungetch();
return -1;
}
}
/*
* rel : '<' | '>' | '<=' | '>='
*/
static int
getrel()
{
register int c1, c2;
c1 = skipws();
c2 = getch();
switch (c1) {
case '<':
if (c2 == '=')
return LEQ;
ungetch();
return LSS;
case '>':
if (c2 == '=')
return GEQ;
ungetch();
return GTR;
default:
ungetch();
ungetch();
return -1;
}
}
/*
* Skip over any white space and return terminating char.
*/
static int
skipws()
{
register char c;
while ((c = getch()) <= ' ' && c > EOS)
;
return c;
}
/*
* resets environment to eval(), prints an error
* and forces eval to return FALSE.
*/
static void
experr(msg)
char *msg;
{
printf("m4: %s in expr.\n", msg);
longjmp(expjump, -1);
}

98
src/cmd/m4/extern.h Normal file
View File

@@ -0,0 +1,98 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 6/6/93
*/
char *basename __P((char *));
char *xalloc __P((unsigned int));
int expr __P((char *));
ndptr addent __P((char *));
void chrsave __P((int));
void dochc __P((char *[], int));
void dochq __P((char *[], int));
void dodefine __P((char *, char *));
void dodefn __P((char *));
void dodiv __P((int));
void dodump __P((char *[], int));
void doifelse __P((char *[], int));
int doincl __P((char *));
int dopaste __P((char *));
void dopushdef __P((char *, char *));
void dosub __P((char *[], int));
void doundiv __P((char *[], int));
void eval __P((char *[], int, int));
void expand __P((char *[], int));
void getdiv __P((int));
char *xstrdup __P((const char *));
int hash __P((char *));
int indx __P((char *, char *));
ndptr lookup __P((char *));
void map __P((char *, char *, char *, char *));
int onintr __P((int));
void oops __P((const char *, ...));
void pbnum __P((int));
void pbstr __P((char *));
void putback __P((int));
void remhash __P((char *, int));
void usage __P((void));
extern ndptr hashtab[]; /* hash table for macros etc. */
extern stae mstack[]; /* stack of m4 machine */
extern FILE *active; /* active output file pointer */
extern FILE *infile[]; /* input file stack (0=stdin) */
extern FILE *outfile[]; /* diversion array(0=bitbucket) */
extern int fp; /* m4 call frame pointer */
extern int ilevel; /* input file stack pointer */
extern int oindex; /* diversion index. */
extern int sp; /* current m4 stack pointer */
extern char *bp; /* first available character */
extern char buf[]; /* push-back buffer */
extern char *bufbase; /* buffer base for this ilevel */
extern char *bbase[]; /* buffer base per ilevel */
extern char ecommt; /* end character for comment */
extern char *endest; /* end of string space */
extern char *endpbb; /* end of push-back buffer */
extern char *ep; /* first free char in strspace */
extern char lquote; /* left quote character (`) */
extern char *m4temp; /* filename for diversions */
extern char *m4wraps; /* m4wrap string default. */
extern char *null; /* as it says.. just a null. */
extern char *progname; /* program name */
extern char rquote; /* right quote character (') */
extern char scommt; /* start character for comment */
extern char *mktemp();
extern char *malloc();

144
src/cmd/m4/look.c Normal file
View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)look.c 8.1 (Berkeley) 6/6/93";
#endif
/*
* look.c
* Facility: m4 macro processor
* by: oz
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include "mdef.h"
#include "stdd.h"
#include "extern.h"
int
hash(name)
register char *name;
{
register unsigned long h = 0;
while (*name)
h = (h << 5) + h + *name++;
return (h % HASHSIZE);
}
/*
* find name in the hash table
*/
ndptr
lookup(name)
char *name;
{
register ndptr p;
for (p = hashtab[hash(name)]; p != nil; p = p->nxtptr)
if (STREQ(name, p->name))
break;
return (p);
}
/*
* hash and create an entry in the hash table.
* The new entry is added in front of a hash bucket.
*/
ndptr
addent(name)
char *name;
{
register int h;
ndptr p;
h = hash(name);
p = (ndptr) xalloc(sizeof(struct ndblock));
p->nxtptr = hashtab[h];
hashtab[h] = p;
p->name = xstrdup(name);
return p;
}
static void
freent(p)
ndptr p;
{
if (!(p->type & STATIC)) {
free((char *) p->name);
if (p->defn != null)
free((char *) p->defn);
}
free((char *) p);
}
/*
* remove an entry from the hashtable
*/
void
remhash(name, all)
char *name;
int all;
{
register int h;
register ndptr xp, tp, mp;
h = hash(name);
mp = hashtab[h];
tp = nil;
while (mp != nil) {
if (STREQ(mp->name, name)) {
mp = mp->nxtptr;
if (tp == nil) {
freent(hashtab[h]);
hashtab[h] = mp;
}
else {
xp = tp->nxtptr;
tp->nxtptr = mp;
freent(xp);
}
if (!all)
break;
}
else {
tp = mp;
mp = mp->nxtptr;
}
}
}

422
src/cmd/m4/main.c Normal file
View File

@@ -0,0 +1,422 @@
/*-
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && defined(DOSCCS)
static char copyright[] =
"@(#) Copyright (c) 1989, 1993\n\
The Regents of the University of California. All rights reserved.\n";
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
#endif
/*
* main.c
* Facility: m4 macro processor
* by: oz
*/
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "mdef.h"
#include "stdd.h"
#include "extern.h"
#include "pathnames.h"
ndptr hashtab[HASHSIZE]; /* hash table for macros etc. */
char buf[BUFSIZE]; /* push-back buffer */
char *bufbase = buf; /* the base for current ilevel */
char *bbase[MAXINP]; /* the base for each ilevel */
char *bp = buf; /* first available character */
char *endpbb = buf+BUFSIZE; /* end of push-back buffer */
stae mstack[STACKMAX+1]; /* stack of m4 machine */
char strspace[STRSPMAX+1]; /* string space for evaluation */
char *ep = strspace; /* first free char in strspace */
char *endest= strspace+STRSPMAX;/* end of string space */
int sp; /* current m4 stack pointer */
int fp; /* m4 call frame pointer */
FILE *infile[MAXINP]; /* input file stack (0=stdin) */
FILE *outfile[MAXOUT]; /* diversion array(0=bitbucket)*/
FILE *active; /* active output file pointer */
char *m4temp; /* filename for diversions */
int ilevel = 0; /* input file stack pointer */
int oindex = 0; /* diversion index.. */
char *null = ""; /* as it says.. just a null.. */
char *m4wraps = ""; /* m4wrap string default.. */
char *progname; /* name of this program */
char lquote = LQUOTE; /* left quote character (`) */
char rquote = RQUOTE; /* right quote character (') */
char scommt = SCOMMT; /* start character for comment */
char ecommt = ECOMMT; /* end character for comment */
struct keyblk keywrds[] = { /* m4 keywords to be installed */
"include", INCLTYPE,
"sinclude", SINCTYPE,
"define", DEFITYPE,
"defn", DEFNTYPE,
"divert", DIVRTYPE,
"expr", EXPRTYPE,
"eval", EXPRTYPE,
"substr", SUBSTYPE,
"ifelse", IFELTYPE,
"ifdef", IFDFTYPE,
"len", LENGTYPE,
"incr", INCRTYPE,
"decr", DECRTYPE,
"dnl", DNLNTYPE,
"changequote", CHNQTYPE,
"changecom", CHNCTYPE,
"index", INDXTYPE,
#ifdef EXTENDED
"paste", PASTTYPE,
"spaste", SPASTYPE,
#endif
"popdef", POPDTYPE,
"pushdef", PUSDTYPE,
"dumpdef", DUMPTYPE,
"shift", SHIFTYPE,
"translit", TRNLTYPE,
"undefine", UNDFTYPE,
"undivert", UNDVTYPE,
"divnum", DIVNTYPE,
"maketemp", MKTMTYPE,
"errprint", ERRPTYPE,
"m4wrap", M4WRTYPE,
"m4exit", EXITTYPE,
"syscmd", SYSCTYPE,
"sysval", SYSVTYPE,
#ifdef unix
"unix", MACRTYPE,
#else
#ifdef vms
"vms", MACRTYPE,
#endif
#endif
};
#define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk))
extern int optind;
extern char *optarg;
void macro();
void initkwds();
extern int getopt();
int
main(argc,argv)
int argc;
char *argv[];
{
register int c;
register int n;
char *p;
register FILE *ifp;
progname = basename(argv[0]);
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, onintr);
initkwds();
while ((c = getopt(argc, argv, "tD:U:o:")) != EOF)
switch(c) {
case 'D': /* define something..*/
for (p = optarg; *p; p++)
if (*p == '=')
break;
if (*p)
*p++ = EOS;
dodefine(optarg, p);
break;
case 'U': /* undefine... */
remhash(optarg, TOP);
break;
case 'o': /* specific output */
case '?':
usage();
}
argc -= optind;
argv += optind;
active = stdout; /* default active output */
/* filename for diversions */
m4temp = mktemp(xstrdup(_PATH_DIVNAME));
bbase[0] = bufbase;
if (!argc) {
sp = -1; /* stack pointer initialized */
fp = 0; /* frame pointer initialized */
infile[0] = stdin; /* default input (naturally) */
macro();
} else
for (; argc--; ++argv) {
p = *argv;
if (p[0] == '-' && p[1] == '\0')
ifp = stdin;
else if ((ifp = fopen(p, "r")) == NULL)
oops("%s: %s", p, strerror(errno));
sp = -1;
fp = 0;
infile[0] = ifp;
macro();
if (ifp != stdin)
(void)fclose(ifp);
}
if (*m4wraps) { /* anything for rundown ?? */
ilevel = 0; /* in case m4wrap includes.. */
bufbase = bp = buf; /* use the entire buffer */
putback(EOF); /* eof is a must !! */
pbstr(m4wraps); /* user-defined wrapup act */
macro(); /* last will and testament */
}
if (active != stdout)
active = stdout; /* reset output just in case */
for (n = 1; n < MAXOUT; n++) /* default wrap-up: undivert */
if (outfile[n] != NULL)
getdiv(n);
/* remove bitbucket if used */
if (outfile[0] != NULL) {
(void) fclose(outfile[0]);
m4temp[UNIQUE] = '0';
#ifdef vms
(void) remove(m4temp);
#else
(void) unlink(m4temp);
#endif
}
return 0;
}
ndptr inspect();
/*
* macro - the work horse..
*/
void
macro() {
char token[MAXTOK];
register char *s;
register int t, l;
register ndptr p;
register int nlpar;
cycle {
if ((t = gpbc()) == '_' || isalpha(t)) {
putback(t);
if ((p = inspect(s = token)) == nil) {
if (sp < 0)
while (*s)
putc(*s++, active);
else
while (*s)
chrsave(*s++);
}
else {
/*
* real thing.. First build a call frame:
*/
pushf(fp); /* previous call frm */
pushf(p->type); /* type of the call */
pushf(0); /* parenthesis level */
fp = sp; /* new frame pointer */
/*
* now push the string arguments:
*/
pushs(p->defn); /* defn string */
pushs(p->name); /* macro name */
pushs(ep); /* start next..*/
putback(l = gpbc());
if (l != LPAREN) { /* add bracks */
putback(RPAREN);
putback(LPAREN);
}
}
}
else if (t == EOF) {
if (sp > -1)
oops("unexpected end of input", "");
if (ilevel <= 0)
break; /* all done thanks.. */
--ilevel;
(void) fclose(infile[ilevel+1]);
bufbase = bbase[ilevel];
continue;
}
/*
* non-alpha single-char token seen..
* [the order of else if .. stmts is important.]
*/
else if (t == lquote) { /* strip quotes */
nlpar = 1;
do {
if ((l = gpbc()) == rquote)
nlpar--;
else if (l == lquote)
nlpar++;
else if (l == EOF)
oops("missing right quote", "");
if (nlpar > 0) {
if (sp < 0)
putc(l, active);
else
chrsave(l);
}
}
while (nlpar != 0);
}
else if (sp < 0) { /* not in a macro at all */
if (t == scommt) { /* comment handling here */
putc(t, active);
while ((t = gpbc()) != ecommt)
putc(t, active);
}
putc(t, active); /* output directly.. */
}
else switch(t) {
case LPAREN:
if (PARLEV > 0)
chrsave(t);
while (isspace(l = gpbc()))
; /* skip blank, tab, nl.. */
putback(l);
PARLEV++;
break;
case RPAREN:
if (--PARLEV > 0)
chrsave(t);
else { /* end of argument list */
chrsave(EOS);
if (sp == STACKMAX)
oops("internal stack overflow", "");
if (CALTYP == MACRTYPE)
expand((char **) mstack+fp+1, sp-fp);
else
eval((char **) mstack+fp+1, sp-fp, CALTYP);
ep = PREVEP; /* flush strspace */
sp = PREVSP; /* previous sp.. */
fp = PREVFP; /* rewind stack...*/
}
break;
case COMMA:
if (PARLEV == 1) {
chrsave(EOS); /* new argument */
while (isspace(l = gpbc()))
;
putback(l);
pushs(ep);
} else
chrsave(t);
break;
default:
chrsave(t); /* stack the char */
break;
}
}
}
/*
* build an input token..
* consider only those starting with _ or A-Za-z. This is a
* combo with lookup to speed things up.
*/
ndptr
inspect(tp)
register char *tp;
{
register char c;
register char *name = tp;
register char *etp = tp+MAXTOK;
register ndptr p;
register unsigned long h = 0;
while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
h = (h << 5) + h + (*tp++ = c);
putback(c);
if (tp == etp)
oops("token too long", "");
*tp = EOS;
for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
if (STREQ(name, p->name))
break;
return p;
}
/*
* initkwds - initialise m4 keywords as fast as possible.
* This very similar to install, but without certain overheads,
* such as calling lookup. Malloc is not used for storing the
* keyword strings, since we simply use the static pointers
* within keywrds block.
*/
void
initkwds() {
register int i;
register int h;
register ndptr p;
for (i = 0; i < MAXKEYS; i++) {
h = hash(keywrds[i].knam);
p = (ndptr) xalloc(sizeof(struct ndblock));
p->nxtptr = hashtab[h];
hashtab[h] = p;
p->name = keywrds[i].knam;
p->defn = null;
p->type = keywrds[i].ktyp | STATIC;
}
}

176
src/cmd/m4/mdef.h Normal file
View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mdef.h 8.1 (Berkeley) 6/6/93
*/
#define MACRTYPE 1
#define DEFITYPE 2
#define EXPRTYPE 3
#define SUBSTYPE 4
#define IFELTYPE 5
#define LENGTYPE 6
#define CHNQTYPE 7
#define SYSCTYPE 8
#define UNDFTYPE 9
#define INCLTYPE 10
#define SINCTYPE 11
#define PASTTYPE 12
#define SPASTYPE 13
#define INCRTYPE 14
#define IFDFTYPE 15
#define PUSDTYPE 16
#define POPDTYPE 17
#define SHIFTYPE 18
#define DECRTYPE 19
#define DIVRTYPE 20
#define UNDVTYPE 21
#define DIVNTYPE 22
#define MKTMTYPE 23
#define ERRPTYPE 24
#define M4WRTYPE 25
#define TRNLTYPE 26
#define DNLNTYPE 27
#define DUMPTYPE 28
#define CHNCTYPE 29
#define INDXTYPE 30
#define SYSVTYPE 31
#define EXITTYPE 32
#define DEFNTYPE 33
#define STATIC 128
/*
* m4 special characters
*/
#define ARGFLAG '$'
#define LPAREN '('
#define RPAREN ')'
#define LQUOTE '`'
#define RQUOTE '\''
#define COMMA ','
#define SCOMMT '#'
#define ECOMMT '\n'
#ifdef msdos
#define system(str) (-1)
#endif
/*
* other important constants
*/
#define EOS (char) 0
#define MAXINP 10 /* maximum include files */
#define MAXOUT 10 /* maximum # of diversions */
#define MAXSTR 512 /* maximum size of string */
#define BUFSIZE 4096 /* size of pushback buffer */
#define STACKMAX 1024 /* size of call stack */
#define STRSPMAX 4096 /* size of string space */
#define MAXTOK MAXSTR /* maximum chars in a tokn */
#define HASHSIZE 199 /* maximum size of hashtab */
#define ALL 1
#define TOP 0
#define TRUE 1
#define FALSE 0
#define cycle for(;;)
/*
* m4 data structures
*/
typedef struct ndblock *ndptr;
struct ndblock { /* hastable structure */
char *name; /* entry name.. */
char *defn; /* definition.. */
int type; /* type of the entry.. */
ndptr nxtptr; /* link to next entry.. */
};
#define nil ((ndptr) 0)
struct keyblk {
char *knam; /* keyword name */
int ktyp; /* keyword type */
};
typedef union { /* stack structure */
int sfra; /* frame entry */
char *sstr; /* string entry */
} stae;
/*
* macros for readibility and/or speed
*
* gpbc() - get a possibly pushed-back character
* pushf() - push a call frame entry onto stack
* pushs() - push a string pointer onto stack
*/
#define gpbc() (bp > bufbase) ? *--bp : getc(infile[ilevel])
#define pushf(x) if (sp < STACKMAX) mstack[++sp].sfra = (x)
#define pushs(x) if (sp < STACKMAX) mstack[++sp].sstr = (x)
/*
* . .
* | . | <-- sp | . |
* +-------+ +-----+
* | arg 3 ----------------------->| str |
* +-------+ | . |
* | arg 2 ---PREVEP-----+ .
* +-------+ |
* . | | |
* +-------+ | +-----+
* | plev | PARLEV +-------->| str |
* +-------+ | . |
* | type | CALTYP .
* +-------+
* | prcf ---PREVFP--+
* +-------+ |
* | . | PREVSP |
* . |
* +-------+ |
* | <----------+
* +-------+
*
*/
#define PARLEV (mstack[fp].sfra)
#define CALTYP (mstack[fp-1].sfra)
#define PREVEP (mstack[fp+3].sstr)
#define PREVSP (fp-3)
#define PREVFP (mstack[fp-2].sfra)

244
src/cmd/m4/misc.c Normal file
View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && defined(DOSCCS)
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
#endif
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "mdef.h"
#include "stdd.h"
#include "extern.h"
#include "pathnames.h"
/*
* find the index of second str in the first str.
*/
int
indx(s1, s2)
char *s1;
char *s2;
{
register char *t;
register char *p;
register char *m;
for (p = s1; *p; p++) {
for (t = p, m = s2; *m && *m == *t; m++, t++);
if (!*m)
return (p - s1);
}
return (-1);
}
/*
* putback - push character back onto input
*/
void
putback(c)
char c;
{
if (bp < endpbb)
*bp++ = c;
else
oops("too many characters pushed back");
}
/*
* pbstr - push string back onto input
* putback is replicated to improve
* performance.
*/
void
pbstr(s)
register char *s;
{
register char *es;
register char *zp;
es = s;
zp = bp;
while (*es)
es++;
es--;
while (es >= s)
if (zp < endpbb)
*zp++ = *es--;
if ((bp = zp) == endpbb)
oops("too many characters pushed back");
}
/*
* pbnum - convert number to string, push back on input.
*/
void
pbnum(n)
int n;
{
register int num;
num = (n < 0) ? -n : n;
do {
putback(num % 10 + '0');
}
while ((num /= 10) > 0);
if (n < 0)
putback('-');
}
/*
* chrsave - put single char on string space
*/
void
chrsave(c)
char c;
{
if (ep < endest)
*ep++ = c;
else
oops("string space overflow");
}
/*
* read in a diversion file, and dispose it.
*/
void
getdiv(n)
int n;
{
register int c;
register FILE *dfil;
if (active == outfile[n])
oops("%s: diversion still active.", "undivert");
(void) fclose(outfile[n]);
outfile[n] = NULL;
m4temp[UNIQUE] = n + '0';
if ((dfil = fopen(m4temp, "r")) == NULL)
oops("%s: cannot undivert.", m4temp);
else
while ((c = getc(dfil)) != EOF)
putc(c, active);
(void) fclose(dfil);
#ifdef vms
if (remove(m4temp))
#else
if (unlink(m4temp) == -1)
#endif
oops("%s: cannot unlink.", m4temp);
}
int
onintr()
{
oops("interrupted.");
}
char *
xalloc(n)
unsigned n;
{
register char *p = malloc(n);
if (p == NULL)
oops("malloc: %s", strerror(errno));
return p;
}
char *
xstrdup(s)
char *s;
{
register char *p = strdup(s);
if (p == NULL)
oops("strdup: %s", strerror(errno));
return p;
}
char *
basename(s)
register char *s;
{
register char *p;
extern char *strrchr();
if ((p = strrchr(s, '/')) == NULL)
return s;
return ++p;
}
void
usage()
{
fprintf(stderr, "usage: m4 [-Dname[=val]] [-Uname]\n");
exit(1);
}
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
void
#if __STDC__
oops(const char *fmt, ...)
#else
/* VARARGS1 */
oops(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)fprintf(stderr, "%s: ", progname);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
exit(1);
/* NOTREACHED */
}

57
src/cmd/m4/pathnames.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*/
/*
* Definitions of diversion files. If the name of the file is changed,
* adjust UNIQUE to point to the wildcard (*) character in the filename.
*/
#ifdef msdos
#define _PATH_DIVNAME "\\M4*XXXXXX" /* msdos diversion files */
#define UNIQUE 3 /* unique char location */
#endif
#ifdef unix
#define _PATH_DIVNAME "/tmp/m4.0XXXXXX" /* unix diversion files */
#define UNIQUE 8 /* unique char location */
#endif
#ifdef vms
#define _PATH_DIVNAME "sys$login:m4*XXXXXX" /* vms diversion files */
#define UNIQUE 12 /* unique char location */
#endif

60
src/cmd/m4/stdd.h Normal file
View File

@@ -0,0 +1,60 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ozan Yigit at York University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)stdd.h 8.1 (Berkeley) 6/6/93
*/
/*
* standard defines
*/
#define max(a,b) ((a) > (b)? (a): (b))
#define min(a,b) ((a) < (b)? (a): (b))
#define iswhite(c) ((c) == ' ' || (c) == '\t')
/*
* STREQ is an optimised strcmp(a,b)==0
* STREQN is an optimised strncmp(a,b,n)==0; assumes n > 0
*/
#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
#define YES 1
#define NO 0
#define __P(protos) ()
extern int errno;

70
src/cmd/m4/tags Normal file
View File

@@ -0,0 +1,70 @@
Mmain main.c /^main(argc,argv)$/
STREQ stdd.h /^#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a,/
STREQN stdd.h /^#define STREQN(a, b, n) ((a)[0] == (b)[0] && strnc/
__P stdd.h /^#define __P(protos) ()$/
addent look.c /^ndptr $/
band expr.c /^band()$/
basename misc.c /^basename(s)$/
bor expr.c /^bor()$/
bxor expr.c /^bxor()$/
chrsave misc.c /^chrsave(c)$/
constant expr.c /^constant()$/
dochc eval.c /^dochc(argv, argc)$/
dochq eval.c /^dochq(argv, argc)$/
dodefine eval.c /^dodefine(name, defn)$/
dodefn eval.c /^dodefn(name)$/
dodiv eval.c /^dodiv(n)$/
dodump eval.c /^dodump(argv, argc)$/
doifelse eval.c /^doifelse(argv, argc)$/
doincl eval.c /^doincl(ifile)$/
dopaste eval.c /^dopaste(pfile)$/
dopushdef eval.c /^dopushdef(name, defn)$/
dosub eval.c /^dosub(argv, argc)$/
doundiv eval.c /^doundiv(argv, argc)$/
eql expr.c /^eql()$/
eval eval.c /^eval(argv, argc, td)$/
expand eval.c /^expand(argv, argc)$/
experr expr.c /^experr(msg)$/
expr expr.c /^expr(expbuf)$/
factor expr.c /^factor()$/
freent look.c /^freent(p)$/
getch expr.c /^#define getch() *nxtch++$/
getdiv misc.c /^getdiv(n)$/
geteql expr.c /^geteql()$/
getrel expr.c /^getrel()$/
gpbc mdef.h /^#define gpbc() (bp > bufbase) ? *--bp : getc(inf/
hash look.c /^hash(name)$/
indx misc.c /^indx(s1, s2)$/
initkwds main.c /^initkwds() {$/
inspect main.c /^inspect(tp) $/
iswhite stdd.h /^#define iswhite(c) ((c) == ' ' || (c) == '\\t')$/
land expr.c /^land()$/
lookup look.c /^ndptr $/
lor expr.c /^lor()$/
macro main.c /^macro() {$/
map eval.c /^map(dest, src, from, to)$/
max stdd.h /^#define max(a,b) ((a) > (b)? (a): (b))$/
min stdd.h /^#define min(a,b) ((a) < (b)? (a): (b))$/
ndptr mdef.h 117
num expr.c /^num()$/
onintr misc.c /^onintr()$/
oops misc.c /^oops(const char *fmt, ...)$/
pbnum misc.c /^pbnum(n)$/
pbstr misc.c /^pbstr(s)$/
primary expr.c /^primary()$/
pushf mdef.h /^#define pushf(x) if (sp < STACKMAX) mstack[++sp].s/
pushs mdef.h /^#define pushs(x) if (sp < STACKMAX) mstack[++sp].s/
putback misc.c /^putback(c)$/
query expr.c /^query()$/
relat expr.c /^relat()$/
remhash look.c /^remhash(name, all)$/
shift expr.c /^shift()$/
skipws expr.c /^skipws()$/
stae mdef.h 136
system mdef.h /^#define system(str) (-1)$/
term expr.c /^term()$/
unary expr.c /^unary()$/
ungetch expr.c /^#define ungetch() nxtch--$/
usage misc.c /^usage()$/
xalloc misc.c /^xalloc(n)$/
xstrdup misc.c /^xstrdup(s)$/