Initial Import from SVN
This commit is contained in:
63
src/cmd/cpp/Makefile
Normal file
63
src/cmd/cpp/Makefile
Normal file
@@ -0,0 +1,63 @@
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
#include $(TOPSRC)/cross.mk
|
||||
#CFLAGS = -DCROSS
|
||||
|
||||
OBJS = cpp.o cpy.o token.o
|
||||
MAN = cpp.0
|
||||
MANSRC = cpp.1
|
||||
|
||||
LDFLAGS += -g
|
||||
|
||||
CFLAGS += -Werror -Wall -Os
|
||||
CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC
|
||||
|
||||
all: cpp $(MAN)
|
||||
|
||||
cpp: $(OBJS)
|
||||
${CC} ${LDFLAGS} -o cpp.elf $(OBJS) ${LIBS}
|
||||
${OBJDUMP} -S cpp.elf > cpp.dis
|
||||
${SIZE} cpp.elf
|
||||
${ELF2AOUT} cpp.elf $@ && rm cpp.elf
|
||||
|
||||
$(MAN): ${MANSRC}
|
||||
${MANROFF} $< > $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.0 *.elf cpp *.elf *.dis tags *~ lex.yy.c y.tab.[ch] tests/run*
|
||||
|
||||
install: all
|
||||
install cpp $(DESTDIR)/bin/
|
||||
cp cpp.0 $(DESTDIR)/share/man/cat1/
|
||||
|
||||
cpp.o: cpp.c y.tab.h
|
||||
|
||||
.l.o:
|
||||
$(LEX) $(LFLAGS) $<
|
||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ lex.yy.c
|
||||
|
||||
cpy.o y.tab.h: cpy.y
|
||||
$(YACC) -d $(YFLAGS) cpy.y
|
||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o cpy.o y.tab.c
|
||||
|
||||
test:
|
||||
./cpp.elf < tests/test1 > tests/run1
|
||||
cmp tests/run1 tests/res1
|
||||
./cpp.elf < tests/test2 > tests/run2
|
||||
cmp tests/run2 tests/res2
|
||||
./cpp.elf < tests/test3 > tests/run3
|
||||
cmp tests/run3 tests/res3
|
||||
./cpp.elf < tests/test4 > tests/run4
|
||||
cmp tests/run4 tests/res4
|
||||
./cpp.elf < tests/test5 > tests/run5
|
||||
cmp tests/run5 tests/res5
|
||||
./cpp.elf < tests/test6 > tests/run6
|
||||
cmp tests/run6 tests/res6
|
||||
./cpp.elf < tests/test7 > tests/run7
|
||||
cmp tests/run7 tests/res7
|
||||
./cpp.elf < tests/test8 > tests/run8
|
||||
cmp tests/run8 tests/res8
|
||||
./cpp.elf < tests/test9 > tests/run9
|
||||
cmp tests/run9 tests/res9
|
||||
./cpp.elf < tests/test10 > tests/run10
|
||||
cmp tests/run10 tests/res10
|
||||
210
src/cmd/cpp/cpp.1
Normal file
210
src/cmd/cpp/cpp.1
Normal file
@@ -0,0 +1,210 @@
|
||||
.\" $Id: cpp.1,v 1.11 2010/04/05 13:13:57 reed Exp $
|
||||
.\" $NetBSD$
|
||||
.\" $OpenBSD$
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Jeremy C. Reed <reed@reedmedia.net>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and/or distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM
|
||||
.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND
|
||||
.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
.\" THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd September 17, 2007
|
||||
.Dt CPP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cpp
|
||||
.Nd C preprocessor
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.\" TODO also document -Dvar and below without spaces?
|
||||
.Op Fl CdMtVv
|
||||
.Op Fl D Ar macro[=value]
|
||||
.Op Fl I Ar path
|
||||
.Op Fl i Ar file
|
||||
.Op Fl S Ar path
|
||||
.Op Fl U Ar macro
|
||||
.Op Ar infile | -
|
||||
.Op Ar outfile
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is a macro preprocessor used by the
|
||||
.Xr pcc 1
|
||||
compiler.
|
||||
It is used to include header files,
|
||||
expand macro definitions,
|
||||
and perform conditional compilation.
|
||||
.Pp
|
||||
The
|
||||
.Ar infile
|
||||
input file is optional.
|
||||
If not provided or the file name is
|
||||
.Qq -
|
||||
(dash),
|
||||
.Nm
|
||||
reads its initial file from standard input.
|
||||
The
|
||||
.Ar outfile
|
||||
output file is also optional.
|
||||
It writes by default to standard output.
|
||||
.Pp
|
||||
.\" TODO: document MAXARG 250 args to a macro, limited by char value
|
||||
.\" TODO: Include order:
|
||||
.\" For "..." files, first search "current" dir, then as <...> files.
|
||||
.\" For <...> files, first search -I directories, then system directories.
|
||||
.\"
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl ?
|
||||
Show command line usage for
|
||||
.Nm .
|
||||
.It Fl C
|
||||
Do not discard comments.
|
||||
.It Fl D Ar macro[=value]
|
||||
Fake a definition at the beginning by using
|
||||
.Do #define
|
||||
.Ar macro=value Dc .
|
||||
If
|
||||
.Ar value
|
||||
is not set on command-line, then define it as 1.
|
||||
.\" TODO: show example
|
||||
.It Fl dM
|
||||
Print list of
|
||||
.Dq #define
|
||||
statements to standard output for all defined macros other than
|
||||
builtin macros (see below).
|
||||
The normal results of preprocessing are not output.
|
||||
.\" TODO this doesn't show predefined macros
|
||||
.\" other -d options are ignored
|
||||
.It Fl I Ar path
|
||||
Add
|
||||
.Ar path
|
||||
to the list of directories containing needed header files.
|
||||
This may be used to override system include directories
|
||||
(see
|
||||
.Fl S
|
||||
option).
|
||||
.Fl I
|
||||
may be specified multiple times.
|
||||
.It Fl i Ar file
|
||||
Include a file at the beginning by using
|
||||
.Do #include
|
||||
.Ar file Dc .
|
||||
.\" Note: I did not use the .In macro above
|
||||
.It Fl M
|
||||
Generate dependencies for
|
||||
.Xr make 1 .
|
||||
.\" TODO: explain and show example?
|
||||
.It Fl P
|
||||
Inhibit generation of line markers. This is sometimes useful when
|
||||
running the preprocessor on something other than C code.
|
||||
.It Fl S Ar path
|
||||
Add
|
||||
.Ar path
|
||||
to the list of system directories containing needed header files.
|
||||
The
|
||||
.Fl S
|
||||
option may be specified multiple times.
|
||||
Note:
|
||||
.Nm
|
||||
does not have a default include directory defined.
|
||||
.\" TODO: explain difference between -I and -S
|
||||
.\" The directories listed by -I are searched first?
|
||||
.It Fl t
|
||||
Traditional cpp syntax.
|
||||
Do not define the
|
||||
.Dv __TIME__ ,
|
||||
.Dv __DATE__ ,
|
||||
.Dv __STDC__ ,
|
||||
and
|
||||
.Dv __STDC_VERSION__
|
||||
macros.
|
||||
.\"
|
||||
.It Fl U Ar macro
|
||||
Undefine a macro at the beginning by using
|
||||
.Do #undef
|
||||
.Ar macro Dc .
|
||||
.It Fl V
|
||||
Verbose debugging output.
|
||||
.Fl V
|
||||
can be repeated for further details.
|
||||
.\" -V only available if cpp source built with CPP_DEBUG, which is the default.
|
||||
.It Fl v
|
||||
Display version.
|
||||
.El
|
||||
.Ss Builtin Macros
|
||||
A few macros are interpreted inside the
|
||||
.Nm cpp
|
||||
program:
|
||||
.Bl -diag
|
||||
.It __DATE__
|
||||
Expands to the date in abbreviated month, day, and year format from
|
||||
.Xr ctime 3
|
||||
in quotes.
|
||||
.\" TODO: is that ctime(3) format output change according to locale?
|
||||
.It __FILE__
|
||||
Expands to the name of the current input file in quotes.
|
||||
When read from standard input, it expands to
|
||||
.Qq Aq stdin .
|
||||
.It __LINE__
|
||||
Expands to the line number of the current line containing the macro.
|
||||
.It __STDC__
|
||||
Expands to the constant 1.
|
||||
This means the compiler conforms to
|
||||
.St -isoC
|
||||
.Po also known as
|
||||
.Do C90 Dc Pc .
|
||||
.It __STDC_VERSION__
|
||||
Expands to
|
||||
.Dq 199901L
|
||||
which indicates that
|
||||
.Nm
|
||||
supports
|
||||
.St -isoC-99
|
||||
.Po commonly referred to as
|
||||
.Do C99 Dc Pc .
|
||||
.It __TIME__
|
||||
Expands to the time in hour, minutes, and seconds from
|
||||
.Xr ctime 3
|
||||
in quotes.
|
||||
.El
|
||||
.Pp
|
||||
Also see the
|
||||
.Fl t
|
||||
option.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits with one of the following values:
|
||||
.Bl -tag -width Ds
|
||||
.It 0
|
||||
Successfully finished.
|
||||
.It 1
|
||||
An error occurred.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr as 1 ,
|
||||
.Xr ccom 1 ,
|
||||
.Xr pcc 1
|
||||
.\"
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command comes from the original Portable C Compiler by S. C. Johnson,
|
||||
written in the late 70's.
|
||||
The code originates from the V6 preprocessor with some additions
|
||||
from V7 cpp and ansi/c99 support.
|
||||
.Pp
|
||||
A lot of the PCC code was rewritten by Anders Magnusson.
|
||||
.Pp
|
||||
This product includes software developed or owned by Caldera
|
||||
International, Inc.
|
||||
1767
src/cmd/cpp/cpp.c
Normal file
1767
src/cmd/cpp/cpp.c
Normal file
File diff suppressed because it is too large
Load Diff
150
src/cmd/cpp/cpp.h
Normal file
150
src/cmd/cpp/cpp.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#ifdef CROSS
|
||||
# include </usr/include/stdio.h>
|
||||
# include </usr/include/ctype.h>
|
||||
#else
|
||||
# include <stdio.h> /* for obuf */
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Version string */
|
||||
#define VERSSTR "cpp for RetroBSD"
|
||||
|
||||
typedef unsigned char uchar;
|
||||
#ifdef YYTEXT_POINTER
|
||||
extern char *yytext;
|
||||
#else
|
||||
extern char yytext[];
|
||||
#endif
|
||||
extern uchar *stringbuf;
|
||||
|
||||
extern int trulvl;
|
||||
extern int flslvl;
|
||||
extern int elflvl;
|
||||
extern int elslvl;
|
||||
extern int tflag, Cflag, Pflag;
|
||||
extern int Mflag, dMflag;
|
||||
extern uchar *Mfile;
|
||||
extern int ofd;
|
||||
|
||||
/* args for lookup() */
|
||||
#define FIND 0
|
||||
#define ENTER 1
|
||||
|
||||
/* buffer used internally */
|
||||
#define CPPBUF BUFSIZ
|
||||
|
||||
#define NAMEMAX CPPBUF /* currently pushbackbuffer */
|
||||
|
||||
/* definition for include file info */
|
||||
struct includ {
|
||||
struct includ *next;
|
||||
const uchar *fname; /* current fn, changed if #line found */
|
||||
const uchar *orgfn; /* current fn, not changed */
|
||||
int lineno;
|
||||
int infil;
|
||||
uchar *curptr;
|
||||
uchar *maxread;
|
||||
uchar *ostr;
|
||||
uchar *buffer;
|
||||
int idx;
|
||||
void *incs;
|
||||
const uchar *fn;
|
||||
uchar bbuf[NAMEMAX+CPPBUF+1];
|
||||
} *ifiles;
|
||||
|
||||
/* Symbol table entry */
|
||||
struct symtab {
|
||||
const uchar *namep;
|
||||
const uchar *value;
|
||||
const uchar *file;
|
||||
int line;
|
||||
};
|
||||
|
||||
struct initar {
|
||||
struct initar *next;
|
||||
int type;
|
||||
char *str;
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct used in parse tree evaluation.
|
||||
* op is one of:
|
||||
* - number type (NUMBER, UNUMBER)
|
||||
* - zero (0) if divided by zero.
|
||||
*/
|
||||
struct nd {
|
||||
int op;
|
||||
union {
|
||||
long long val;
|
||||
unsigned long long uval;
|
||||
} n;
|
||||
};
|
||||
|
||||
#define nd_val n.val
|
||||
#define nd_uval n.uval
|
||||
|
||||
struct recur; /* not used outside cpp.c */
|
||||
int subst(struct symtab *, struct recur *);
|
||||
struct symtab *lookup(const uchar *namep, int enterf);
|
||||
uchar *gotident(struct symtab *nl);
|
||||
int slow; /* scan slowly for new tokens */
|
||||
|
||||
int pushfile(const uchar *fname, const uchar *fn, int idx, void *incs);
|
||||
void popfile(void);
|
||||
void prtline(void);
|
||||
int yylex(void);
|
||||
int sloscan(void);
|
||||
void cunput(int);
|
||||
int curline(void);
|
||||
char *curfile(void);
|
||||
void setline(int);
|
||||
void setfile(char *);
|
||||
int yyparse(void);
|
||||
void yyerror(const char *);
|
||||
void unpstr(const uchar *);
|
||||
uchar *savstr(const uchar *str);
|
||||
void savch(int c);
|
||||
void mainscan(void);
|
||||
void putch(int);
|
||||
void putstr(const uchar *s);
|
||||
void line(void);
|
||||
uchar *sheap(const char *fmt, ...);
|
||||
void xwarning(uchar *);
|
||||
void xerror(uchar *);
|
||||
#ifdef HAVE_CPP_VARARG_MACRO_GCC
|
||||
#define warning(...) xwarning(sheap(__VA_ARGS__))
|
||||
#define error(...) xerror(sheap(__VA_ARGS__))
|
||||
#else
|
||||
#define warning printf
|
||||
#define error printf
|
||||
#endif
|
||||
void expmac(struct recur *);
|
||||
int cinput(void);
|
||||
void getcmnt(void);
|
||||
217
src/cmd/cpp/cpy.y
Normal file
217
src/cmd/cpp/cpy.y
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code and documentation must retain the above
|
||||
* copyright notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed or owned by Caldera
|
||||
* International, Inc.
|
||||
* Neither the name of Caldera International, Inc. nor the names of other
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
|
||||
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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 OFLIABILITY, 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.
|
||||
*/
|
||||
%{
|
||||
|
||||
#include "cpp.h"
|
||||
|
||||
void yyerror(const char *);
|
||||
int yylex(void);
|
||||
int setd(int l, int r);
|
||||
|
||||
#define EVALUNARY(tok, l, r) l.nd_val = tok r.nd_val; l.op = r.op
|
||||
#define EVALBIN(tok, d, l, r) \
|
||||
d.op = setd(l.op, r.op); d.nd_val = l.nd_val tok r.nd_val
|
||||
#define EVALUBIN(tok, d, l, r, t) \
|
||||
d.op = setd(l.op, r.op); \
|
||||
if (d.op == NUMBER) d.nd_val = l.nd_val tok r.nd_val; \
|
||||
else d.nd_uval = l.nd_uval tok r.nd_uval; \
|
||||
if (t && d.op) d.op = NUMBER
|
||||
#define XEVALUBIN(tok, d, l, r) \
|
||||
if (r.nd_val) { EVALUBIN(tok, d, l, r, 0); } else d.op = 0
|
||||
%}
|
||||
|
||||
%term stop
|
||||
%term EQ NE LE GE LS RS
|
||||
%term ANDAND OROR IDENT NUMBER UNUMBER DEFINED
|
||||
/*
|
||||
* The following terminals are not used in the yacc code.
|
||||
*/
|
||||
%term STRING WSPACE CMNT
|
||||
|
||||
%left ','
|
||||
%right '?' ':'
|
||||
%left OROR
|
||||
%left ANDAND
|
||||
%left '|' '^'
|
||||
%left '&'
|
||||
%binary EQ NE
|
||||
%binary '<' '>' LE GE
|
||||
%left LS RS
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%right '!' '~' UMINUS
|
||||
%left '('
|
||||
|
||||
%union {
|
||||
struct nd node;
|
||||
}
|
||||
|
||||
%type <node> term e NUMBER UNUMBER
|
||||
|
||||
%%
|
||||
S: e '\n' {
|
||||
if ($1.op == 0)
|
||||
error("division by zero");
|
||||
return $1.nd_val;
|
||||
}
|
||||
|
||||
e: e '*' e
|
||||
{ EVALUBIN(*, $$, $1, $3, 0); }
|
||||
| e '/' e
|
||||
{ XEVALUBIN(/, $$, $1, $3); }
|
||||
| e '%' e
|
||||
{ XEVALUBIN(%, $$, $1, $3); }
|
||||
| e '+' e
|
||||
{ EVALBIN(+, $$, $1, $3); }
|
||||
| e '-' e
|
||||
{ EVALBIN(-, $$, $1, $3); }
|
||||
| e LS e
|
||||
{ EVALBIN(<<, $$, $1, $3); }
|
||||
| e RS e
|
||||
{ EVALUBIN(>>, $$, $1, $3, 0); }
|
||||
| e '<' e
|
||||
{ EVALUBIN(<, $$, $1, $3, 1); }
|
||||
| e '>' e
|
||||
{ EVALUBIN(>, $$, $1, $3, 1); }
|
||||
| e LE e
|
||||
{ EVALUBIN(<=, $$, $1, $3, 1); }
|
||||
| e GE e
|
||||
{ EVALUBIN(>=, $$, $1, $3, 1); }
|
||||
| e EQ e
|
||||
{ EVALUBIN(==, $$, $1, $3, 1); }
|
||||
| e NE e
|
||||
{ EVALUBIN(!=, $$, $1, $3, 1); }
|
||||
| e '&' e
|
||||
{ EVALBIN(&, $$, $1, $3); }
|
||||
| e '^' e
|
||||
{ EVALBIN(^, $$, $1, $3); }
|
||||
| e '|' e
|
||||
{ EVALBIN(|, $$, $1, $3); }
|
||||
| e ANDAND e {
|
||||
$$ = $1;
|
||||
if ($1.nd_val) {
|
||||
$$.op = setd($1.op, $3.op);
|
||||
$$.nd_val = ($3.nd_val != 0);
|
||||
}
|
||||
if ($$.op == UNUMBER) $$.op = NUMBER;
|
||||
}
|
||||
| e OROR e {
|
||||
if ($1.nd_val != 0) {
|
||||
$$.nd_val = ($1.nd_val != 0);
|
||||
$$.op = $1.op;
|
||||
} else {
|
||||
$$.nd_val = ($3.nd_val != 0);
|
||||
$$.op = setd($1.op, $3.op);
|
||||
}
|
||||
if ($$.op == UNUMBER) $$.op = NUMBER;
|
||||
}
|
||||
| e '?' e ':' e {
|
||||
if ($1.op == 0)
|
||||
$$ = $1;
|
||||
else if ($1.nd_val)
|
||||
$$ = $3;
|
||||
else
|
||||
$$ = $5;
|
||||
}
|
||||
| e ',' e {
|
||||
$$.op = setd($1.op, $3.op);
|
||||
$$.nd_val = $3.nd_val;
|
||||
if ($$.op) $$.op = $3.op;
|
||||
}
|
||||
| term
|
||||
{$$ = $1;}
|
||||
term:
|
||||
'-' term %prec UMINUS
|
||||
{ EVALUNARY(-, $$, $2); }
|
||||
| '+' term %prec UMINUS
|
||||
{$$ = $2;}
|
||||
| '!' term
|
||||
{ $$.nd_val = ! $2.nd_val; $$.op = $2.op ? NUMBER : 0; }
|
||||
| '~' term
|
||||
{ EVALUNARY(~, $$, $2); }
|
||||
| '(' e ')'
|
||||
{$$ = $2;}
|
||||
| DEFINED '(' NUMBER ')'
|
||||
{$$= $3;}
|
||||
| DEFINED NUMBER
|
||||
{$$ = $2;}
|
||||
| NUMBER
|
||||
{$$ = $1;}
|
||||
%%
|
||||
|
||||
void
|
||||
yyerror(const char *err)
|
||||
{
|
||||
error(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set return type of an expression.
|
||||
*/
|
||||
int
|
||||
setd(int l, int r)
|
||||
{
|
||||
if (!l || !r)
|
||||
return 0; /* div by zero involved */
|
||||
if (l == UNUMBER || r == UNUMBER)
|
||||
return UNUMBER;
|
||||
return NUMBER;
|
||||
}
|
||||
932
src/cmd/cpp/scanner.l
Normal file
932
src/cmd/cpp/scanner.l
Normal file
@@ -0,0 +1,932 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2004 Anders Magnusson. All rights reserved.
|
||||
*
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "cpp.h"
|
||||
#include "y.tab.h"
|
||||
%}
|
||||
|
||||
%{
|
||||
static void cvtdig(int rad);
|
||||
static int charcon(uchar *);
|
||||
static void elsestmt(void);
|
||||
static void ifdefstmt(void);
|
||||
static void ifndefstmt(void);
|
||||
static void endifstmt(void);
|
||||
static void ifstmt(void);
|
||||
static void cpperror(void);
|
||||
static void pragmastmt(void);
|
||||
static void undefstmt(void);
|
||||
static void cpperror(void);
|
||||
static void elifstmt(void);
|
||||
static void storepb(void);
|
||||
static void badop(const char *);
|
||||
void include(void);
|
||||
void define(void);
|
||||
|
||||
extern int yyget_lineno (void);
|
||||
extern void yyset_lineno (int);
|
||||
|
||||
static int inch(void);
|
||||
|
||||
static int scale, gotdef, contr;
|
||||
int inif;
|
||||
|
||||
#ifdef FLEX_SCANNER /* should be set by autoconf instead */
|
||||
static int
|
||||
yyinput(char *b, int m)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
if ((c = inch()) < 0)
|
||||
break;
|
||||
*b++ = c;
|
||||
if (c == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
#undef YY_INPUT
|
||||
#undef YY_BUF_SIZE
|
||||
#define YY_BUF_SIZE (8*65536)
|
||||
#define YY_INPUT(b,r,m) (r = yyinput(b, m))
|
||||
#ifdef HAVE_CPP_VARARG_MACRO_GCC
|
||||
#define fprintf(x, ...) error(__VA_ARGS__)
|
||||
#endif
|
||||
#define ECHO putstr((uchar *)yytext)
|
||||
#undef fileno
|
||||
#define fileno(x) 0
|
||||
|
||||
#if YY_FLEX_SUBMINOR_VERSION >= 31
|
||||
/* Hack to avoid unnecessary warnings */
|
||||
FILE *yyget_in (void);
|
||||
FILE *yyget_out (void);
|
||||
int yyget_leng (void);
|
||||
char *yyget_text (void);
|
||||
void yyset_in (FILE * in_str );
|
||||
void yyset_out (FILE * out_str );
|
||||
int yyget_debug (void);
|
||||
void yyset_debug (int bdebug );
|
||||
int yylex_destroy (void);
|
||||
#endif
|
||||
#else /* Assume lex here */
|
||||
#undef input
|
||||
#undef unput
|
||||
#define input() inch()
|
||||
#define unput(ch) unch(ch)
|
||||
#endif
|
||||
#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((uchar *)yytext);
|
||||
/* protection against recursion in #include */
|
||||
#define MAX_INCLEVEL 100
|
||||
static int inclevel;
|
||||
%}
|
||||
|
||||
D [0-9]
|
||||
L [a-zA-Z_]
|
||||
H [a-fA-F0-9]
|
||||
E [Ee][+-]?{D}+
|
||||
FS (f|F|l|L)
|
||||
IS (u|U|l|L)*
|
||||
WS [\t ]
|
||||
|
||||
%s IFR CONTR DEF COMMENT
|
||||
|
||||
%%
|
||||
|
||||
"\n" { int os = YYSTATE;
|
||||
if (os != IFR)
|
||||
BEGIN 0;
|
||||
ifiles->lineno++;
|
||||
if (flslvl == 0) {
|
||||
if (ifiles->lineno == 1)
|
||||
prtline();
|
||||
else
|
||||
putch('\n');
|
||||
}
|
||||
if ((os != 0 || slow) && !contr)
|
||||
return '\n';
|
||||
contr = 0;
|
||||
}
|
||||
|
||||
"\r" { ; /* Ignore CR's */ }
|
||||
|
||||
<IFR>"++" { badop("++"); }
|
||||
<IFR>"--" { badop("--"); }
|
||||
<IFR>"==" { return EQ; }
|
||||
<IFR>"!=" { return NE; }
|
||||
<IFR>"<=" { return LE; }
|
||||
<IFR>"<<" { return LS; }
|
||||
<IFR>">>" { return RS; }
|
||||
<IFR>">=" { return GE; }
|
||||
<IFR>"||" { return OROR; }
|
||||
<IFR>"&&" { return ANDAND; }
|
||||
<IFR>"defined" { int p, c;
|
||||
gotdef = 1;
|
||||
if ((p = c = yylex()) == '(')
|
||||
c = yylex();
|
||||
if (c != IDENT || (p != IDENT && p != '('))
|
||||
error("syntax error");
|
||||
if (p == '(' && yylex() != ')')
|
||||
error("syntax error");
|
||||
return NUMBER;
|
||||
}
|
||||
|
||||
<IFR>{WS}+ { ; }
|
||||
<IFR>{L}({L}|{D})* {
|
||||
yylval.node.op = NUMBER;
|
||||
if (gotdef) {
|
||||
yylval.node.nd_val
|
||||
= lookup((uchar *)yytext, FIND) != 0;
|
||||
gotdef = 0;
|
||||
return IDENT;
|
||||
}
|
||||
yylval.node.nd_val = 0;
|
||||
return NUMBER;
|
||||
}
|
||||
|
||||
[0-9][0-9]* {
|
||||
if (slow && !YYSTATE)
|
||||
return IDENT;
|
||||
scale = yytext[0] == '0' ? 8 : 10;
|
||||
goto num;
|
||||
}
|
||||
|
||||
0[xX]{H}+{IS}? { scale = 16;
|
||||
num: if (YYSTATE == IFR)
|
||||
cvtdig(scale);
|
||||
PRTOUT(NUMBER);
|
||||
}
|
||||
0{D}+{IS}? { scale = 8; goto num; }
|
||||
{D}+{IS}? { scale = 10; goto num; }
|
||||
'(\\.|[^\\'])+' {
|
||||
if (YYSTATE || slow) {
|
||||
yylval.node.op = NUMBER;
|
||||
yylval.node.nd_val = charcon((uchar *)yytext);
|
||||
return (NUMBER);
|
||||
}
|
||||
if (tflag)
|
||||
yyless(1);
|
||||
if (!flslvl)
|
||||
putstr((uchar *)yytext);
|
||||
}
|
||||
|
||||
<IFR>. { return yytext[0]; }
|
||||
|
||||
{D}+{E}{FS}? { PRTOUT(FPOINT); }
|
||||
{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); }
|
||||
{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); }
|
||||
|
||||
^{WS}*#{WS}* { extern int inmac;
|
||||
|
||||
if (inmac)
|
||||
error("preprocessor directive found "
|
||||
"while expanding macro");
|
||||
contr = 1;
|
||||
BEGIN CONTR;
|
||||
}
|
||||
{WS}+ { PRTOUT(WSPACE); }
|
||||
|
||||
<CONTR>"ifndef" { contr = 0; ifndefstmt(); }
|
||||
<CONTR>"ifdef" { contr = 0; ifdefstmt(); }
|
||||
<CONTR>"if" { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; }
|
||||
<CONTR>"include" { contr = 0; BEGIN 0; include(); prtline(); }
|
||||
<CONTR>"else" { contr = 0; elsestmt(); }
|
||||
<CONTR>"endif" { contr = 0; endifstmt(); }
|
||||
<CONTR>"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; }
|
||||
<CONTR>"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; }
|
||||
<CONTR>"undef" { contr = 0; if (slow) return IDENT; undefstmt(); }
|
||||
<CONTR>"line" { contr = 0; storepb(); BEGIN 0; line(); }
|
||||
<CONTR>"pragma" { contr = 0; pragmastmt(); BEGIN 0; }
|
||||
<CONTR>"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; }
|
||||
|
||||
|
||||
|
||||
"//".*$ { /* if (tflag) yyless(..) */
|
||||
if (Cflag && !flslvl && !slow)
|
||||
putstr((uchar *)yytext);
|
||||
else if (!flslvl)
|
||||
putch(' ');
|
||||
}
|
||||
"/*" { int c, wrn;
|
||||
int prtcm = Cflag && !flslvl && !slow;
|
||||
extern int readmac;
|
||||
|
||||
if (Cflag && !flslvl && readmac)
|
||||
return CMNT;
|
||||
|
||||
if (prtcm)
|
||||
putstr((uchar *)yytext);
|
||||
wrn = 0;
|
||||
more: while ((c = input()) && c != '*') {
|
||||
if (c == '\n')
|
||||
putch(c), ifiles->lineno++;
|
||||
else if (c == 1) /* WARN */
|
||||
wrn = 1;
|
||||
else if (prtcm)
|
||||
putch(c);
|
||||
}
|
||||
if (c == 0)
|
||||
return 0;
|
||||
if (prtcm)
|
||||
putch(c);
|
||||
if ((c = input()) && c != '/') {
|
||||
unput(c);
|
||||
goto more;
|
||||
}
|
||||
if (prtcm)
|
||||
putch(c);
|
||||
if (c == 0)
|
||||
return 0;
|
||||
if (!tflag && !Cflag && !flslvl)
|
||||
unput(' ');
|
||||
if (wrn)
|
||||
unput(1);
|
||||
}
|
||||
|
||||
<DEF>"##" { return CONCAT; }
|
||||
<DEF>"#" { return MKSTR; }
|
||||
<DEF>"..." { return ELLIPS; }
|
||||
<DEF>"__VA_ARGS__" { return VA_ARGS; }
|
||||
|
||||
L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); }
|
||||
[a-zA-Z_0-9]+ { /* {L}({L}|{D})* */
|
||||
struct symtab *nl;
|
||||
if (slow)
|
||||
return IDENT;
|
||||
if (YYSTATE == CONTR) {
|
||||
if (flslvl == 0) {
|
||||
/*error("undefined control");*/
|
||||
while (input() != '\n')
|
||||
;
|
||||
unput('\n');
|
||||
BEGIN 0;
|
||||
goto xx;
|
||||
} else {
|
||||
BEGIN 0; /* do nothing */
|
||||
}
|
||||
}
|
||||
if (flslvl) {
|
||||
; /* do nothing */
|
||||
} else if (isdigit((int)yytext[0]) == 0 &&
|
||||
(nl = lookup((uchar *)yytext, FIND)) != 0) {
|
||||
uchar *op = stringbuf;
|
||||
putstr(gotident(nl));
|
||||
stringbuf = op;
|
||||
} else
|
||||
putstr((uchar *)yytext);
|
||||
xx: ;
|
||||
}
|
||||
|
||||
. {
|
||||
if (contr) {
|
||||
while (input() != '\n')
|
||||
;
|
||||
unput('\n');
|
||||
BEGIN 0;
|
||||
contr = 0;
|
||||
goto yy;
|
||||
}
|
||||
if (YYSTATE || slow)
|
||||
return yytext[0];
|
||||
if (yytext[0] == 6) { /* PRAGS */
|
||||
uchar *obp = stringbuf;
|
||||
extern uchar *prtprag(uchar *);
|
||||
*stringbuf++ = yytext[0];
|
||||
do {
|
||||
*stringbuf = input();
|
||||
} while (*stringbuf++ != 14);
|
||||
prtprag(obp);
|
||||
stringbuf = obp;
|
||||
} else {
|
||||
PRTOUT(yytext[0]);
|
||||
}
|
||||
yy:;
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
uchar *yyp, yybuf[CPPBUF];
|
||||
|
||||
int yylex(void);
|
||||
int yywrap(void);
|
||||
|
||||
static int
|
||||
inpch(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (ifiles->curptr < ifiles->maxread)
|
||||
return *ifiles->curptr++;
|
||||
|
||||
if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
|
||||
error("read error on file %s", ifiles->orgfn);
|
||||
if (len == 0)
|
||||
return -1;
|
||||
ifiles->curptr = ifiles->buffer;
|
||||
ifiles->maxread = ifiles->buffer + len;
|
||||
return inpch();
|
||||
}
|
||||
|
||||
#define unch(c) *--ifiles->curptr = c
|
||||
|
||||
static int
|
||||
inch(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
again: switch (c = inpch()) {
|
||||
case '\\': /* continued lines */
|
||||
msdos: if ((c = inpch()) == '\n') {
|
||||
ifiles->lineno++;
|
||||
putch('\n');
|
||||
goto again;
|
||||
} else if (c == '\r')
|
||||
goto msdos;
|
||||
unch(c);
|
||||
return '\\';
|
||||
case '?': /* trigraphs */
|
||||
if ((c = inpch()) != '?') {
|
||||
unch(c);
|
||||
return '?';
|
||||
}
|
||||
switch (c = inpch()) {
|
||||
case '=': c = '#'; break;
|
||||
case '(': c = '['; break;
|
||||
case ')': c = ']'; break;
|
||||
case '<': c = '{'; break;
|
||||
case '>': c = '}'; break;
|
||||
case '/': c = '\\'; break;
|
||||
case '\'': c = '^'; break;
|
||||
case '!': c = '|'; break;
|
||||
case '-': c = '~'; break;
|
||||
default:
|
||||
unch(c);
|
||||
unch('?');
|
||||
return '?';
|
||||
}
|
||||
unch(c);
|
||||
goto again;
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the command-line args be faked defines at beginning of file.
|
||||
*/
|
||||
static void
|
||||
prinit(struct initar *it, struct includ *ic)
|
||||
{
|
||||
char *a, *pre, *post;
|
||||
|
||||
if (it->next)
|
||||
prinit(it->next, ic);
|
||||
pre = post = NULL; /* XXX gcc */
|
||||
switch (it->type) {
|
||||
case 'D':
|
||||
pre = "#define ";
|
||||
if ((a = strchr(it->str, '=')) != NULL) {
|
||||
*a = ' ';
|
||||
post = "\n";
|
||||
} else
|
||||
post = " 1\n";
|
||||
break;
|
||||
case 'U':
|
||||
pre = "#undef ";
|
||||
post = "\n";
|
||||
break;
|
||||
case 'i':
|
||||
pre = "#include \"";
|
||||
post = "\"\n";
|
||||
break;
|
||||
default:
|
||||
error("prinit");
|
||||
}
|
||||
strlcat((char *)ic->buffer, pre, CPPBUF+1);
|
||||
strlcat((char *)ic->buffer, it->str, CPPBUF+1);
|
||||
if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
|
||||
error("line exceeds buffer size");
|
||||
|
||||
ic->lineno--;
|
||||
while (*ic->maxread)
|
||||
ic->maxread++;
|
||||
}
|
||||
|
||||
/*
|
||||
* A new file included.
|
||||
* If ifiles == NULL, this is the first file and already opened (stdin).
|
||||
* Return 0 on success, -1 if file to be included is not found.
|
||||
*/
|
||||
int
|
||||
pushfile(uchar *file)
|
||||
{
|
||||
extern struct initar *initar;
|
||||
struct includ ibuf;
|
||||
struct includ *ic;
|
||||
int c, otrulvl;
|
||||
|
||||
ic = &ibuf;
|
||||
ic->next = ifiles;
|
||||
|
||||
slow = 0;
|
||||
if (file != NULL) {
|
||||
if ((ic->infil = open((char *)file, O_RDONLY)) < 0)
|
||||
return -1;
|
||||
ic->orgfn = ic->fname = file;
|
||||
if (++inclevel > MAX_INCLEVEL)
|
||||
error("Limit for nested includes exceeded");
|
||||
} else {
|
||||
ic->infil = 0;
|
||||
ic->orgfn = ic->fname = (uchar *)"<stdin>";
|
||||
}
|
||||
ic->buffer = ic->bbuf+NAMEMAX;
|
||||
ic->curptr = ic->buffer;
|
||||
ifiles = ic;
|
||||
ic->lineno = 1;
|
||||
ic->maxread = ic->curptr;
|
||||
prtline();
|
||||
if (initar) {
|
||||
*ic->maxread = 0;
|
||||
prinit(initar, ic);
|
||||
if (dMflag)
|
||||
write(ofd, ic->buffer, strlen((char *)ic->buffer));
|
||||
initar = NULL;
|
||||
}
|
||||
|
||||
otrulvl = trulvl;
|
||||
|
||||
if ((c = yylex()) != 0)
|
||||
error("yylex returned %d", c);
|
||||
|
||||
if (otrulvl != trulvl || flslvl)
|
||||
error("unterminated conditional");
|
||||
|
||||
ifiles = ic->next;
|
||||
close(ic->infil);
|
||||
inclevel--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print current position to output file.
|
||||
*/
|
||||
void
|
||||
prtline()
|
||||
{
|
||||
uchar *s, *os = stringbuf;
|
||||
|
||||
if (Mflag) {
|
||||
if (dMflag)
|
||||
return; /* no output */
|
||||
if (ifiles->lineno == 1) {
|
||||
s = sheap("%s: %s\n", Mfile, ifiles->fname);
|
||||
write(ofd, s, strlen((char *)s));
|
||||
}
|
||||
} else if (!Pflag)
|
||||
putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
|
||||
stringbuf = os;
|
||||
}
|
||||
|
||||
void
|
||||
cunput(int c)
|
||||
{
|
||||
#ifdef CPP_DEBUG
|
||||
extern int dflag;
|
||||
if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c);
|
||||
#endif
|
||||
unput(c);
|
||||
}
|
||||
|
||||
int yywrap(void) { return 1; }
|
||||
|
||||
static int
|
||||
dig2num(int c)
|
||||
{
|
||||
if (c >= 'a')
|
||||
c = c - 'a' + 10;
|
||||
else if (c >= 'A')
|
||||
c = c - 'A' + 10;
|
||||
else
|
||||
c = c - '0';
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string numbers to unsigned long long and check overflow.
|
||||
*/
|
||||
static void
|
||||
cvtdig(int rad)
|
||||
{
|
||||
unsigned long long rv = 0;
|
||||
unsigned long long rv2 = 0;
|
||||
char *y = yytext;
|
||||
int c;
|
||||
|
||||
c = *y++;
|
||||
if (rad == 16)
|
||||
y++;
|
||||
while (isxdigit(c)) {
|
||||
rv = rv * rad + dig2num(c);
|
||||
/* check overflow */
|
||||
if (rv / rad < rv2)
|
||||
error("Constant \"%s\" is out of range", yytext);
|
||||
rv2 = rv;
|
||||
c = *y++;
|
||||
}
|
||||
y--;
|
||||
while (*y == 'l' || *y == 'L')
|
||||
y++;
|
||||
yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
|
||||
yylval.node.nd_uval = rv;
|
||||
if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
|
||||
yylval.node.op = UNUMBER;
|
||||
if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
|
||||
/* too large for signed */
|
||||
error("Constant \"%s\" is out of range", yytext);
|
||||
}
|
||||
|
||||
static int
|
||||
charcon(uchar *p)
|
||||
{
|
||||
int val, c;
|
||||
|
||||
p++; /* skip first ' */
|
||||
val = 0;
|
||||
if (*p++ == '\\') {
|
||||
switch (*p++) {
|
||||
case 'a': val = '\a'; break;
|
||||
case 'b': val = '\b'; break;
|
||||
case 'f': val = '\f'; break;
|
||||
case 'n': val = '\n'; break;
|
||||
case 'r': val = '\r'; break;
|
||||
case 't': val = '\t'; break;
|
||||
case 'v': val = '\v'; break;
|
||||
case '\"': val = '\"'; break;
|
||||
case '\'': val = '\''; break;
|
||||
case '\\': val = '\\'; break;
|
||||
case 'x':
|
||||
while (isxdigit(c = *p)) {
|
||||
val = val * 16 + dig2num(c);
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7':
|
||||
p--;
|
||||
while (isdigit(c = *p)) {
|
||||
val = val * 8 + (c - '0');
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
default: val = p[-1];
|
||||
}
|
||||
|
||||
} else
|
||||
val = p[-1];
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
chknl(int ignore)
|
||||
{
|
||||
int t;
|
||||
|
||||
slow = 1;
|
||||
while ((t = yylex()) == WSPACE)
|
||||
;
|
||||
if (t != '\n') {
|
||||
if (ignore) {
|
||||
warning("newline expected, got \"%s\"", yytext);
|
||||
/* ignore rest of line */
|
||||
while ((t = yylex()) && t != '\n')
|
||||
;
|
||||
}
|
||||
else
|
||||
error("newline expected, got \"%s\"", yytext);
|
||||
}
|
||||
slow = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
elsestmt(void)
|
||||
{
|
||||
if (flslvl) {
|
||||
if (elflvl > trulvl)
|
||||
;
|
||||
else if (--flslvl!=0) {
|
||||
flslvl++;
|
||||
} else {
|
||||
trulvl++;
|
||||
prtline();
|
||||
}
|
||||
} else if (trulvl) {
|
||||
flslvl++;
|
||||
trulvl--;
|
||||
} else
|
||||
error("If-less else");
|
||||
if (elslvl==trulvl+flslvl)
|
||||
error("Too many else");
|
||||
elslvl=trulvl+flslvl;
|
||||
chknl(1);
|
||||
}
|
||||
|
||||
static void
|
||||
ifdefstmt(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (flslvl) {
|
||||
/* just ignore the rest of the line */
|
||||
while (input() != '\n')
|
||||
;
|
||||
unput('\n');
|
||||
yylex();
|
||||
flslvl++;
|
||||
return;
|
||||
}
|
||||
slow = 1;
|
||||
do
|
||||
t = yylex();
|
||||
while (t == WSPACE);
|
||||
if (t != IDENT)
|
||||
error("bad ifdef");
|
||||
slow = 0;
|
||||
if (flslvl == 0 && lookup((uchar *)yytext, FIND) != 0)
|
||||
trulvl++;
|
||||
else
|
||||
flslvl++;
|
||||
chknl(0);
|
||||
}
|
||||
|
||||
static void
|
||||
ifndefstmt(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
slow = 1;
|
||||
do
|
||||
t = yylex();
|
||||
while (t == WSPACE);
|
||||
if (t != IDENT)
|
||||
error("bad ifndef");
|
||||
slow = 0;
|
||||
if (flslvl == 0 && lookup((uchar *)yytext, FIND) == 0)
|
||||
trulvl++;
|
||||
else
|
||||
flslvl++;
|
||||
chknl(0);
|
||||
}
|
||||
|
||||
static void
|
||||
endifstmt(void)
|
||||
{
|
||||
if (flslvl) {
|
||||
flslvl--;
|
||||
if (flslvl == 0)
|
||||
prtline();
|
||||
} else if (trulvl)
|
||||
trulvl--;
|
||||
else
|
||||
error("If-less endif");
|
||||
if (flslvl == 0)
|
||||
elflvl = 0;
|
||||
elslvl = 0;
|
||||
chknl(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note! Ugly!
|
||||
* Walk over the string s and search for defined, and replace it with
|
||||
* spaces and a 1 or 0.
|
||||
*/
|
||||
static void
|
||||
fixdefined(uchar *s)
|
||||
{
|
||||
uchar *bc, oc;
|
||||
|
||||
for (; *s; s++) {
|
||||
if (*s != 'd')
|
||||
continue;
|
||||
if (memcmp(s, "defined", 7))
|
||||
continue;
|
||||
/* Ok, got defined, can scratch it now */
|
||||
memset(s, ' ', 7);
|
||||
s += 7;
|
||||
#define WSARG(x) (x == ' ' || x == '\t')
|
||||
if (*s != '(' && !WSARG(*s))
|
||||
continue;
|
||||
while (WSARG(*s))
|
||||
s++;
|
||||
if (*s == '(')
|
||||
s++;
|
||||
while (WSARG(*s))
|
||||
s++;
|
||||
#define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_'))
|
||||
#define NUMARG(x) (x >= '0' && x <= '9')
|
||||
if (!IDARG(*s))
|
||||
error("bad defined arg");
|
||||
bc = s;
|
||||
while (IDARG(*s) || NUMARG(*s))
|
||||
s++;
|
||||
oc = *s;
|
||||
*s = 0;
|
||||
*bc = (lookup(bc, FIND) != 0) + '0';
|
||||
memset(bc+1, ' ', s-bc-1);
|
||||
*s = oc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get the full line of identifiers after an #if, pushback a WARN and
|
||||
* the line and prepare for expmac() to expand.
|
||||
* This is done before switching state. When expmac is finished,
|
||||
* pushback the expanded line, change state and call yyparse.
|
||||
*/
|
||||
static void
|
||||
storepb(void)
|
||||
{
|
||||
uchar *opb = stringbuf;
|
||||
int c;
|
||||
|
||||
while ((c = input()) != '\n') {
|
||||
if (c == '/') {
|
||||
if ((c = input()) == '*') {
|
||||
/* ignore comments here whatsoever */
|
||||
uchar *g = stringbuf;
|
||||
getcmnt();
|
||||
stringbuf = g;
|
||||
continue;
|
||||
} else if (c == '/') {
|
||||
while ((c = input()) && c != '\n')
|
||||
;
|
||||
break;
|
||||
}
|
||||
unput(c);
|
||||
c = '/';
|
||||
}
|
||||
savch(c);
|
||||
}
|
||||
cunput('\n');
|
||||
savch(0);
|
||||
fixdefined(opb); /* XXX can fail if #line? */
|
||||
cunput(1); /* WARN XXX */
|
||||
unpstr(opb);
|
||||
stringbuf = opb;
|
||||
slow = 1;
|
||||
expmac(NULL);
|
||||
slow = 0;
|
||||
/* line now expanded */
|
||||
while (stringbuf > opb)
|
||||
cunput(*--stringbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
ifstmt(void)
|
||||
{
|
||||
if (flslvl == 0) {
|
||||
slow = 1;
|
||||
if (yyparse())
|
||||
++trulvl;
|
||||
else
|
||||
++flslvl;
|
||||
slow = 0;
|
||||
} else
|
||||
++flslvl;
|
||||
}
|
||||
|
||||
static void
|
||||
elifstmt(void)
|
||||
{
|
||||
if (flslvl == 0)
|
||||
elflvl = trulvl;
|
||||
if (flslvl) {
|
||||
if (elflvl > trulvl)
|
||||
;
|
||||
else if (--flslvl!=0)
|
||||
++flslvl;
|
||||
else {
|
||||
slow = 1;
|
||||
if (yyparse()) {
|
||||
++trulvl;
|
||||
prtline();
|
||||
} else
|
||||
++flslvl;
|
||||
slow = 0;
|
||||
}
|
||||
} else if (trulvl) {
|
||||
++flslvl;
|
||||
--trulvl;
|
||||
} else
|
||||
error("If-less elif");
|
||||
}
|
||||
|
||||
static uchar *
|
||||
svinp(void)
|
||||
{
|
||||
int c;
|
||||
uchar *cp = stringbuf;
|
||||
|
||||
while ((c = input()) && c != '\n')
|
||||
savch(c);
|
||||
savch('\n');
|
||||
savch(0);
|
||||
BEGIN 0;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static void
|
||||
cpperror(void)
|
||||
{
|
||||
uchar *cp;
|
||||
int c;
|
||||
|
||||
if (flslvl)
|
||||
return;
|
||||
c = yylex();
|
||||
if (c != WSPACE && c != '\n')
|
||||
error("bad error");
|
||||
cp = svinp();
|
||||
if (flslvl)
|
||||
stringbuf = cp;
|
||||
else
|
||||
error("%s", cp);
|
||||
}
|
||||
|
||||
static void
|
||||
undefstmt(void)
|
||||
{
|
||||
struct symtab *np;
|
||||
|
||||
slow = 1;
|
||||
if (yylex() != WSPACE || yylex() != IDENT)
|
||||
error("bad undef");
|
||||
if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND)))
|
||||
np->value = 0;
|
||||
slow = 0;
|
||||
chknl(0);
|
||||
}
|
||||
|
||||
static void
|
||||
pragmastmt(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
slow = 1;
|
||||
if (yylex() != WSPACE)
|
||||
error("bad pragma");
|
||||
if (!flslvl)
|
||||
putstr((uchar *)"#pragma ");
|
||||
do {
|
||||
c = input();
|
||||
if (!flslvl)
|
||||
putch(c); /* Do arg expansion instead? */
|
||||
} while (c && c != '\n');
|
||||
ifiles->lineno++;
|
||||
prtline();
|
||||
slow = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
badop(const char *op)
|
||||
{
|
||||
error("invalid operator in preprocessor expression: %s", op);
|
||||
}
|
||||
|
||||
int
|
||||
cinput()
|
||||
{
|
||||
return input();
|
||||
}
|
||||
8
src/cmd/cpp/tests/res1
Normal file
8
src/cmd/cpp/tests/res1
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
char p[] = "x ## y";
|
||||
|
||||
16
src/cmd/cpp/tests/res10
Normal file
16
src/cmd/cpp/tests/res10
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int midiopen(int);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
foo_optarg
|
||||
26
src/cmd/cpp/tests/res2
Normal file
26
src/cmd/cpp/tests/res2
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
|
||||
int i[] = { 1, 23, 4, 5, };
|
||||
char c[2][6] = { "hello", "" };
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
16
src/cmd/cpp/tests/res3
Normal file
16
src/cmd/cpp/tests/res3
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
|
||||
fputs(
|
||||
"strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);
|
||||
\#include "vers2.h"
|
||||
"hello";
|
||||
"hello" ", world"
|
||||
6
src/cmd/cpp/tests/res4
Normal file
6
src/cmd/cpp/tests/res4
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
(1)
|
||||
5
src/cmd/cpp/tests/res5
Normal file
5
src/cmd/cpp/tests/res5
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
int j[] = { 123, 45, 67, 89,
|
||||
10, 11, 12, };
|
||||
5
src/cmd/cpp/tests/res6
Normal file
5
src/cmd/cpp/tests/res6
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
foo
|
||||
6
src/cmd/cpp/tests/res7
Normal file
6
src/cmd/cpp/tests/res7
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
a
|
||||
YES
|
||||
9
src/cmd/cpp/tests/res8
Normal file
9
src/cmd/cpp/tests/res8
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(hej.s_s.s_pos)
|
||||
|
||||
6
src/cmd/cpp/tests/res9
Normal file
6
src/cmd/cpp/tests/res9
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
# 1 "<stdin>"
|
||||
|
||||
|
||||
|
||||
ao
|
||||
6
src/cmd/cpp/tests/test1
Normal file
6
src/cmd/cpp/tests/test1
Normal file
@@ -0,0 +1,6 @@
|
||||
#define hash_hash # ## #
|
||||
#define mkstr(a) # a
|
||||
#define in_between(a) mkstr(a)
|
||||
#define join(c, d) in_between(c hash_hash d)
|
||||
char p[] = join(x, y); // equivalent to
|
||||
// char p[] = "x ## y";
|
||||
14
src/cmd/cpp/tests/test10
Normal file
14
src/cmd/cpp/tests/test10
Normal file
@@ -0,0 +1,14 @@
|
||||
#define __CONCAT(x,y) x ## y
|
||||
#define dev_type_open(n) int n(int)
|
||||
#define dev_decl(n,t) __CONCAT(dev_type_,t)(__CONCAT(n,t))
|
||||
#define cdev_decl(n) dev_decl(n,open)
|
||||
|
||||
cdev_decl(midi);
|
||||
|
||||
# define __GETOPT_PREFIX foo_
|
||||
# define __GETOPT_CONCAT(x, y) x ## y
|
||||
# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
|
||||
# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
|
||||
# define optarg __GETOPT_ID (optarg)
|
||||
|
||||
optarg
|
||||
25
src/cmd/cpp/tests/test2
Normal file
25
src/cmd/cpp/tests/test2
Normal file
@@ -0,0 +1,25 @@
|
||||
#define x 3
|
||||
#define f(a) f(x * (a))
|
||||
#undef x
|
||||
#define x 2
|
||||
#define g f
|
||||
#define z z[0]
|
||||
#define h g(~
|
||||
#define m(a) a(w)
|
||||
#define w 0,1
|
||||
#define t(a) a
|
||||
#define p() int
|
||||
#define q(x) x
|
||||
#define r(x,y) x ## y
|
||||
#define str(x) # x
|
||||
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
|
||||
g(x+(3,4)-w) | h 5) & m
|
||||
(f)^m(m);
|
||||
p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
|
||||
char c[2][6] = { str(hello), str() };
|
||||
/*
|
||||
* f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
* f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
|
||||
* int i[] = { 1, 23, 4, 5, };
|
||||
* char c[2][6] = { "hello", "" };
|
||||
*/
|
||||
15
src/cmd/cpp/tests/test3
Normal file
15
src/cmd/cpp/tests/test3
Normal file
@@ -0,0 +1,15 @@
|
||||
#define str(s) # s
|
||||
#define xstr(s) str(s)
|
||||
#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
|
||||
x ## s, x ## t)
|
||||
#define INCFILE(n) vers ## n
|
||||
#define glue(a, b) a ## b
|
||||
#define xglue(a, b) glue(a, b)
|
||||
#define HIGHLOW "hello"
|
||||
#define LOW LOW ", world"
|
||||
debug(1, 2);
|
||||
fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away
|
||||
== 0) str(: @\n), s);
|
||||
\#include xstr(INCFILE(2).h)
|
||||
glue(HIGH, LOW);
|
||||
xglue(HIGH, LOW)
|
||||
4
src/cmd/cpp/tests/test4
Normal file
4
src/cmd/cpp/tests/test4
Normal file
@@ -0,0 +1,4 @@
|
||||
#define foobar 1
|
||||
#define C(x,y) x##y
|
||||
#define D(x) (C(x,bar))
|
||||
D(foo)
|
||||
3
src/cmd/cpp/tests/test5
Normal file
3
src/cmd/cpp/tests/test5
Normal file
@@ -0,0 +1,3 @@
|
||||
#define t(x,y,z) x ## y ## z
|
||||
int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
|
||||
t(10,,), t(,11,), t(,,12), t(,,) };
|
||||
5
src/cmd/cpp/tests/test6
Normal file
5
src/cmd/cpp/tests/test6
Normal file
@@ -0,0 +1,5 @@
|
||||
#define X(a,b, \
|
||||
c,d) \
|
||||
foo
|
||||
|
||||
X(1,2,3,4)
|
||||
4
src/cmd/cpp/tests/test7
Normal file
4
src/cmd/cpp/tests/test7
Normal file
@@ -0,0 +1,4 @@
|
||||
#define a() YES
|
||||
#define b() a
|
||||
b()
|
||||
b()()
|
||||
7
src/cmd/cpp/tests/test8
Normal file
7
src/cmd/cpp/tests/test8
Normal file
@@ -0,0 +1,7 @@
|
||||
// test macro expansion in arguments
|
||||
#define s_pos s_s.s_pos
|
||||
#define foo(x) (x)
|
||||
|
||||
//hej.s_pos
|
||||
foo(hej.s_pos)
|
||||
|
||||
4
src/cmd/cpp/tests/test9
Normal file
4
src/cmd/cpp/tests/test9
Normal file
@@ -0,0 +1,4 @@
|
||||
#define C(a,b,c) a##b##c
|
||||
#define N(x,y) C(x,_,y)
|
||||
#define A_O ao
|
||||
N(A,O)
|
||||
1289
src/cmd/cpp/token.c
Normal file
1289
src/cmd/cpp/token.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user