[Midnightbsd-cvs] src: usr.bin/pcc: Work in progress: A reorganization of pcc similar to
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Wed May 14 00:26:00 EDT 2008
Log Message:
-----------
Work in progress: A reorganization of pcc similar to what OpenBSD did with it. This is much easier to work with.
Modified Files:
--------------
src/usr.bin/pcc:
Makefile (r1.1 -> r1.2)
config.h (r1.1 -> r1.2)
src/usr.bin/pcc/cc:
Makefile (r1.1 -> r1.2)
Added Files:
-----------
src/usr.bin/pcc:
ccconfig.h (r1.1)
src/usr.bin/pcc/cc:
cc.1 (r1.1)
cc.c (r1.1)
src/usr.bin/pcc/ccom:
Makefile (r1.1)
ccom.1 (r1.1)
cgram.y (r1.1)
gcc_compat.c (r1.1)
init.c (r1.1)
inline.c (r1.1)
main.c (r1.1)
optim.c (r1.1)
pass1.h (r1.1)
pftn.c (r1.1)
scan.l (r1.1)
stabs.c (r1.1)
symtabs.c (r1.1)
trees.c (r1.1)
src/usr.bin/pcc/cpp:
Makefile (r1.1)
cpp.1 (r1.1)
cpp.c (r1.1)
cpp.h (r1.1)
cpy.y (r1.1)
scanner.l (r1.1)
token.c (r1.1)
Removed Files:
-------------
src/usr.bin/pcc/cc/cc:
Makefile
cc.1
cc.c
src/usr.bin/pcc/cc/ccom:
Makefile
ccom.1
cgram.y
gcc_compat.c
init.c
inline.c
main.c
optim.c
pass1.h
pftn.c
scan.l
stabs.c
symtabs.c
trees.c
src/usr.bin/pcc/cc/cpp:
Makefile
cpp.1
cpp.c
cpp.h
cpy.y
scanner.l
token.c
src/usr.bin/pcc/cc/cpp/tests:
res1
res2
res3
res4
res5
res6
res7
res8
res9
test1
test2
test3
test4
test5
test6
test7
test8
test9
-------------- next part --------------
--- /dev/null
+++ usr.bin/pcc/ccconfig.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2007 Lucas Holt <luke at midnightbsd.org>
+ * Copyright (c) 2007 David O'Brien <obrien at FreeBSD.org>
+ * Copyright (c) 2007 Ed Schouten <ed at fxq.nl>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#define CPPADD { "-D__MidnightBSD__", "-D__ELF__", "-D__unix__=1", "-D__unix=1", "-D__STDC__=1", NULL, }
+#define DYNLINKER { "-dynamic-linker", "/libexec/ld-elf.so.1", NULL }
+#define CRT0FILE "/usr/lib/crt1.o"
+#define STARTFILES { "/usr/lib/crti.o", "/usr/lib/crtbegin.o", NULL }
+#define ENDFILES { "/usr/lib/crtend.o", "/usr/lib/crtn.o", NULL }
+#define STARTLABEL "_start"
+
+#if defined(mach_i386) || defined(mach_x86)
+#define CPPMDADD { "-D__i386__", "-D__i386", NULL, }
+#else
+#error defines for arch missing
+#endif
+
+#define STABS
+
Index: config.h
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/config.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/config.h -L usr.bin/pcc/config.h -u -r1.1 -r1.2
--- usr.bin/pcc/config.h
+++ usr.bin/pcc/config.h
@@ -131,7 +131,7 @@
#define PCC_MAJOR 0
#define PCC_MINOR 9
#define PCC_MINORMINOR 8
-#define VERSSTR "pcc 0.9.8 for i386-unknown-midnightbsd0.1, laffer1 at m5.midnightbsd.org Wed Sep 26 15:13:33 EDT 2007"
+#define VERSSTR "pcc 0.9.8 for i386-unknown-midnightbsd0.2, laffer1 at m5.midnightbsd.org Wed Sep 26 15:13:33 EDT 2007"
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/Makefile -L usr.bin/pcc/Makefile -u -r1.1 -r1.2
--- usr.bin/pcc/Makefile
+++ usr.bin/pcc/Makefile
@@ -1,31 +1,5 @@
-# $Id: Makefile.in,v 1.3 2005/05/14 13:28:13 ragge Exp $
-#
-# Makefile.in for top-level of pcc.
-#
+# $MidnightBSD$
-CC=gcc
-CFLAGS=-g
-LDFLAGS=
-CPPFLAGS=
-YACC=yacc
-LEX=flex
+SUBDIR= cc cpp ccom
-SUBDIR=cc
-
-all: ${SUBDIR}
-
-install:
- cd cc && ${MAKE} install
-
-clean:
- cd cc && ${MAKE} clean
-
-distclean:
- cd cc && ${MAKE} distclean
- /bin/rm -rf Makefile config.log stamp-h1 config.status \
- configure.lineno config.h autom4te.cache
-
-${SUBDIR}: nonexistant
- cd $@ && $(MAKE) all $(MFLAGS)
-
-nonexistant:
+.include <bsd.subdir.mk>
--- /dev/null
+++ usr.bin/pcc/cc/cc.c
@@ -0,0 +1,736 @@
+/* $Id: cc.c,v 1.61 2007/09/26 14:48:47 ragge Exp $ */
+/*
+ * 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 conditionsand 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.
+ */
+
+/*
+ * Front-end to the C compiler.
+ *
+ * Brief description of its syntax:
+ * - Files that end with .c are passed via cpp->ccom->as->ld
+ * - Files that end with .i are passed via ccom->as->ld
+ * - Files that end with .s are passed as->ld
+ * - Files that end with .o are passed directly to ld
+ * - Multiple files may be given on the command line.
+ * - Unrecognized options are all sent directly to ld.
+ * -c or -S cannot be combined with -o if multiple files are given.
+ *
+ * This file should be rewritten readable.
+ */
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include "../config.h"
+
+#include "ccconfig.h"
+/* C command */
+
+#define MKS(x) _MKS(x)
+#define _MKS(x) #x
+
+/*
+ * Many specific definitions, should be declared elsewhere.
+ */
+#define STDINC "/usr/include/"
+
+#define SBSIZE 10000
+#define MAXINC 100
+#define MAXFIL 100
+#define MAXLIB 10000
+#define MAXAV 10000
+#define MAXOPT 100
+char *tmp3;
+char *tmp4;
+char *outfile;
+char *copy(char *as),*setsuf(char *as, char ch);
+int getsuf(char []);
+int main(int, char *[]);
+void error(char *, ...);
+void errorx(int eval, char *, ...);
+int nodup(char **, char *);
+int callsys(char [], char *[]);
+int cunlink(char *);
+void dexit(int eval);
+void idexit(int);
+char *gettmp();
+char *av[MAXAV];
+char *clist[MAXFIL];
+char *llist[MAXLIB];
+char alist[20];
+char *xlist[100];
+int xnum;
+int dflag;
+int pflag;
+int sflag;
+int cflag;
+int eflag;
+int gflag;
+int vflag;
+int tflag;
+int Eflag;
+int Oflag;
+int kflag; /* generate PIC/pic code */
+#define F_PIC 1
+#define F_pic 2
+int Mflag; /* dependencies only */
+int pgflag;
+int exfail;
+int Xflag;
+int nostartfiles, Bstatic;
+int nostdinc, nostdlib;
+int onlyas;
+int pthreads;
+
+char *pass0 = LIBEXECDIR "/ccom";
+char *passp = LIBEXECDIR "/cpp";
+char *Bflag;
+char *cppadd[] = CPPADD;
+char *dynlinker[] = DYNLINKER;
+char *crt0file = CRT0FILE;
+char *startfiles[] = STARTFILES;
+char *endfiles[] = ENDFILES;
+char *cppmdadd[] = CPPMDADD;
+#ifdef LIBCLIBS
+char *libclibs[] = LIBCLIBS;
+#else
+char *libclibs[] = { "-lc", NULL };
+#endif
+#ifndef STARTLABEL
+#define STARTLABEL "__start"
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ char *t, *u;
+ char *assource;
+ char **pv, *ptemp[MAXOPT], **pvt;
+ int nc, nl, i, j, c, nxo, na;
+
+ i = nc = nl = nxo = 0;
+ pv = ptemp;
+ while(++i < argc) {
+ if (argv[i][0] == '-')
+ switch (argv[i][1]) {
+ default:
+ goto passa;
+
+ case 'B': /* other search paths for binaries */
+ Bflag = &argv[i][2];
+ break;
+
+ case 'X':
+ Xflag++;
+ break;
+ case 'W': /* Ignore (most of) W-flags */
+ if (strncmp(argv[i], "-Wl,", 4) == 0) {
+ /* options to the linker */
+ t = &argv[i][4];
+ while ((u = strchr(t, ','))) {
+ *u++ = 0;
+ llist[nl++] = t;
+ t = u;
+ }
+ llist[nl++] = t;
+ }
+ break;
+
+ case 'f': /* GCC compatibility flags */
+ if (strcmp(argv[i], "-fPIC") == 0)
+ kflag = F_PIC;
+ if (strcmp(argv[i], "-fpic") == 0)
+ kflag = F_pic;
+ /* silently ignore the rest */
+ break;
+
+ case 'g': /* create debug output */
+ gflag++;
+ break;
+
+ case 'i':
+ if (strcmp(argv[i], "-isystem") == 0) {
+ *pv++ = "-S";
+ *pv++ = argv[++i];
+ } else if (strcmp(argv[i], "-include") == 0) {
+ *pv++ = "-i";
+ *pv++ = argv[++i];
+ } else
+ goto passa;
+ break;
+
+ case 'k': /* generate PIC code */
+ kflag = F_pic;
+ break;
+
+ case 'n': /* handle -n flags */
+ if (strcmp(argv[i], "-nostdinc") == 0)
+ nostdinc++;
+ if (strcmp(argv[i], "-nostdlib") == 0) {
+ nostdlib++;
+ nostartfiles++;
+ } else if (strcmp(argv[i], "-nostartfiles") == 0)
+ nostartfiles = 1;
+ else
+ goto passa;
+ break;
+
+ case 'p':
+ if (strcmp(argv[i], "-pg") == 0)
+ pgflag++;
+ else if (strcmp(argv[i], "-pthread") == 0)
+ pthreads++;
+ else
+ errorx(1, "unknown option %s", argv[i]);
+ break;
+
+ case 'x':
+ xlist[xnum++] = argv[i];
+ break;
+ case 't':
+ tflag++;
+ break;
+ case 'S':
+ sflag++;
+ cflag++;
+ break;
+ case 'o':
+ if (outfile)
+ errorx(8, "too many -o");
+ outfile = argv[++i];
+ break;
+ case 'O':
+ Oflag++;
+ break;
+ case 'E':
+ Eflag++;
+ break;
+ case 'P':
+ pflag++;
+ *pv++ = argv[i];
+ case 'c':
+ cflag++;
+ break;
+
+#if 0
+ case '2':
+ if(argv[i][2] == '\0')
+ pref = "/lib/crt2.o";
+ else {
+ pref = "/lib/crt20.o";
+ }
+ break;
+#endif
+ case 'D':
+ case 'I':
+ case 'U':
+ case 'C':
+ *pv++ = argv[i];
+ if (argv[i][2] == 0)
+ *pv++ = argv[++i];
+ if (pv >= ptemp+MAXOPT)
+ {
+ error("Too many DIUC options");
+ --pv;
+ }
+ break;
+
+ case 'M':
+ Mflag++;
+ break;
+
+ case 'd':
+ dflag++;
+ strncpy(alist, argv[i], 19);
+ break;
+ case 'v':
+ printf("%s\n", VERSSTR);
+ vflag++;
+ break;
+
+ case 's':
+ if (strcmp(argv[i], "-static") == 0)
+ Bstatic = 1;
+ else
+ goto passa;
+ break;
+ } else {
+ passa:
+ t = argv[i];
+ if (*argv[i] == '-' && argv[i][1] == 'L')
+ ;
+ else if((c=getsuf(t))=='c' || c=='S' || c=='i' ||
+ c=='s'|| Eflag) {
+ clist[nc++] = t;
+ if (nc>=MAXFIL)
+ {
+ error("Too many source files");
+ exit(1);
+ }
+ t = setsuf(t, 'o');
+ }
+ if (nodup(llist, t)) {
+ llist[nl++] = t;
+ if (nl >= MAXLIB)
+ {
+ error("Too many object/library files");
+ exit(1);
+ }
+ if (getsuf(t)=='o')
+ nxo++;
+ }
+ }
+ }
+ /* Sanity checking */
+ if (nc == 0 && nl == 0)
+ errorx(8, "no input files");
+ if (outfile && (cflag || sflag || Eflag) && nc > 1)
+ errorx(8, "-o given with -c || -E || -S and more than one file");
+ if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
+ errorx(8, "output file will be clobbered");
+#if 0
+ for(i=0, j=0; i<nc; i++) {
+ if((c=getsuf(clist[i]))=='c' || c=='S') {
+ j++;
+ break;
+ }
+ }
+ if (j==0 && Eflag)
+ errorx(8, "no file to be preprocessed");
+#endif
+
+ if (gflag) Oflag = 0;
+#if 0
+ if (proflag)
+ pref = "/lib/mcrt0.o";
+#endif
+ if(nc==0)
+ goto nocom;
+ if (pflag==0) {
+ tmp3 = gettmp();
+ tmp4 = gettmp();
+ }
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */
+ signal(SIGINT, idexit);
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */
+ signal(SIGTERM, idexit);
+ pvt = pv;
+ for (i=0; i<nc; i++) {
+ /*
+ * C preprocessor
+ */
+ if (nc>1 && !Eflag)
+ printf("%s:\n", clist[i]);
+ onlyas = 0;
+ assource = tmp3;
+ if (getsuf(clist[i])=='i') {
+ if(Eflag)
+ continue;
+ goto com;
+ } else if (getsuf(clist[i])=='s') {
+ assource = clist[i];
+ onlyas = 1;
+ goto assemble;
+ } else if (getsuf(clist[i])=='S') {
+ assource = clist[i];
+ onlyas = 1;
+ }
+ if (pflag)
+ tmp4 = setsuf(clist[i], 'i');
+ na = 0;
+ av[na++] = "cpp";
+ if (vflag)
+ av[na++] = "-v";
+ av[na++] = "-D__PCC__=" MKS(PCC_MAJOR);
+ av[na++] = "-D__PCC_MINOR__=" MKS(PCC_MINOR);
+ av[na++] = "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR);
+ if (getsuf(clist[i])=='S')
+ av[na++] = "-D__ASSEMBLER__";
+ if (pthreads)
+ av[na++] = "-D_PTHREADS";
+ if (Mflag)
+ av[na++] = "-M";
+ if (dflag)
+ av[na++] = alist;
+ for (j = 0; cppadd[j]; j++)
+ av[na++] = cppadd[j];
+ for (j = 0; cppmdadd[j]; j++)
+ av[na++] = cppmdadd[j];
+ if (tflag)
+ av[na++] = "-t";
+ for(pv=ptemp; pv <pvt; pv++)
+ av[na++] = *pv;
+ if (!nostdinc)
+ av[na++] = "-S", av[na++] = STDINC;
+ av[na++] = clist[i];
+ if (!Eflag && !Mflag)
+ av[na++] = tmp4;
+ if (Eflag && outfile)
+ av[na++] = outfile;
+ av[na++]=0;
+ if (callsys(passp, av))
+ {exfail++; eflag++;}
+ if (Eflag || Mflag)
+ continue;
+ if (onlyas)
+ goto assemble;
+
+ /*
+ * C compiler
+ */
+ com:
+ na = 0;
+ av[na++]= "ccom";
+ if (vflag)
+ av[na++] = "-v";
+ if (gflag)
+ av[na++] = "-g";
+ if (kflag)
+ av[na++] = "-k";
+ if (Oflag) {
+ av[na++] = "-xtemps";
+ }
+ for (j = 0; j < xnum; j++)
+ av[na++] = xlist[j];
+ av[na++] = tmp4;
+ if (pflag || exfail)
+ {
+ cflag++;
+ continue;
+ }
+ if(sflag) {
+ if (outfile)
+ assource = tmp3 = outfile;
+ else
+ assource = tmp3 = setsuf(clist[i], 's');
+ }
+ av[na++] = tmp3;
+#if 0
+ if (proflag) {
+ av[3] = "-XP";
+ av[4] = 0;
+ } else
+ av[3] = 0;
+#endif
+ av[na++] = NULL;
+ if (callsys(pass0, av)) {
+ cflag++;
+ eflag++;
+ continue;
+ }
+ if (sflag)
+ continue;
+
+ /*
+ * Assembler
+ */
+ assemble:
+ na = 0;
+ av[na++] = "as";
+ if (vflag)
+ av[na++] = "-v";
+ if (kflag)
+ av[na++] = "-k";
+ av[na++] = "-o";
+ if (outfile && cflag)
+ av[na++] = outfile;
+ else
+ av[na++] = setsuf(clist[i], 'o');
+ av[na++] = onlyas ? tmp4 : assource;
+ if (dflag)
+ av[na++] = alist;
+ av[na++] = 0;
+ if (callsys("/bin/as", av)) {
+ cflag++;
+ eflag++;
+ cunlink(tmp4);
+ continue;
+ }
+ cunlink(tmp4);
+ }
+
+ if (Eflag || Mflag)
+ dexit(eflag);
+
+ /*
+ * Linker
+ */
+nocom:
+ if (cflag==0 && nl!=0) {
+ j = 0;
+ av[j++] = "ld";
+ if (vflag)
+ av[j++] = "-v";
+ av[j++] = "-X";
+ av[j++] = "-d";
+ av[j++] = "-e";
+ av[j++] = STARTLABEL;
+ if (Bstatic == 0) { /* Dynamic linkage */
+ for (i = 0; dynlinker[i]; i++)
+ av[j++] = dynlinker[i];
+ } else
+ av[j++] = "-Bstatic";
+ if (outfile) {
+ av[j++] = "-o";
+ av[j++] = outfile;
+ }
+ if (!nostartfiles) {
+ av[j++] = crt0file;
+ for (i = 0; startfiles[i]; i++)
+ av[j++] = startfiles[i];
+ }
+ i = 0;
+ while(i<nl) {
+ av[j++] = llist[i++];
+ if (j >= MAXAV)
+ error("Too many ld options");
+ }
+#if 0
+ if (gflag)
+ av[j++] = "-lg";
+#endif
+ if (pthreads)
+ av[j++] = "-lpthread";
+ if (!nostdlib)
+ for (i = 0; libclibs[i]; i++)
+ av[j++] = libclibs[i];
+ if (!nostartfiles) {
+ for (i = 0; endfiles[i]; i++)
+ av[j++] = endfiles[i];
+ }
+ av[j++] = 0;
+ eflag |= callsys("/bin/ld", av);
+ if (nc==1 && nxo==1 && eflag==0)
+ cunlink(setsuf(clist[0], 'o'));
+ else if (nc > 0 && eflag == 0) {
+ /* remove .o files XXX ugly */
+ for (i = 0; i < nc; i++)
+ cunlink(setsuf(clist[i], 'o'));
+ }
+ }
+ dexit(eflag);
+ return 0;
+}
+
+/*
+ * exit and cleanup after interrupt.
+ */
+void
+idexit(int arg)
+{
+ dexit(100);
+}
+
+/*
+ * exit and cleanup.
+ */
+void
+dexit(int eval)
+{
+ if (!pflag && !Xflag) {
+ if (sflag==0)
+ cunlink(tmp3);
+ cunlink(tmp4);
+ }
+ exit(eval);
+}
+
+static void
+ccerror(char *s, va_list ap)
+{
+ vfprintf(Eflag ? stderr : stdout, s, ap);
+ putc('\n', Eflag? stderr : stdout);
+ exfail++;
+ cflag++;
+ eflag++;
+}
+
+/*
+ * complain a bit.
+ */
+void
+error(char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ ccerror(s, ap);
+ va_end(ap);
+}
+
+/*
+ * complain a bit and then exit.
+ */
+void
+errorx(int eval, char *s, ...)
+{
+ va_list ap;
+
+ va_start(ap, s);
+ ccerror(s, ap);
+ va_end(ap);
+ dexit(eval);
+}
+
+int
+getsuf(as)
+char as[];
+{
+ register char *s;
+
+ if ((s = strrchr(as, '.')) && s[1] != '\0' && s[2] == '\0')
+ return s[1];
+ return(0);
+}
+
+/*
+ * Get basename of string s and change its suffix to ch.
+ */
+char *
+setsuf(char *s, char ch)
+{
+ s = copy(basename(s));
+ s[strlen(s) - 1] = ch;
+ return(s);
+}
+
+int
+callsys(char f[], char *v[])
+{
+ int status;
+ pid_t t;
+ char *s;
+
+ if (vflag) {
+ fprintf(stderr, "%s ", f);
+ for (t = 1; v[t]; t++)
+ fprintf(stderr, "%s ", v[t]);
+ fprintf(stderr, "\n");
+ }
+
+ if ((t=fork())==0) {
+ if (Bflag) {
+ size_t len = strlen(Bflag) + 8;
+ char *a = malloc(len);
+ if (a == NULL)
+ errorx(1, "callsys: malloc failed\n");
+ if ((s = strrchr(f, '/'))) {
+ strlcpy(a, Bflag, len);
+ strlcat(a, s, len);
+ execv(a, v);
+ }
+ }
+ execv(f, v);
+ if ((s = strrchr(f, '/')))
+ execvp(s+1, v);
+ printf("Can't find %s\n", f);
+ exit(100);
+ } else
+ if (t == -1) {
+ printf("Try again\n");
+ return(100);
+ }
+ while(t!=wait(&status));
+ if ((t=(status&0377)) != 0 && t!=14) {
+ if (t!=2) /* interrupt */
+ errorx(8, "Fatal error in %s", f);
+ dexit(eflag);
+ }
+ return((status>>8) & 0377);
+}
+
+char *
+copy(char *as)
+{
+ char *p;
+
+ if ((p = strdup(as)) == NULL)
+ errorx(8, "no space for file names");
+
+ return p;
+}
+
+int
+nodup(l, os)
+char **l, *os;
+{
+ register char *t, *s;
+ register int c;
+
+ s = os;
+ if (getsuf(s) != 'o')
+ return(1);
+ while((t = *l++)) {
+ while((c = *s++))
+ if (c != *t++)
+ break;
+ if (*t=='\0' && c=='\0')
+ return(0);
+ s = os;
+ }
+ return(1);
+}
+
+int
+cunlink(f)
+char *f;
+{
+ if (f==0 || Xflag)
+ return(0);
+ return(unlink(f));
+}
+
+char *
+gettmp()
+{
+ char *sfn = strdup("/tmp/ctm.XXXXXX");
+ int fd = -1;
+
+ if ((fd = mkstemp(sfn)) == -1) {
+ fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
+ exit(8);
+ }
+ close(fd);
+
+ return sfn;
+}
--- /dev/null
+++ usr.bin/pcc/cc/cc.1
@@ -0,0 +1,275 @@
+.\" $Id: cc.1,v 1.4 2007/09/26 14:48:47 ragge Exp $
+.\" $NetBSD$
+.\" $OpenBSD$
+."\
+.\" Copyright (c) 2007 Jeremy C. Reed <reed at 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 14, 2007
+.Dt cc 1
+.Os
+.Sh NAME
+.Nm cc
+.Nd front-end to the C compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl cdEgkLMPOStvxX
+.Op Fl B Ar prefix
+.Op Fl fPIC
+.Op Fl include Ar path
+.Op Fl isystem Ar path
+.Op Fl nostdinc
+.Op Fl nostdlib
+.Op Fl nostartfiles
+.Op Fl o Ar outfile
+.Op Fl pg
+.Op Fl pthread
+.Op Fl static
+.Op Fl Wl Ar flags
+.Op Ar infile ...
+.Pp
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a front-end to the
+.Dq portable C compiler.
+Multiple files may be given on the command line.
+Unrecognized options are all sent directly to
+.Xr ld 1 .
+.Pp
+.\" Brief description of its syntax:
+Filenames that end with
+.Sy .c
+are passed via
+.Xr cpp 1 ->
+.Xr ccom 1 ->
+.Xr as 1 ->
+.Xr ld 1 .
+.Pp
+Filenames that end with
+.Sy .i
+are passed via
+.Xr ccom 1 ->
+.Xr as 1 ->
+.Xr ld 1 .
+.Pp
+Filenames that end with
+.Sy .s
+are passed via
+.Xr as 1 ->
+.Xr ld 1 .
+.Pp
+Filenames that end with
+.Sy .o
+are passed directly to
+.Xr ld 1 .
+.Pp
+.\"
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl B Ar prefix
+Define alternate prefix path for
+.Xr cpp 1 ,
+.Xr ccom 1 ,
+.Xr as 1 ,
+or
+.Xr ld 1
+executables.
+.\" TODO: provide an example of -B
+.It Fl c
+Only compile or assemble and then stop.
+Do not link.
+The resulting object output is saved
+as a filename with a
+.Dq .o
+suffix unless
+.Fl o
+option is used.
+Note: cannot be combined with
+.Fl o
+if multiple files are given.
+.It Fl d Ar option
+Passed to the
+.Xr as 1
+assembler.
+.\" TODO: what is as -dfoo for?
+.It Fl D Ar macro[=value]
+Passed to the
+.Xr cpp 1
+preprocessor to define
+.Ar macro .
+.It Fl E
+Stop after preprocessing with
+.Xr cpp 1 .
+Do not compile, assemble, or link.
+.It Fl fpic
+Tells C compiler to generate PIC code
+and tells assembler that PIC code has been generated.
+.\" TODO: document difference between PIC and pic
+.It Fl fPIC
+Generate PIC code.
+.\" TODO: document about avoiding machine-specific maximum size?
+.\" other -f GCC compatibility flags are ignored for now
+.It Fl g
+Send
+.Fl g
+flag to
+.Xr ccom 1
+to create debug output.
+This unsets the
+.Fl O
+option.
+.It Fl include Ar path
+.\" TODO
+.It Fl isystem Ar path
+.\" TODO
+.It Fl k
+Generate PIC code.
+See
+.Fl fpic
+option.
+.It Fl I Ar path
+Passed to the
+.Xr cpp 1
+preprocessor to add header search directory to override system defaults.
+.It Fl L
+.\" TODO
+.It Fl M
+Pass
+.Fl M
+flag to
+.Xr cpp 1
+to generate dependencies for
+.Xr make 1 .
+.It Fl nostdinc
+.\" TODO
+.It Fl nostdlib
+.\" TODO
+.\" implies -nostartfiles ??
+.It Fl nostartfiles
+.\" TODO
+.It Fl o Ar outfile
+Save result to
+.Ar outfile .
+.It Fl P
+TODO: what is this?
+.\" TODO: Looks like it does cpp only, but I couldn't get it to work for me.
+.It Fl pg
+Not implemented.
+.It Fl O
+Enable optimizations.
+Currently passes
+.Fl xtemps
+to
+.Xr ccom 1 .
+Note: this is unset if
+.Fl g
+option is set.
+.It Fl pthread
+Defines
+.Sy _PTHREADS
+preprocessor directive for
+.Xr cpp 1 .
+Uses
+.Sy -lpthread
+for
+.Xr ld 1 linker.
+.It Fl static
+Do not use dynamic linkage.
+By default, it will link using the dynamic linker options
+and/or shared objects for the platform.
+.It Fl S
+Stop after compilation by
+.Xr ccom 1 .
+Do not assemble and do not link.
+The resulting assembler-language output is saved
+as a filename with a
+.Dq .s
+suffix unless the
+.Fl o
+option is used.
+Note: cannot be combined with
+.Fl o
+if multiple files are given.
+.It Fl t
+Passes
+.Fl t
+to
+.Xr cpp 1
+for traditional C preprocessor syntax.
+.It Fl U Ar macro
+Passed to the
+.Xr cpp 1
+preprocessor to remove the initial macro definition.
+.It Fl v
+Outputs the version of
+.Nm
+and shows what commands will be ran with their command line arguments.
+.It Fl x
+TODO
+.It Fl X
+TODO
+.It Fl Wl Ar flags
+Options for the linker
+.\" what is ignored? llist?
+.El
+.Sh Predefined Macros
+A few
+macros are predefined by
+.Nm
+went sent to
+.Xr cpp 1 .
+.Bl -diag
+.\" TODO:
+.\" .It __ASSEMBLER__
+.\" Defined if suffix is .S -- why not with .s? what does this mean?
+.It __PCC__
+Set to the major version of
+.Xr pcc 1 .
+These macros can be used to select code based on
+.Xr pcc 1
+compatibility.
+See
+.Fl v
+option.
+.It __PCC_MINOR__
+Set to the minor version.
+.It __PCC_MINORMINOR__
+Set to the minor-minor version -- the number after the minor version.
+.It _PTHREADS
+Defined when
+.Fl pthread
+switch is used.
+.El
+.Pp
+Also system- and/or machine-dependent macros may also be predefined;
+for example:
+.Dv __NetBSD__ ,
+.Dv __ELF__ ,
+and
+.Dv __i386__ .
+.Sh SEE ALSO
+.Xr as 1 ,
+.Xr ccom 1 ,
+.Xr cpp 1 ,
+.Xr ld 1
+.Sh HISTORY
+The
+.Nm
+command comes from the original Portable C Compiler by S. C.
+Johnson, written in the late 70's.
+.Pp
+This product includes software developed or owned by Caldera
+International, Inc.
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cc/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -L usr.bin/pcc/cc/Makefile -L usr.bin/pcc/cc/Makefile -u -r1.1 -r1.2
--- usr.bin/pcc/cc/Makefile
+++ usr.bin/pcc/cc/Makefile
@@ -1,38 +1,14 @@
-# $Id: Makefile.in,v 1.2 2005/05/14 13:28:21 ragge Exp $
-#
-# Makefile.in for top-level of pcc.
-#
+# $MidnightBSD$
+PROG= cc
+PREFIX= /usr/local
+BINDIR= ${PREFIX}/bin
+MANDIR= ${PREFIX}/man
+TARGOS= midnightbsd
+TARGMACH= ${MACHINE_ARCH}
+
+CFLAGS+= -DLIBEXECDIR=\"${PREFIX}\"
+CFLAGS+= -I${.CURDIR}/..
+CFLAGS+= -Dmach_${TARGMACH} -Dos_${TARGOS}
-CC=gcc
-CFLAGS=-g
-LDFLAGS=
-CPPFLAGS=
-YACC=yacc
-LEX=flex
-
-SUBDIR=cc cpp ccom
-
-all: ${SUBDIR}
-
-install:
- cd cc && ${MAKE} install
- cd cpp && ${MAKE} install
- cd ccom && ${MAKE} install
-
-clean:
- cd cc && ${MAKE} clean
- cd cpp && ${MAKE} clean
- cd ccom && ${MAKE} clean
-
-distclean:
- cd cc && ${MAKE} distclean
- cd cpp && ${MAKE} distclean
- cd ccom && ${MAKE} distclean
- /bin/rm -rf Makefile config.log stamp-h1 config.status \
- configure.lineno config.h autom4te.cache
-
-${SUBDIR}: nonexistant
- cd $@; $(MAKE) all $(MFLAGS)
-
-nonexistant:
+.include <bsd.prog.mk>
--- usr.bin/pcc/cc/cc/cc.c
+++ /dev/null
@@ -1,736 +0,0 @@
-/* $Id: cc.c,v 1.61 2007/09/26 14:48:47 ragge Exp $ */
-/*
- * 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 conditionsand 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.
- */
-
-/*
- * Front-end to the C compiler.
- *
- * Brief description of its syntax:
- * - Files that end with .c are passed via cpp->ccom->as->ld
- * - Files that end with .i are passed via ccom->as->ld
- * - Files that end with .s are passed as->ld
- * - Files that end with .o are passed directly to ld
- * - Multiple files may be given on the command line.
- * - Unrecognized options are all sent directly to ld.
- * -c or -S cannot be combined with -o if multiple files are given.
- *
- * This file should be rewritten readable.
- */
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <libgen.h>
-#include <errno.h>
-
-#include "../../config.h"
-
-#include "ccconfig.h"
-/* C command */
-
-#define MKS(x) _MKS(x)
-#define _MKS(x) #x
-
-/*
- * Many specific definitions, should be declared elsewhere.
- */
-#define STDINC "/usr/include/"
-
-#define SBSIZE 10000
-#define MAXINC 100
-#define MAXFIL 100
-#define MAXLIB 10000
-#define MAXAV 10000
-#define MAXOPT 100
-char *tmp3;
-char *tmp4;
-char *outfile;
-char *copy(char *as),*setsuf(char *as, char ch);
-int getsuf(char []);
-int main(int, char *[]);
-void error(char *, ...);
-void errorx(int eval, char *, ...);
-int nodup(char **, char *);
-int callsys(char [], char *[]);
-int cunlink(char *);
-void dexit(int eval);
-void idexit(int);
-char *gettmp();
-char *av[MAXAV];
-char *clist[MAXFIL];
-char *llist[MAXLIB];
-char alist[20];
-char *xlist[100];
-int xnum;
-int dflag;
-int pflag;
-int sflag;
-int cflag;
-int eflag;
-int gflag;
-int vflag;
-int tflag;
-int Eflag;
-int Oflag;
-int kflag; /* generate PIC/pic code */
-#define F_PIC 1
-#define F_pic 2
-int Mflag; /* dependencies only */
-int pgflag;
-int exfail;
-int Xflag;
-int nostartfiles, Bstatic;
-int nostdinc, nostdlib;
-int onlyas;
-int pthreads;
-
-char *pass0 = LIBEXECDIR "/ccom";
-char *passp = LIBEXECDIR "/cpp";
-char *Bflag;
-char *cppadd[] = CPPADD;
-char *dynlinker[] = DYNLINKER;
-char *crt0file = CRT0FILE;
-char *startfiles[] = STARTFILES;
-char *endfiles[] = ENDFILES;
-char *cppmdadd[] = CPPMDADD;
-#ifdef LIBCLIBS
-char *libclibs[] = LIBCLIBS;
-#else
-char *libclibs[] = { "-lc", NULL };
-#endif
-#ifndef STARTLABEL
-#define STARTLABEL "__start"
-#endif
-
-int
-main(int argc, char *argv[])
-{
- char *t, *u;
- char *assource;
- char **pv, *ptemp[MAXOPT], **pvt;
- int nc, nl, i, j, c, nxo, na;
-
- i = nc = nl = nxo = 0;
- pv = ptemp;
- while(++i < argc) {
- if (argv[i][0] == '-')
- switch (argv[i][1]) {
- default:
- goto passa;
-
- case 'B': /* other search paths for binaries */
- Bflag = &argv[i][2];
- break;
-
- case 'X':
- Xflag++;
- break;
- case 'W': /* Ignore (most of) W-flags */
- if (strncmp(argv[i], "-Wl,", 4) == 0) {
- /* options to the linker */
- t = &argv[i][4];
- while ((u = strchr(t, ','))) {
- *u++ = 0;
- llist[nl++] = t;
- t = u;
- }
- llist[nl++] = t;
- }
- break;
-
- case 'f': /* GCC compatibility flags */
- if (strcmp(argv[i], "-fPIC") == 0)
- kflag = F_PIC;
- if (strcmp(argv[i], "-fpic") == 0)
- kflag = F_pic;
- /* silently ignore the rest */
- break;
-
- case 'g': /* create debug output */
- gflag++;
- break;
-
- case 'i':
- if (strcmp(argv[i], "-isystem") == 0) {
- *pv++ = "-S";
- *pv++ = argv[++i];
- } else if (strcmp(argv[i], "-include") == 0) {
- *pv++ = "-i";
- *pv++ = argv[++i];
- } else
- goto passa;
- break;
-
- case 'k': /* generate PIC code */
- kflag = F_pic;
- break;
-
- case 'n': /* handle -n flags */
- if (strcmp(argv[i], "-nostdinc") == 0)
- nostdinc++;
- if (strcmp(argv[i], "-nostdlib") == 0) {
- nostdlib++;
- nostartfiles++;
- } else if (strcmp(argv[i], "-nostartfiles") == 0)
- nostartfiles = 1;
- else
- goto passa;
- break;
-
- case 'p':
- if (strcmp(argv[i], "-pg") == 0)
- pgflag++;
- else if (strcmp(argv[i], "-pthread") == 0)
- pthreads++;
- else
- errorx(1, "unknown option %s", argv[i]);
- break;
-
- case 'x':
- xlist[xnum++] = argv[i];
- break;
- case 't':
- tflag++;
- break;
- case 'S':
- sflag++;
- cflag++;
- break;
- case 'o':
- if (outfile)
- errorx(8, "too many -o");
- outfile = argv[++i];
- break;
- case 'O':
- Oflag++;
- break;
- case 'E':
- Eflag++;
- break;
- case 'P':
- pflag++;
- *pv++ = argv[i];
- case 'c':
- cflag++;
- break;
-
-#if 0
- case '2':
- if(argv[i][2] == '\0')
- pref = "/lib/crt2.o";
- else {
- pref = "/lib/crt20.o";
- }
- break;
-#endif
- case 'D':
- case 'I':
- case 'U':
- case 'C':
- *pv++ = argv[i];
- if (argv[i][2] == 0)
- *pv++ = argv[++i];
- if (pv >= ptemp+MAXOPT)
- {
- error("Too many DIUC options");
- --pv;
- }
- break;
-
- case 'M':
- Mflag++;
- break;
-
- case 'd':
- dflag++;
- strncpy(alist, argv[i], 19);
- break;
- case 'v':
- printf("%s\n", VERSSTR);
- vflag++;
- break;
-
- case 's':
- if (strcmp(argv[i], "-static") == 0)
- Bstatic = 1;
- else
- goto passa;
- break;
- } else {
- passa:
- t = argv[i];
- if (*argv[i] == '-' && argv[i][1] == 'L')
- ;
- else if((c=getsuf(t))=='c' || c=='S' || c=='i' ||
- c=='s'|| Eflag) {
- clist[nc++] = t;
- if (nc>=MAXFIL)
- {
- error("Too many source files");
- exit(1);
- }
- t = setsuf(t, 'o');
- }
- if (nodup(llist, t)) {
- llist[nl++] = t;
- if (nl >= MAXLIB)
- {
- error("Too many object/library files");
- exit(1);
- }
- if (getsuf(t)=='o')
- nxo++;
- }
- }
- }
- /* Sanity checking */
- if (nc == 0 && nl == 0)
- errorx(8, "no input files");
- if (outfile && (cflag || sflag || Eflag) && nc > 1)
- errorx(8, "-o given with -c || -E || -S and more than one file");
- if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
- errorx(8, "output file will be clobbered");
-#if 0
- for(i=0, j=0; i<nc; i++) {
- if((c=getsuf(clist[i]))=='c' || c=='S') {
- j++;
- break;
- }
- }
- if (j==0 && Eflag)
- errorx(8, "no file to be preprocessed");
-#endif
-
- if (gflag) Oflag = 0;
-#if 0
- if (proflag)
- pref = "/lib/mcrt0.o";
-#endif
- if(nc==0)
- goto nocom;
- if (pflag==0) {
- tmp3 = gettmp();
- tmp4 = gettmp();
- }
- if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */
- signal(SIGINT, idexit);
- if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */
- signal(SIGTERM, idexit);
- pvt = pv;
- for (i=0; i<nc; i++) {
- /*
- * C preprocessor
- */
- if (nc>1 && !Eflag)
- printf("%s:\n", clist[i]);
- onlyas = 0;
- assource = tmp3;
- if (getsuf(clist[i])=='i') {
- if(Eflag)
- continue;
- goto com;
- } else if (getsuf(clist[i])=='s') {
- assource = clist[i];
- onlyas = 1;
- goto assemble;
- } else if (getsuf(clist[i])=='S') {
- assource = clist[i];
- onlyas = 1;
- }
- if (pflag)
- tmp4 = setsuf(clist[i], 'i');
- na = 0;
- av[na++] = "cpp";
- if (vflag)
- av[na++] = "-v";
- av[na++] = "-D__PCC__=" MKS(PCC_MAJOR);
- av[na++] = "-D__PCC_MINOR__=" MKS(PCC_MINOR);
- av[na++] = "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR);
- if (getsuf(clist[i])=='S')
- av[na++] = "-D__ASSEMBLER__";
- if (pthreads)
- av[na++] = "-D_PTHREADS";
- if (Mflag)
- av[na++] = "-M";
- if (dflag)
- av[na++] = alist;
- for (j = 0; cppadd[j]; j++)
- av[na++] = cppadd[j];
- for (j = 0; cppmdadd[j]; j++)
- av[na++] = cppmdadd[j];
- if (tflag)
- av[na++] = "-t";
- for(pv=ptemp; pv <pvt; pv++)
- av[na++] = *pv;
- if (!nostdinc)
- av[na++] = "-S", av[na++] = STDINC;
- av[na++] = clist[i];
- if (!Eflag && !Mflag)
- av[na++] = tmp4;
- if (Eflag && outfile)
- av[na++] = outfile;
- av[na++]=0;
- if (callsys(passp, av))
- {exfail++; eflag++;}
- if (Eflag || Mflag)
- continue;
- if (onlyas)
- goto assemble;
-
- /*
- * C compiler
- */
- com:
- na = 0;
- av[na++]= "ccom";
- if (vflag)
- av[na++] = "-v";
- if (gflag)
- av[na++] = "-g";
- if (kflag)
- av[na++] = "-k";
- if (Oflag) {
- av[na++] = "-xtemps";
- }
- for (j = 0; j < xnum; j++)
- av[na++] = xlist[j];
- av[na++] = tmp4;
- if (pflag || exfail)
- {
- cflag++;
- continue;
- }
- if(sflag) {
- if (outfile)
- assource = tmp3 = outfile;
- else
- assource = tmp3 = setsuf(clist[i], 's');
- }
- av[na++] = tmp3;
-#if 0
- if (proflag) {
- av[3] = "-XP";
- av[4] = 0;
- } else
- av[3] = 0;
-#endif
- av[na++] = NULL;
- if (callsys(pass0, av)) {
- cflag++;
- eflag++;
- continue;
- }
- if (sflag)
- continue;
-
- /*
- * Assembler
- */
- assemble:
- na = 0;
- av[na++] = "as";
- if (vflag)
- av[na++] = "-v";
- if (kflag)
- av[na++] = "-k";
- av[na++] = "-o";
- if (outfile && cflag)
- av[na++] = outfile;
- else
- av[na++] = setsuf(clist[i], 'o');
- av[na++] = onlyas ? tmp4 : assource;
- if (dflag)
- av[na++] = alist;
- av[na++] = 0;
- if (callsys("/bin/as", av)) {
- cflag++;
- eflag++;
- cunlink(tmp4);
- continue;
- }
- cunlink(tmp4);
- }
-
- if (Eflag || Mflag)
- dexit(eflag);
-
- /*
- * Linker
- */
-nocom:
- if (cflag==0 && nl!=0) {
- j = 0;
- av[j++] = "ld";
- if (vflag)
- av[j++] = "-v";
- av[j++] = "-X";
- av[j++] = "-d";
- av[j++] = "-e";
- av[j++] = STARTLABEL;
- if (Bstatic == 0) { /* Dynamic linkage */
- for (i = 0; dynlinker[i]; i++)
- av[j++] = dynlinker[i];
- } else
- av[j++] = "-Bstatic";
- if (outfile) {
- av[j++] = "-o";
- av[j++] = outfile;
- }
- if (!nostartfiles) {
- av[j++] = crt0file;
- for (i = 0; startfiles[i]; i++)
- av[j++] = startfiles[i];
- }
- i = 0;
- while(i<nl) {
- av[j++] = llist[i++];
- if (j >= MAXAV)
- error("Too many ld options");
- }
-#if 0
- if (gflag)
- av[j++] = "-lg";
-#endif
- if (pthreads)
- av[j++] = "-lpthread";
- if (!nostdlib)
- for (i = 0; libclibs[i]; i++)
- av[j++] = libclibs[i];
- if (!nostartfiles) {
- for (i = 0; endfiles[i]; i++)
- av[j++] = endfiles[i];
- }
- av[j++] = 0;
- eflag |= callsys("/bin/ld", av);
- if (nc==1 && nxo==1 && eflag==0)
- cunlink(setsuf(clist[0], 'o'));
- else if (nc > 0 && eflag == 0) {
- /* remove .o files XXX ugly */
- for (i = 0; i < nc; i++)
- cunlink(setsuf(clist[i], 'o'));
- }
- }
- dexit(eflag);
- return 0;
-}
-
-/*
- * exit and cleanup after interrupt.
- */
-void
-idexit(int arg)
-{
- dexit(100);
-}
-
-/*
- * exit and cleanup.
- */
-void
-dexit(int eval)
-{
- if (!pflag && !Xflag) {
- if (sflag==0)
- cunlink(tmp3);
- cunlink(tmp4);
- }
- exit(eval);
-}
-
-static void
-ccerror(char *s, va_list ap)
-{
- vfprintf(Eflag ? stderr : stdout, s, ap);
- putc('\n', Eflag? stderr : stdout);
- exfail++;
- cflag++;
- eflag++;
-}
-
-/*
- * complain a bit.
- */
-void
-error(char *s, ...)
-{
- va_list ap;
-
- va_start(ap, s);
- ccerror(s, ap);
- va_end(ap);
-}
-
-/*
- * complain a bit and then exit.
- */
-void
-errorx(int eval, char *s, ...)
-{
- va_list ap;
-
- va_start(ap, s);
- ccerror(s, ap);
- va_end(ap);
- dexit(eval);
-}
-
-int
-getsuf(as)
-char as[];
-{
- register char *s;
-
- if ((s = strrchr(as, '.')) && s[1] != '\0' && s[2] == '\0')
- return s[1];
- return(0);
-}
-
-/*
- * Get basename of string s and change its suffix to ch.
- */
-char *
-setsuf(char *s, char ch)
-{
- s = copy(basename(s));
- s[strlen(s) - 1] = ch;
- return(s);
-}
-
-int
-callsys(char f[], char *v[])
-{
- int status;
- pid_t t;
- char *s;
-
- if (vflag) {
- fprintf(stderr, "%s ", f);
- for (t = 1; v[t]; t++)
- fprintf(stderr, "%s ", v[t]);
- fprintf(stderr, "\n");
- }
-
- if ((t=fork())==0) {
- if (Bflag) {
- size_t len = strlen(Bflag) + 8;
- char *a = malloc(len);
- if (a == NULL)
- errorx(1, "callsys: malloc failed\n");
- if ((s = strrchr(f, '/'))) {
- strlcpy(a, Bflag, len);
- strlcat(a, s, len);
- execv(a, v);
- }
- }
- execv(f, v);
- if ((s = strrchr(f, '/')))
- execvp(s+1, v);
- printf("Can't find %s\n", f);
- exit(100);
- } else
- if (t == -1) {
- printf("Try again\n");
- return(100);
- }
- while(t!=wait(&status));
- if ((t=(status&0377)) != 0 && t!=14) {
- if (t!=2) /* interrupt */
- errorx(8, "Fatal error in %s", f);
- dexit(eflag);
- }
- return((status>>8) & 0377);
-}
-
-char *
-copy(char *as)
-{
- char *p;
-
- if ((p = strdup(as)) == NULL)
- errorx(8, "no space for file names");
-
- return p;
-}
-
-int
-nodup(l, os)
-char **l, *os;
-{
- register char *t, *s;
- register int c;
-
- s = os;
- if (getsuf(s) != 'o')
- return(1);
- while((t = *l++)) {
- while((c = *s++))
- if (c != *t++)
- break;
- if (*t=='\0' && c=='\0')
- return(0);
- s = os;
- }
- return(1);
-}
-
-int
-cunlink(f)
-char *f;
-{
- if (f==0 || Xflag)
- return(0);
- return(unlink(f));
-}
-
-char *
-gettmp()
-{
- char *sfn = strdup("/tmp/ctm.XXXXXX");
- int fd = -1;
-
- if ((fd = mkstemp(sfn)) == -1) {
- fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
- exit(8);
- }
- close(fd);
-
- return sfn;
-}
--- usr.bin/pcc/cc/cc/cc.1
+++ /dev/null
@@ -1,275 +0,0 @@
-.\" $Id: cc.1,v 1.4 2007/09/26 14:48:47 ragge Exp $
-.\" $NetBSD$
-.\" $OpenBSD$
-."\
-.\" Copyright (c) 2007 Jeremy C. Reed <reed at 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 14, 2007
-.Dt cc 1
-.Os
-.Sh NAME
-.Nm cc
-.Nd front-end to the C compiler
-.Sh SYNOPSIS
-.Nm
-.Op Fl cdEgkLMPOStvxX
-.Op Fl B Ar prefix
-.Op Fl fPIC
-.Op Fl include Ar path
-.Op Fl isystem Ar path
-.Op Fl nostdinc
-.Op Fl nostdlib
-.Op Fl nostartfiles
-.Op Fl o Ar outfile
-.Op Fl pg
-.Op Fl pthread
-.Op Fl static
-.Op Fl Wl Ar flags
-.Op Ar infile ...
-.Pp
-.Sh DESCRIPTION
-The
-.Nm
-utility provides a front-end to the
-.Dq portable C compiler.
-Multiple files may be given on the command line.
-Unrecognized options are all sent directly to
-.Xr ld 1 .
-.Pp
-.\" Brief description of its syntax:
-Filenames that end with
-.Sy .c
-are passed via
-.Xr cpp 1 ->
-.Xr ccom 1 ->
-.Xr as 1 ->
-.Xr ld 1 .
-.Pp
-Filenames that end with
-.Sy .i
-are passed via
-.Xr ccom 1 ->
-.Xr as 1 ->
-.Xr ld 1 .
-.Pp
-Filenames that end with
-.Sy .s
-are passed via
-.Xr as 1 ->
-.Xr ld 1 .
-.Pp
-Filenames that end with
-.Sy .o
-are passed directly to
-.Xr ld 1 .
-.Pp
-.\"
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl B Ar prefix
-Define alternate prefix path for
-.Xr cpp 1 ,
-.Xr ccom 1 ,
-.Xr as 1 ,
-or
-.Xr ld 1
-executables.
-.\" TODO: provide an example of -B
-.It Fl c
-Only compile or assemble and then stop.
-Do not link.
-The resulting object output is saved
-as a filename with a
-.Dq .o
-suffix unless
-.Fl o
-option is used.
-Note: cannot be combined with
-.Fl o
-if multiple files are given.
-.It Fl d Ar option
-Passed to the
-.Xr as 1
-assembler.
-.\" TODO: what is as -dfoo for?
-.It Fl D Ar macro[=value]
-Passed to the
-.Xr cpp 1
-preprocessor to define
-.Ar macro .
-.It Fl E
-Stop after preprocessing with
-.Xr cpp 1 .
-Do not compile, assemble, or link.
-.It Fl fpic
-Tells C compiler to generate PIC code
-and tells assembler that PIC code has been generated.
-.\" TODO: document difference between PIC and pic
-.It Fl fPIC
-Generate PIC code.
-.\" TODO: document about avoiding machine-specific maximum size?
-.\" other -f GCC compatibility flags are ignored for now
-.It Fl g
-Send
-.Fl g
-flag to
-.Xr ccom 1
-to create debug output.
-This unsets the
-.Fl O
-option.
-.It Fl include Ar path
-.\" TODO
-.It Fl isystem Ar path
-.\" TODO
-.It Fl k
-Generate PIC code.
-See
-.Fl fpic
-option.
-.It Fl I Ar path
-Passed to the
-.Xr cpp 1
-preprocessor to add header search directory to override system defaults.
-.It Fl L
-.\" TODO
-.It Fl M
-Pass
-.Fl M
-flag to
-.Xr cpp 1
-to generate dependencies for
-.Xr make 1 .
-.It Fl nostdinc
-.\" TODO
-.It Fl nostdlib
-.\" TODO
-.\" implies -nostartfiles ??
-.It Fl nostartfiles
-.\" TODO
-.It Fl o Ar outfile
-Save result to
-.Ar outfile .
-.It Fl P
-TODO: what is this?
-.\" TODO: Looks like it does cpp only, but I couldn't get it to work for me.
-.It Fl pg
-Not implemented.
-.It Fl O
-Enable optimizations.
-Currently passes
-.Fl xtemps
-to
-.Xr ccom 1 .
-Note: this is unset if
-.Fl g
-option is set.
-.It Fl pthread
-Defines
-.Sy _PTHREADS
-preprocessor directive for
-.Xr cpp 1 .
-Uses
-.Sy -lpthread
-for
-.Xr ld 1 linker.
-.It Fl static
-Do not use dynamic linkage.
-By default, it will link using the dynamic linker options
-and/or shared objects for the platform.
-.It Fl S
-Stop after compilation by
-.Xr ccom 1 .
-Do not assemble and do not link.
-The resulting assembler-language output is saved
-as a filename with a
-.Dq .s
-suffix unless the
-.Fl o
-option is used.
-Note: cannot be combined with
-.Fl o
-if multiple files are given.
-.It Fl t
-Passes
-.Fl t
-to
-.Xr cpp 1
-for traditional C preprocessor syntax.
-.It Fl U Ar macro
-Passed to the
-.Xr cpp 1
-preprocessor to remove the initial macro definition.
-.It Fl v
-Outputs the version of
-.Nm
-and shows what commands will be ran with their command line arguments.
-.It Fl x
-TODO
-.It Fl X
-TODO
-.It Fl Wl Ar flags
-Options for the linker
-.\" what is ignored? llist?
-.El
-.Sh Predefined Macros
-A few
-macros are predefined by
-.Nm
-went sent to
-.Xr cpp 1 .
-.Bl -diag
-.\" TODO:
-.\" .It __ASSEMBLER__
-.\" Defined if suffix is .S -- why not with .s? what does this mean?
-.It __PCC__
-Set to the major version of
-.Xr pcc 1 .
-These macros can be used to select code based on
-.Xr pcc 1
-compatibility.
-See
-.Fl v
-option.
-.It __PCC_MINOR__
-Set to the minor version.
-.It __PCC_MINORMINOR__
-Set to the minor-minor version -- the number after the minor version.
-.It _PTHREADS
-Defined when
-.Fl pthread
-switch is used.
-.El
-.Pp
-Also system- and/or machine-dependent macros may also be predefined;
-for example:
-.Dv __NetBSD__ ,
-.Dv __ELF__ ,
-and
-.Dv __i386__ .
-.Sh SEE ALSO
-.Xr as 1 ,
-.Xr ccom 1 ,
-.Xr cpp 1 ,
-.Xr ld 1
-.Sh HISTORY
-The
-.Nm
-command comes from the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
-.Pp
-This product includes software developed or owned by Caldera
-International, Inc.
--- usr.bin/pcc/cc/cc/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-# $Id: Makefile.in,v 1.9 2007/09/26 14:48:47 ragge Exp $
-#
-# Makefile.in for the cc part of pcc.
-#
-prefix = /usr/local
-exec_prefix = ${prefix}
-bindir = ${exec_prefix}/bin
-libexecdir = ${exec_prefix}/libexec
-datarootdir = ${prefix}/share
-mandir = ${datarootdir}/man
-#strip = yes
-CC = gcc
-TARGOS = midnightbsd
-TARGMACH = x86
-CFLAGS = -g -DLIBEXECDIR=\"${libexecdir}\" -DINCLUDEDIR=\"${includedir}\" -static-libgcc
-CPPFLAGS = -I../../os/${TARGOS} -I${MDIR} -Dmach_${TARGMACH} -Dos_${TARGOS}
-LIBS =
-LDFLAGS =
-INSTALL = /usr/bin/install -c
-INSTALL_PROGRAM = ${INSTALL}
-
-OBJS=cc.o compat.o
-DEST=pcc
-
-MIPDIR=../../mip
-MDIR=../../arch/$(TARGMACH)
-
-all: ${DEST}
-
-${DEST}: $(OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
-
-.c.o:
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
-
-compat.o: $(MIPDIR)/compat.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c
-
-install:
- test -z "${DESTDIR}$(bindir)" || mkdir -p "${DESTDIR}$(bindir)"
- ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${bindir}
- @if [ ${strip} = yes ]; then \
- strip ${DESTDIR}${bindir}/${DEST} ; \
- echo strip ${DESTDIR}${bindir}/${DEST} ; \
- fi
- test -z "${DESTDIR}$(mandir)/man1" || mkdir -p "${DESTDIR}$(mandir)/man1"
- ${INSTALL} cc.1 ${DESTDIR}${mandir}/man1/${DEST}.1
-
-clean:
- /bin/rm -f $(OBJS) ${DEST}
-
-distclean: clean
- /bin/rm -f Makefile
--- usr.bin/pcc/cc/ccom/inline.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* $Id: inline.c,v 1.17 2007/09/09 10:01:01 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-#include "pass1.h"
-
-#include <stdarg.h>
-
-/*
- * ilink from ipole points to the next struct in the list of functions.
- */
-static struct istat {
- struct istat *ilink;
- char *name;
- int type;
-#define NOTYETR 0 /* saved but not yet referenced */
-#define NOTYETW 1 /* saved and referenced but not yet written out */
-#define WRITTEN 2 /* is written out */
-#define NOTYETD 3 /* referenced but not yet saved */
- struct interpass shead;
-} *ipole, *cifun;
-
-#define IP_REF (MAXIP+1)
-
-int isinlining, recovernodes;
-int inlnodecnt, inlstatcnt;
-
-#define ialloc() permalloc(sizeof(struct istat)); inlstatcnt++
-#define nalloc() permalloc(sizeof(NODE))
-
-static void
-tcnt(NODE *p)
-{
- inlnodecnt++;
-}
-
-static struct istat *
-findfun(char *name)
-{
- struct istat *is = ipole;
- while (is) {
- if (is->name == name)
- return is;
- is = is->ilink;
- }
- return NULL;
-}
-
-static void
-refnode(char *str)
-{
- struct interpass *ip;
-
- if (sdebug)
- printf("refnode(%s)\n", str);
-
- ip = permalloc(sizeof(*ip));
- ip->type = IP_REF;
- ip->ip_name = str;
- inline_addarg(ip);
-}
-
-void
-inline_addarg(struct interpass *ip)
-{
- DLIST_INSERT_BEFORE(&cifun->shead, ip, qelem);
- if (ip->type == IP_NODE)
- walkf(ip->ip_node, tcnt); /* Count as saved */
-}
-
-/*
- * Called to setup for inlining of a new function.
- */
-void
-inline_start(char *name)
-{
- struct istat *is;
-
- if (sdebug)
- printf("inline_start(\"%s\")\n", name);
-
- if (isinlining)
- cerror("already inlining function");
-
- if ((is = findfun(name)) == 0) {
- is = ialloc();
- is->ilink = ipole;
- ipole = is;
- is->name = name;
- is->type = NOTYETR;
- } else {
- if (is->type != NOTYETD)
- cerror("inline function already defined");
- is->type = NOTYETW;
- }
- DLIST_INIT(&is->shead, qelem);
- cifun = is;
- isinlining++;
-}
-
-void
-inline_end()
-{
- if (sdebug)
- printf("inline_end()\n");
-
- isinlining = 0;
-}
-
-/*
- * Called when an inline function is found, to be sure that it will
- * be written out.
- * The function may not be defined when inline_ref() is called.
- */
-void
-inline_ref(char *name)
-{
- struct istat *w = ipole;
-
- if (sdebug)
- printf("inline_ref(\"%s\")\n", name);
- if (isinlining) {
- refnode(name);
- } else {
- while (w != NULL) {
- if (w->name == name) {
- if (w->type == NOTYETR)
- w->type = NOTYETW;
- return; /* setup for writeout */
- }
- w = w->ilink;
- }
- /* function not yet defined, print out when found */
- w = ialloc();
- w->ilink = ipole;
- ipole = w;
- w->name = name;
- w->type = NOTYETD;
- }
-}
-
-static void
-puto(struct istat *w)
-{
- struct interpass *ip, *nip;
-
- /* if -O, list will be saved again so foreach cannot be used */
- ip = DLIST_NEXT(&w->shead, qelem);
- while (ip != (&w->shead)) {
- nip = DLIST_NEXT(ip, qelem);
- DLIST_REMOVE(ip, qelem);
- if (ip->type == IP_REF)
- inline_ref(ip->ip_name);
- else
- pass2_compile(ip);
- ip = nip;
- }
- DLIST_INIT(&w->shead, qelem);
-}
-
-/*
- * printout functions that are referenced.
- */
-void
-inline_prtout()
-{
- struct istat *w = ipole;
- int gotone = 0;
-
- if (w == NULL)
- return;
- recovernodes++;
- while (w != NULL) {
- if (w->type == NOTYETW) {
- puto(w);
- w->type = WRITTEN;
- gotone++;
- }
- w = w->ilink;
- }
- if (gotone)
- inline_prtout();
- recovernodes--;
-}
--- usr.bin/pcc/cc/ccom/scan.l
+++ /dev/null
@@ -1,467 +0,0 @@
-%{
-/* $Id: scan.l,v 1.61 2007/09/19 17:20:26 ragge Exp $ */
-
-/*
- * Copyright (c) 2002 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.
- */
-%}
-
-
-D [0-9]
-L [a-zA-Z_]
-H [a-fA-F0-9]
-E [Ee][+-]?{D}+
-P [Pp][+-]?{D}+
-FS (f|F|l|L)
-IS (u|U|l|L)*
-
-%{
-#include <errno.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "pass1.h"
-#include "cgram.h"
-
-static NODE *cvtdig(int radix);
-static NODE *charcon(void);
-static void control(int);
-static NODE *floatcon(void);
-static NODE *fhexcon(void);
-int notype, parbal;
-
-#define CPP_PRAGMA 1
-#define CPP_IDENT 2
-#define CPP_LINE 3
-#define CPP_HASH 4
-
-#ifdef STABS
-#define STABS_LINE(x) if (gflag && blevel) stabs_line(x)
-#else
-#define STABS_LINE(x)
-#endif
-#if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION >= 31
-/* Hack to avoid unneccessary 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);
-extern int yyget_lineno (void);
-extern void yyset_lineno (int);
-#endif
-
-%}
-
-%%
-
-"__func__" {
- if (cftnsp == NULL)
- uerror("__func__ outside function");
- yylval.strp = cftnsp->sname; /* XXX - not C99 */
- return(C_STRING);
- }
-"asm" { return(C_ASM); }
-"auto" { yylval.intval = AUTO; return(C_CLASS); }
-"_Bool" { yylval.nodep = mkty((TWORD)BOOL, 0, MKSUE(BOOL));
- return(C_TYPE); }
-"break" { return(C_BREAK); }
-"case" { return(C_CASE); }
-"char" { yylval.nodep = mkty((TWORD)CHAR, 0, MKSUE(CHAR));
- notype=1; return(C_TYPE); }
-"const" { yylval.nodep =
- block(QUALIFIER, NIL, NIL, CON, 0, 0);
- return(C_QUALIFIER); }
-"continue" { return(C_CONTINUE); }
-"default" { return(C_DEFAULT); }
-"do" { return(C_DO); }
-"double" { yylval.nodep = mkty((TWORD)DOUBLE, 0, MKSUE(DOUBLE));
- notype=1; return(C_TYPE); }
-"else" { return(C_ELSE); }
-"enum" { notype=1; return(C_ENUM); }
-"extern" { yylval.intval = EXTERN; return(C_CLASS); }
-"float" { yylval.nodep = mkty((TWORD)FLOAT, 0, MKSUE(FLOAT));
- notype=1; return(C_TYPE); }
-"for" { return(C_FOR); }
-"goto" { return(C_GOTO); }
-"if" { return(C_IF); }
-"inline" { return(C_FUNSPEC); }
-"int" { yylval.nodep = mkty((TWORD)INT, 0, MKSUE(INT));
- notype=1; return(C_TYPE); }
-"long" { yylval.nodep = mkty((TWORD)LONG, 0, MKSUE(LONG));
- notype=1; return(C_TYPE); }
-"register" { yylval.intval = REGISTER; return(C_CLASS); }
-"restrict" { ; /* just ignore */ }
-"return" { return(C_RETURN); }
-"short" { yylval.nodep = mkty((TWORD)SHORT, 0, MKSUE(SHORT));
- notype=1; return(C_TYPE); }
-"signed" { yylval.nodep = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
- notype=1; return(C_TYPE); }
-"sizeof" { return(C_SIZEOF); }
-"static" { yylval.intval = STATIC; return(C_CLASS); }
-"struct" { yylval.intval = INSTRUCT; notype=1; return(C_STRUCT); }
-"switch" { return(C_SWITCH); }
-"typedef" { yylval.intval = TYPEDEF; return(C_CLASS); }
-"union" { yylval.intval = INUNION; notype=1; return(C_STRUCT); }
-"unsigned" { yylval.nodep = mkty((TWORD)UNSIGNED, 0, MKSUE(UNSIGNED));
- notype=1; return(C_TYPE); }
-"void" { yylval.nodep = mkty((TWORD)VOID, 0, MKSUE(VOID));
- notype=1; return(C_TYPE); }
-"volatile" { yylval.nodep =
- block(QUALIFIER, NIL, NIL, VOL, 0, 0);
- return(C_QUALIFIER); }
-"while" { return(C_WHILE); }
-
-{L}({L}|{D})* { struct symtab *s;
- int i;
-
- yylval.strp = addname(yytext);
- if ((i = gcc_keyword(yylval.strp,
- &yylval.nodep)) != 0)
- return i;
-// printf("str: %s notype %d parbal %d\n", yytext, notype, parbal);
- if (!notype) {
- s = lookup(yylval.strp, SNOCREAT);
- if (s && s->sclass == TYPEDEF)
- return notype=1, C_TYPENAME;
- }
- return(C_NAME);
- }
-
-0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); }
-0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); }
-{D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); }
-L?'(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); }
-
-{D}+{E}{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
-{D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
-{D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
-0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
-0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
-0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
-
-L?\"(\\.|[^\\"])*\" {
- char *c = yytext;
- int i = yyleng-2, rv;
-
- if (*c++ == 'L') {
- c++, i--;
- rv = C_WSTRING;
- } else
- rv = C_STRING;
- c[i] = 0; /* last " */
- yylval.strp = c;
- return rv;
- }
-"..." { return(C_ELLIPSIS); }
-">>=" { yylval.intval = RSEQ; return(C_ASOP); }
-"<<=" { yylval.intval = LSEQ; return(C_ASOP); }
-"+=" { yylval.intval = PLUSEQ; return(C_ASOP); }
-"-=" { yylval.intval = MINUSEQ; return(C_ASOP); }
-"*=" { yylval.intval = MULEQ; return(C_ASOP); }
-"/=" { yylval.intval = DIVEQ; return(C_ASOP); }
-"%=" { yylval.intval = MODEQ; return(C_ASOP); }
-"&=" { yylval.intval = ANDEQ; return(C_ASOP); }
-"^=" { yylval.intval = EREQ; return(C_ASOP); }
-"|=" { yylval.intval = OREQ; return(C_ASOP); }
-">>" { yylval.intval = RS; return(C_SHIFTOP); }
-"<<" { yylval.intval = LS; return(C_SHIFTOP); }
-"++" { yylval.intval = INCR; return(C_INCOP); }
-"--" { yylval.intval = DECR; return(C_INCOP); }
-"->" { yylval.intval = STREF; return(C_STROP); }
-"&&" { yylval.intval = ANDAND; return(C_ANDAND); }
-"||" { yylval.intval = OROR; return(C_OROR); }
-"<=" { yylval.intval = LE; return(C_RELOP); }
-">=" { yylval.intval = GE; return(C_RELOP); }
-"==" { yylval.intval = EQ; return(C_EQUOP); }
-"!=" { yylval.intval = NE; return(C_EQUOP); }
-";" { notype = 0; return(';'); }
-("{"|"<%") { notype = 0; return('{'); }
-("}"|"%>") { return('}'); }
-"," { if (parbal) notype = 0; return(','); }
-":" { return(':'); }
-"=" { return('='); }
-"(" { parbal++; notype = 0; return('('); }
-")" { parbal--; if (parbal==0) { notype = 0; } return(')'); }
-("["|"<:") { return('['); }
-("]"|":>") { return(']'); }
-"." { yylval.intval = DOT; return(C_STROP); }
-"&" { return('&'); }
-"!" { yylval.intval = NOT; return(C_UNOP); }
-"~" { yylval.intval = COMPL; return(C_UNOP); }
-"-" { return('-'); }
-"+" { return('+'); }
-"*" { if (parbal && notype == 0) notype = 1; return('*'); }
-"/" { yylval.intval = DIV; return(C_DIVOP); }
-"%" { yylval.intval = MOD; return(C_DIVOP); }
-"<" { yylval.intval = LT; return(C_RELOP); }
-">" { yylval.intval = GT; return(C_RELOP); }
-"^" { return('^'); }
-"|" { return('|'); }
-"?" { return('?'); }
-^#pragma[ \t].* { control(CPP_PRAGMA); }
-^#ident[ \t].* { control(CPP_IDENT); }
-^#line[ \t].* { control(CPP_LINE); }
-^#.* { control(CPP_HASH); }
-
-[ \t\v\f] { }
-"\n" { ++lineno; STABS_LINE(lineno); }
-. { /* ignore bad characters */ }
-
-%%
-
-int lineno;
-char *ftitle = "<stdin>";
-
-int
-yywrap(void)
-{
- if (0) unput(0); /* quiet gcc */
- return(1);
-}
-
-/*
- * XXX floatcon() and fhexcon() should be in support libraries for
- * the target floating point.
- */
-static NODE *
-f2(char *str)
-{
- TWORD tw;
- NODE *p;
- double dc;
- char *eptr;
-
- dc = strtod(str, &eptr); /* XXX - avoid strtod() */
- tw = (*eptr == 'f' || *eptr == 'F' ? FLOAT : DOUBLE);
- p = block(FCON, NIL, NIL, tw, 0, MKSUE(tw));
- p->n_dcon = dc;
- return p;
-}
-
-NODE *
-floatcon(void)
-{
- return f2(yytext);
-}
-
-static int
-h2n(int ch)
-{
- if (ch >= '0' && ch <= '9')
- return ch - '0';
- if (ch >= 'a' && ch <= 'f')
- return ch - 'a' + 10;
- return ch - 'A' + 10;
-
-}
-
-NODE *
-fhexcon(void)
-{
- char buf[500];
- char *c = yytext;
- unsigned long long num1, num2;
-
- /* XXX - convert it to a decimal float number and use strtod */
- c+= 2; /* skip 0x */
- for (num1 = 0; *c != '.' && *c != 'p' && *c != 'P'; c++)
- num1 = (num1 << 4) | h2n(*c);
- if (*c != '.' && *c != 'p' && *c != 'P')
- cerror("fhexcon");
- num2 = 0;
- if (*c == '.') {
- c++;
- for (; *c != 'p' && *c != 'P'; c++)
- num2 = (num2 << 4) | h2n(*c);
- }
- if (*c != 'P' && *c != 'p')
- cerror("fhexcon2");
- c++;
- snprintf(buf, sizeof(buf), "%llu.%lluE%s", num1, num2, c);
- return f2(buf);
-}
-
-unsigned int
-esccon(char **sptr)
-{
- char *wr = *sptr;
- unsigned int val;
-
- switch (*wr++) {
- 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 'x': val = strtoul(wr, &wr, 16); break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- wr--;
- val = strtoul(wr, &wr, 8);
- break;
- default: val = wr[-1];
- }
- *sptr = wr;
- return val;
-}
-
-NODE *
-cvtdig(int radix)
-{
- NODE *p;
- TWORD ntype;
- unsigned long long v;
- char *ch = yytext;
- int n, numl, numu;
-
- if (radix == 16)
- ch += 2; /* Skip 0x */
-
- v = 0;
- while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') ||
- (*ch >= 'A' && *ch <= 'F')) {
- v *= radix;
- n = *ch;
- n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10);
- ch++;
- v += n;
- }
- /* Parse trailing chars */
- ntype = INT;
- numl = numu = 0;
- for (n = 0; n < 3; n++) {
- if (*ch == 0)
- break;
- if ((*ch == 'l' || *ch == 'L') && numl < 2)
- ntype+=2, numl++;
- else if ((*ch == 'u' || *ch == 'U') && numu < 1)
- ntype = ENUNSIGN(ntype), numu++;
- else
- break;
- ch++;
- }
- if (*ch)
- uerror("constant has too many '%c'", *ch);
-
- if (ntype == INT) {
- /* v contains a number. Get type correct */
- if (v > MAX_LONGLONG && radix != 10)
- ntype = ULONGLONG;
- else if (v > MAX_ULONG)
- ntype = LONGLONG;
- else if (v > MAX_LONG && radix != 10)
- ntype = ULONG;
- else if (v > MAX_UNSIGNED)
- ntype = LONG;
- else if (v > MAX_INT && radix != 10)
- ntype = UNSIGNED;
- }
- ntype = ctype(ntype);
- p = block(ICON, NIL, NIL, ntype, 0, MKSUE(ntype));
- p->n_lval = v;
- ASGLVAL(p->n_slval, v);
-
- return p;
-}
-
-/*
- * Convert a character constant to an integer.
- */
-NODE *
-charcon(void)
-{
- int lastcon = 0;
- int val, i = 0;
- char *pp = yytext;
-
- if (*pp == 'L')
- pp++;
- pp++;
- while (*pp != '\'') {
- if (*pp++ == '\\') {
- val = esccon(&pp);
- } else
- val = pp[-1];
- makecc(val, i);
- i++;
- }
-
- if (i == 0)
- uerror("empty character constant");
- if (i > (SZINT/SZCHAR) || (i>1))
- werror("too many characters in character constant");
- return bcon(lastcon);
-}
-
-void
-control(int t)
-{
- char *wr = yytext;
- char *eptr;
- int val;
-
- wr++; /* Skip initial '#' */
- switch (t) {
- case CPP_PRAGMA:
- case CPP_IDENT:
- return; /* Just skip these for now. */
-
- case CPP_LINE:
- wr += 4;
- /* FALLTHROUGH */
- case CPP_HASH:
- val = strtol(wr, &eptr, 10);
- if (wr == eptr) /* Illegal string */
- goto bad;
- wr = eptr;
- lineno = val - 1;
- while (*wr && *wr != '\"')
- wr++;
- if (*wr++ != '\"')
- goto bad;
- eptr = wr;
- while (*wr && *wr != '\"')
- wr++;
- if (*wr != '\"')
- goto bad;
- *wr = 0;
- ftitle = addstring(eptr);
-#ifdef STABS
- if (gflag)
- stabs_file(ftitle);
-#endif
- }
- return;
-bad:
- werror("%s: illegal control", yytext);
-}
--- usr.bin/pcc/cc/ccom/pftn.c
+++ /dev/null
@@ -1,2553 +0,0 @@
-/* $Id: pftn.c,v 1.171 2007/09/23 20:00:22 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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 conditionsand 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.
- */
-
-/*
- * Many changes from the 32V sources, among them:
- * - New symbol table manager (moved to another file).
- * - Prototype saving/checks.
- */
-
-# include "pass1.h"
-
-#include <string.h> /* XXX - for strcmp */
-
-struct symtab *spname;
-struct symtab *cftnsp;
-static int strunem; /* currently parsed member type */
-int arglistcnt, dimfuncnt; /* statistics */
-int symtabcnt, suedefcnt; /* statistics */
-int autooff, /* the next unused automatic offset */
- maxautooff, /* highest used automatic offset in function */
- argoff, /* the next unused argument offset */
- strucoff; /* the next structure offset position */
-int retlab = NOLAB; /* return label for subroutine */
-int brklab;
-int contlab;
-int flostat;
-int instruct, blevel;
-int reached, prolab;
-
-struct params;
-
-#define ISSTR(ty) (ty == STRTY || ty == UNIONTY || ty == ENUMTY)
-#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
-#define MKTY(p, t, d, s) r = talloc(); *r = *p; \
- r = argcast(r, t, d, s); *p = *r; nfree(r);
-
-/*
- * Info stored for delaying string printouts.
- */
-struct strsched {
- struct strsched *next;
- int locctr;
- struct symtab *sym;
-} *strpole;
-
-/*
- * Linked list stack while reading in structs.
- */
-struct rstack {
- struct rstack *rnext;
- int rinstruct;
- int rclass;
- int rstrucoff;
- struct params *rlparam;
- struct symtab *rsym;
-};
-
-/*
- * Linked list for parameter (and struct elements) declaration.
- */
-static struct params {
- struct params *next, *prev;
- struct symtab *sym;
-} *lpole, *lparam;
-static int nparams;
-
-/* defines used for getting things off of the initialization stack */
-
-static NODE *arrstk[10];
-static int arrstkp;
-static int intcompare;
-
-void fixtype(NODE *p, int class);
-int fixclass(int class, TWORD type);
-int falloc(struct symtab *p, int w, int new, NODE *pty);
-static void dynalloc(struct symtab *p, int *poff);
-void inforce(OFFSZ n);
-void vfdalign(int n);
-static void ssave(struct symtab *);
-static void strprint(void);
-static void alprint(union arglist *al, int in);
-static void lcommadd(struct symtab *sp);
-
-int ddebug = 0;
-
-/*
- * Declaration of an identifier. Handles redeclarations, hiding,
- * incomplete types and forward declarations.
- */
-
-void
-defid(NODE *q, int class)
-{
- struct symtab *p;
- TWORD type, qual;
- TWORD stp, stq;
- int scl;
- union dimfun *dsym, *ddef;
- int slev, temp, changed;
-
- if (q == NIL)
- return; /* an error was detected */
-
- p = q->n_sp;
-
-#ifdef PCC_DEBUG
- if (ddebug) {
- printf("defid(%s (%p), ", p->sname, p);
- tprint(stdout, q->n_type, q->n_qual);
- printf(", %s, (%p,%p)), level %d\n", scnames(class),
- q->n_df, q->n_sue, blevel);
- }
-#endif
-
- fixtype(q, class);
-
- type = q->n_type;
- qual = q->n_qual;
- class = fixclass(class, type);
-
- stp = p->stype;
- stq = p->squal;
- slev = p->slevel;
-
-#ifdef PCC_DEBUG
- if (ddebug) {
- printf(" modified to ");
- tprint(stdout, type, qual);
- printf(", %s\n", scnames(class));
- printf(" previous def'n: ");
- tprint(stdout, stp, stq);
- printf(", %s, (%p,%p)), level %d\n",
- scnames(p->sclass), p->sdf, p->ssue, slev);
- }
-#endif
-
- if (blevel == 1) {
- switch (class) {
- default:
- if (!(class&FIELD))
- uerror("declared argument %s missing",
- p->sname );
- case MOS:
- case STNAME:
- case MOU:
- case UNAME:
- case MOE:
- case ENAME:
- case TYPEDEF:
- ;
- }
- }
-
- if (stp == UNDEF)
- goto enter; /* New symbol */
-
- if (type != stp)
- goto mismatch;
-
- if (blevel > slev && (class == AUTO || class == REGISTER))
- /* new scope */
- goto mismatch;
-
- /*
- * test (and possibly adjust) dimensions.
- * also check that prototypes are correct.
- */
- dsym = p->sdf;
- ddef = q->n_df;
- changed = 0;
- for (temp = type; temp & TMASK; temp = DECREF(temp)) {
- if (ISARY(temp)) {
- if (dsym->ddim == 0) {
- dsym->ddim = ddef->ddim;
- changed = 1;
- } else if (ddef->ddim != 0 && dsym->ddim!=ddef->ddim) {
- goto mismatch;
- }
- ++dsym;
- ++ddef;
- } else if (ISFTN(temp)) {
- /* add a late-defined prototype here */
- if (cftnsp == NULL && dsym->dfun == NULL)
- dsym->dfun = ddef->dfun;
- if (!oldstyle && ddef->dfun != NULL &&
- chkftn(dsym->dfun, ddef->dfun))
- uerror("declaration doesn't match prototype");
- dsym++, ddef++;
- }
- }
-#ifdef STABS
- if (changed && gflag)
- stabs_chgsym(p); /* symbol changed */
-#endif
-
- /* check that redeclarations are to the same structure */
- if ((temp == STRTY || temp == UNIONTY || temp == ENUMTY) &&
- p->ssue != q->n_sue &&
- class != STNAME && class != UNAME && class != ENAME) {
- goto mismatch;
- }
-
- scl = p->sclass;
-
-#ifdef PCC_DEBUG
- if (ddebug)
- printf(" previous class: %s\n", scnames(scl));
-#endif
-
- if (class&FIELD) {
- /* redefinition */
- if (!falloc(p, class&FLDSIZ, 1, NIL)) {
- /* successful allocation */
- ssave(p);
- return;
- }
- /* blew it: resume at end of switch... */
- } else switch(class) {
-
- case EXTERN:
- switch( scl ){
- case STATIC:
- case USTATIC:
- if( slev==0 ) return;
- break;
- case EXTDEF:
- case EXTERN:
- case FORTRAN:
- case UFORTRAN:
- return;
- }
- break;
-
- case STATIC:
- if (scl==USTATIC || (scl==EXTERN && blevel==0)) {
- p->sclass = STATIC;
- return;
- }
- if (changed || (scl == STATIC && blevel == slev))
- return; /* identical redeclaration */
- break;
-
- case USTATIC:
- if (scl==STATIC || scl==USTATIC)
- return;
- break;
-
- case TYPEDEF:
- if (scl == class)
- return;
- break;
-
- case UFORTRAN:
- if (scl == UFORTRAN || scl == FORTRAN)
- return;
- break;
-
- case FORTRAN:
- if (scl == UFORTRAN) {
- p->sclass = FORTRAN;
- return;
- }
- break;
-
- case MOU:
- case MOS:
- if (scl == class) {
- if (oalloc(p, &strucoff))
- break;
- if (class == MOU)
- strucoff = 0;
- ssave(p);
- return;
- }
- break;
-
- case MOE:
- break;
-
- case EXTDEF:
- switch (scl) {
- case EXTERN:
- p->sclass = EXTDEF;
- return;
- case USTATIC:
- p->sclass = STATIC;
- return;
- }
- break;
-
- case STNAME:
- case UNAME:
- case ENAME:
- if (scl != class)
- break;
- if (p->ssue->suesize == 0)
- return; /* previous entry just a mention */
- break;
-
- case AUTO:
- case REGISTER:
- ; /* mismatch.. */
- }
-
- mismatch:
-
- /*
- * Only allowed for automatic variables.
- */
- if (blevel == slev || class == EXTERN || class == FORTRAN ||
- class == UFORTRAN) {
- if (ISSTR(class) && !ISSTR(p->sclass)) {
- uerror("redeclaration of %s", p->sname);
- return;
- }
- }
- if (blevel == 0)
- uerror("redeclaration of %s", p->sname);
- q->n_sp = p = hide(p);
-
- enter: /* make a new entry */
-
-#ifdef PCC_DEBUG
- if(ddebug)
- printf(" new entry made\n");
-#endif
- p->stype = type;
- p->squal = qual;
- p->sclass = class;
- p->slevel = blevel;
- p->soffset = NOOFFSET;
- p->suse = lineno;
- if (class == STNAME || class == UNAME || class == ENAME) {
- p->ssue = permalloc(sizeof(struct suedef));
- suedefcnt++;
- p->ssue->suesize = 0;
- p->ssue->suelem = NULL;
- p->ssue->suealign = ALSTRUCT;
- } else {
- switch (BTYPE(type)) {
- case STRTY:
- case UNIONTY:
- case ENUMTY:
- p->ssue = q->n_sue;
- break;
- default:
- p->ssue = MKSUE(BTYPE(type));
- }
- }
-
- /* copy dimensions */
- p->sdf = q->n_df;
- /* Do not save param info for old-style functions */
- if (ISFTN(type) && oldstyle)
- p->sdf->dfun = NULL;
-
- /* allocate offsets */
- if (class&FIELD) {
- (void) falloc(p, class&FLDSIZ, 0, NIL); /* new entry */
- ssave(p);
- } else switch (class) {
-
- case REGISTER:
- cerror("register var");
-
- case AUTO:
- if (arrstkp)
- dynalloc(p, &autooff);
- else
- oalloc(p, &autooff);
- break;
- case STATIC:
- case EXTDEF:
- p->soffset = getlab();
-#ifdef GCC_COMPAT
- { extern char *renname;
- if (renname)
- gcc_rename(p, renname);
- renname = NULL;
- }
-#endif
- break;
-
- case EXTERN:
- case UFORTRAN:
- case FORTRAN:
- p->soffset = getlab();
-#ifdef notdef
- /* Cannot reset level here. What does the standard say??? */
- p->slevel = 0;
-#endif
-#ifdef GCC_COMPAT
- { extern char *renname;
- if (renname)
- gcc_rename(p, renname);
- renname = NULL;
- }
-#endif
- break;
- case MOU:
- case MOS:
- oalloc(p, &strucoff);
- if (class == MOU)
- strucoff = 0;
- ssave(p);
- break;
-
- case MOE:
- p->soffset = strucoff++;
- ssave(p);
- break;
-
- }
-
-#ifdef STABS
- if (gflag)
- stabs_newsym(p);
-#endif
-
-#ifdef PCC_DEBUG
- if (ddebug)
- printf( " sdf, ssue, offset: %p, %p, %d\n",
- p->sdf, p->ssue, p->soffset);
-#endif
-
-}
-
-void
-ssave(struct symtab *sym)
-{
- struct params *p;
-
- p = tmpalloc(sizeof(struct params));
- p->next = NULL;
- p->sym = sym;
-
- if (lparam == NULL) {
- p->prev = (struct params *)&lpole;
- lpole = p;
- } else {
- lparam->next = p;
- p->prev = lparam;
- }
- lparam = p;
-}
-
-/*
- * end of function
- */
-void
-ftnend()
-{
- extern struct savbc *savbc;
- extern struct swdef *swpole;
- char *c;
-
- if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
- plabel(retlab);
- efcode(); /* struct return handled here */
- c = cftnsp->sname;
-#ifdef GCC_COMPAT
- c = gcc_findname(cftnsp);
-#endif
- SETOFF(maxautooff, ALCHAR);
- send_passt(IP_EPILOG, 0, maxautooff/SZCHAR, c,
- cftnsp->stype, cftnsp->sclass == EXTDEF, retlab);
- }
-
- tcheck();
- brklab = contlab = retlab = NOLAB;
- flostat = 0;
- if (nerrors == 0) {
- if (savbc != NULL)
- cerror("bcsave error");
- if (lparam != NULL)
- cerror("parameter reset error");
- if (swpole != NULL)
- cerror("switch error");
- }
- savbc = NULL;
- lparam = NULL;
- maxautooff = autooff = AUTOINIT;
- reached = 1;
-
- if (isinlining)
- inline_end();
- inline_prtout();
-
- strprint();
-
- tmpfree(); /* Release memory resources */
-}
-
-void
-dclargs()
-{
- union dimfun *df;
- union arglist *al, *al2, *alb;
- struct params *a;
- struct symtab *p, **parr = NULL; /* XXX gcc */
- char *c;
- int i;
-
- argoff = ARGINIT;
-
- /*
- * Deal with fun(void) properly.
- */
- if (nparams == 1 && lparam->sym->stype == VOID)
- goto done;
-
- /*
- * Generate a list for bfcode().
- * Parameters were pushed in reverse order.
- */
- if (nparams != 0)
- parr = tmpalloc(sizeof(struct symtab *) * nparams);
-
- if (nparams)
- for (a = lparam, i = 0; a != NULL && a != (struct params *)&lpole;
- a = a->prev) {
-
- p = a->sym;
- parr[i++] = p;
- if (p->stype == FARG) {
- p->stype = INT;
- p->ssue = MKSUE(INT);
- }
- if (ISARY(p->stype)) {
- p->stype += (PTR-ARY);
- p->sdf++;
- } else if (ISFTN(p->stype)) {
- werror("function declared as argument");
- p->stype = INCREF(p->stype);
- }
- /* always set aside space, even for register arguments */
- oalloc(p, &argoff);
-#ifdef STABS
- if (gflag)
- stabs_newsym(p);
-#endif
- }
- if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
- /*
- * Check against prototype of oldstyle function.
- */
- alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
- for (i = 0; i < nparams; i++) {
- TWORD type = parr[i]->stype;
- (al2++)->type = type;
- if (ISSTR(BTYPE(type)))
- (al2++)->sue = parr[i]->ssue;
- while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
- type = DECREF(type);
- if (type > BTMASK)
- (al2++)->df = parr[i]->sdf;
- }
- al2->type = TNULL;
- intcompare = 1;
- if (chkftn(al, alb))
- uerror("function doesn't match prototype");
- intcompare = 0;
- }
-done: cendarg();
- c = cftnsp->sname;
-#ifdef GCC_COMPAT
- c = gcc_findname(cftnsp);
-#endif
-#if 0
- prolab = getlab();
- send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
- cftnsp->sclass == EXTDEF, prolab);
-#endif
- plabel(prolab); /* after prolog, used in optimization */
- retlab = getlab();
- bfcode(parr, nparams);
- if (xtemps) {
- /* put arguments in temporaries */
- for (i = 0; i < nparams; i++) {
- NODE *q, *r, *s;
-
- p = parr[i];
- if (p->stype == STRTY || p->stype == UNIONTY ||
- cisreg(p->stype) == 0)
- continue;
- spname = p;
- q = buildtree(NAME, 0, 0);
- r = tempnode(0, p->stype, p->sdf, p->ssue);
- s = buildtree(ASSIGN, r, q);
- p->soffset = r->n_lval;
- p->sflags |= STNODE;
- ecomp(s);
- }
- plabel(getlab()); /* used when spilling */
- }
- lparam = NULL;
- nparams = 0;
-}
-
-/*
- * reference to a structure or union, with no definition
- */
-NODE *
-rstruct(char *tag, int soru)
-{
- struct symtab *p;
- NODE *q;
-
- p = (struct symtab *)lookup(tag, STAGNAME);
- switch (p->stype) {
-
- case UNDEF:
- def:
- q = block(NAME, NIL, NIL, 0, 0, 0);
- q->n_sp = p;
- q->n_type = (soru&INSTRUCT) ? STRTY :
- ((soru&INUNION) ? UNIONTY : ENUMTY);
- defid(q, (soru&INSTRUCT) ? STNAME :
- ((soru&INUNION) ? UNAME : ENAME));
- nfree(q);
- break;
-
- case STRTY:
- if (soru & INSTRUCT)
- break;
- goto def;
-
- case UNIONTY:
- if (soru & INUNION)
- break;
- goto def;
-
- case ENUMTY:
- if (!(soru&(INUNION|INSTRUCT)))
- break;
- goto def;
-
- }
- q = mkty(p->stype, 0, p->ssue);
- q->n_sue = p->ssue;
- return q;
-}
-
-void
-moedef(char *name)
-{
- NODE *q;
-
- q = block(NAME, NIL, NIL, MOETY, 0, 0);
- q->n_sp = lookup(name, 0);
- defid(q, MOE);
- nfree(q);
-}
-
-/*
- * begining of structure or union declaration
- */
-struct rstack *
-bstruct(char *name, int soru)
-{
- struct rstack *r;
- struct symtab *s;
- NODE *q;
-
- if (name != NULL)
- s = lookup(name, STAGNAME);
- else
- s = NULL;
-
- r = tmpalloc(sizeof(struct rstack));
- r->rinstruct = instruct;
- r->rclass = strunem;
- r->rstrucoff = strucoff;
-
- strucoff = 0;
- instruct = soru;
- q = block(NAME, NIL, NIL, 0, 0, 0);
- q->n_sp = s;
- if (instruct==INSTRUCT) {
- strunem = MOS;
- q->n_type = STRTY;
- if (s != NULL)
- defid(q, STNAME);
- } else if(instruct == INUNION) {
- strunem = MOU;
- q->n_type = UNIONTY;
- if (s != NULL)
- defid(q, UNAME);
- } else { /* enum */
- strunem = MOE;
- q->n_type = ENUMTY;
- if (s != NULL)
- defid(q, ENAME);
- }
- r->rsym = q->n_sp;
- r->rlparam = lparam;
- nfree(q);
-
- return r;
-}
-
-/*
- * Called after a struct is declared to restore the environment.
- */
-NODE *
-dclstruct(struct rstack *r)
-{
- NODE *n;
- struct params *l, *m;
- struct suedef *sue;
- struct symtab *p;
- int al, sa, sz;
- TWORD temp;
- int i, high, low;
-
- if (r->rsym == NULL) {
- sue = permalloc(sizeof(struct suedef));
- suedefcnt++;
- sue->suesize = 0;
- sue->suealign = ALSTRUCT;
- } else
- sue = r->rsym->ssue;
-
-#ifdef PCC_DEBUG
- if (ddebug)
- printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??");
-#endif
- temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
- instruct = r->rinstruct;
- strunem = r->rclass;
- al = ALSTRUCT;
-
- high = low = 0;
-
- if ((l = r->rlparam) == NULL)
- l = lpole;
- else
- l = l->next;
-
- /* memory for the element array must be allocated first */
- for (m = l, i = 1; m != NULL; m = m->next)
- i++;
- sue->suelem = permalloc(sizeof(struct symtab *) * i);
-
- for (i = 0; l != NULL; l = l->next) {
- sue->suelem[i++] = p = l->sym;
-
- if (p == NULL)
- cerror("gummy structure member");
- if (temp == ENUMTY) {
- if (p->soffset < low)
- low = p->soffset;
- if (p->soffset > high)
- high = p->soffset;
- p->ssue = sue;
- continue;
- }
- sa = talign(p->stype, p->ssue);
- if (p->sclass & FIELD) {
- sz = p->sclass&FLDSIZ;
- } else {
- sz = tsize(p->stype, p->sdf, p->ssue);
- }
- if (sz > strucoff)
- strucoff = sz; /* for use with unions */
- /*
- * set al, the alignment, to the lcm of the alignments
- * of the members.
- */
- SETOFF(al, sa);
- }
- sue->suelem[i] = NULL;
- SETOFF(strucoff, al);
-
- if (temp == ENUMTY) {
- TWORD ty;
-
-#ifdef ENUMSIZE
- ty = ENUMSIZE(high,low);
-#else
- if ((char)high == high && (char)low == low)
- ty = ctype(CHAR);
- else if ((short)high == high && (short)low == low)
- ty = ctype(SHORT);
- else
- ty = ctype(INT);
-#endif
- strucoff = tsize(ty, 0, MKSUE(ty));
- sue->suealign = al = talign(ty, MKSUE(ty));
- }
-
- sue->suesize = strucoff;
- sue->suealign = al;
-
-#ifdef STABS
- if (gflag)
- stabs_struct(r->rsym, sue);
-#endif
-
-#ifdef PCC_DEBUG
- if (ddebug>1) {
- int i;
-
- printf("\tsize %d align %d elem %p\n",
- sue->suesize, sue->suealign, sue->suelem);
- for (i = 0; sue->suelem[i] != NULL; ++i) {
- printf("\tmember %s(%p)\n",
- sue->suelem[i]->sname, sue->suelem[i]);
- }
- }
-#endif
-
- strucoff = r->rstrucoff;
- if ((lparam = r->rlparam) != NULL)
- lparam->next = NULL;
- n = mkty(temp, 0, sue);
- return n;
-}
-
-/*
- * error printing routine in parser
- */
-void yyerror(char *s);
-void
-yyerror(char *s)
-{
- uerror(s);
-}
-
-void yyaccpt(void);
-void
-yyaccpt(void)
-{
- ftnend();
-}
-
-/*
- * p is top of type list given to tymerge later.
- * Find correct CALL node and declare parameters from there.
- */
-void
-ftnarg(NODE *p)
-{
- NODE *q;
- struct symtab *s;
-
-#ifdef PCC_DEBUG
- if (ddebug > 2)
- printf("ftnarg(%p)\n", p);
-#endif
- /*
- * Enter argument onto param stack.
- * Do not declare parameters until later (in dclargs);
- * the function must be declared first.
- * put it on the param stack in reverse order, due to the
- * nature of the stack it will be reclaimed correct.
- */
- for (; p->n_op != NAME; p = p->n_left) {
- if (p->n_op == (UCALL) && p->n_left->n_op == NAME)
- return; /* Nothing to enter */
- if (p->n_op == CALL && p->n_left->n_op == NAME)
- break;
- }
-
- p = p->n_right;
- blevel = 1;
-
- while (p->n_op == CM) {
- q = p->n_right;
- if (q->n_op != ELLIPSIS) {
- s = lookup((char *)q->n_sp, 0);
- if (s->stype != UNDEF) {
- if (s->slevel > 0)
- uerror("parameter '%s' redefined",
- s->sname);
- s = hide(s);
- }
- s->soffset = NOOFFSET;
- s->sclass = PARAM;
- s->stype = q->n_type;
- s->sdf = q->n_df;
- s->ssue = q->n_sue;
- ssave(s);
- nparams++;
-#ifdef PCC_DEBUG
- if (ddebug > 2)
- printf(" saving sym %s (%p) from (%p)\n",
- s->sname, s, q);
-#endif
- }
- p = p->n_left;
- }
- s = lookup((char *)p->n_sp, 0);
- if (s->stype != UNDEF) {
- if (s->slevel > 0)
- uerror("parameter '%s' redefined", s->sname);
- s = hide(s);
- }
- s->soffset = NOOFFSET;
- s->sclass = PARAM;
- s->stype = p->n_type;
- s->sdf = p->n_df;
- s->ssue = p->n_sue;
- ssave(s);
- if (p->n_type != VOID)
- nparams++;
- blevel = 0;
-
-#ifdef PCC_DEBUG
- if (ddebug > 2)
- printf(" saving sym %s (%p) from (%p)\n",
- s->sname, s, p);
-#endif
-}
-
-/*
- * compute the alignment of an object with type ty, sizeoff index s
- */
-int
-talign(unsigned int ty, struct suedef *sue)
-{
- int i;
-
- if (ISPTR(ty))
- return(ALPOINT); /* shortcut */
-
- if(sue == NULL && ty!=INT && ty!=CHAR && ty!=SHORT &&
- ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT) {
- return(fldal(ty));
- }
-
- for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
- switch( (ty>>i)&TMASK ){
-
- case FTN:
- cerror("compiler takes alignment of function");
- case PTR:
- return(ALPOINT);
- case ARY:
- continue;
- case 0:
- break;
- }
- }
-
- switch( BTYPE(ty) ){
-
- case UNIONTY:
- case ENUMTY:
- case STRTY:
- return((unsigned int)sue->suealign);
- case BOOL:
- return (ALBOOL);
- case CHAR:
- case UCHAR:
- return (ALCHAR);
- case FLOAT:
- return (ALFLOAT);
- case LDOUBLE:
- return (ALLDOUBLE);
- case DOUBLE:
- return (ALDOUBLE);
- case LONGLONG:
- case ULONGLONG:
- return (ALLONGLONG);
- case LONG:
- case ULONG:
- return (ALLONG);
- case SHORT:
- case USHORT:
- return (ALSHORT);
- default:
- return (ALINT);
- }
-}
-
-/* compute the size associated with type ty,
- * dimoff d, and sizoff s */
-/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
-OFFSZ
-tsize(TWORD ty, union dimfun *d, struct suedef *sue)
-{
-
- int i;
- OFFSZ mult, sz;
-
- mult = 1;
-
- for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
- switch( (ty>>i)&TMASK ){
-
- case FTN:
- uerror( "cannot take size of function");
- case PTR:
- return( SZPOINT(ty) * mult );
- case ARY:
- mult *= d->ddim;
- d++;
- continue;
- case 0:
- break;
-
- }
- }
-
- if (sue == NULL)
- cerror("bad tsize sue");
- sz = sue->suesize;
-#ifdef GCC_COMPAT
- if (ty == VOID)
- sz = SZCHAR;
-#endif
- if (ty != STRTY && ty != UNIONTY) {
- if (sz == 0) {
- uerror("unknown size");
- return(SZINT);
- }
- } else {
- if (sue->suelem == NULL)
- uerror("unknown structure/union/enum");
- }
-
- return((unsigned int)sz * mult);
-}
-
-/*
- * Write last part of wide string.
- * Do not bother to save wide strings.
- */
-NODE *
-wstrend(char *str)
-{
- struct symtab *sp = getsymtab(str, SSTRING|STEMP);
- struct strsched *sc = tmpalloc(sizeof(struct strsched));
- NODE *p = block(NAME, NIL, NIL, WCHAR_TYPE+ARY,
- tmpalloc(sizeof(union dimfun)), MKSUE(WCHAR_TYPE));
- int i;
- char *c;
-
- sp->sclass = ILABEL;
- sp->soffset = getlab();
- sp->stype = WCHAR_TYPE+ARY;
-
- sc = tmpalloc(sizeof(struct strsched));
- sc->locctr = STRNG;
- sc->sym = sp;
- sc->next = strpole;
- strpole = sc;
-
- /* length calculation, used only for sizeof */
- for (i = 0, c = str; *c; ) {
- if (*c++ == '\\')
- (void)esccon(&c);
- i++;
- }
- p->n_df->ddim = (i+1) * ((MKSUE(WCHAR_TYPE))->suesize/SZCHAR);
- p->n_sp = sp;
- return(p);
-}
-
-/*
- * Write last part of string.
- */
-NODE *
-strend(char *str)
-{
-// extern int maystr;
- struct symtab *s;
- NODE *p;
- int i;
- char *c;
-
- /* If an identical string is already emitted, just forget this one */
- str = addstring(str); /* enter string in string table */
- s = lookup(str, SSTRING); /* check for existance */
-
- if (s->soffset == 0 /* && maystr == 0 */) { /* No string */
- struct strsched *sc;
- s->sclass = ILABEL;
-
- /*
- * Delay printout of this string until after the current
- * function, or the end of the statement.
- */
- sc = tmpalloc(sizeof(struct strsched));
- sc->locctr = STRNG;
- sc->sym = s;
- sc->next = strpole;
- strpole = sc;
- s->soffset = getlab();
- }
-
- p = block(NAME, NIL, NIL, CHAR+ARY,
- tmpalloc(sizeof(union dimfun)), MKSUE(CHAR));
-#ifdef CHAR_UNSIGNED
- p->n_type = UCHAR+ARY;
-#endif
- /* length calculation, used only for sizeof */
- for (i = 0, c = str; *c; ) {
- if (*c++ == '\\')
- (void)esccon(&c);
- i++;
- }
- p->n_df->ddim = i+1;
- p->n_sp = s;
- return(p);
-}
-
-/*
- * Print out new strings, before temp memory is cleared.
- */
-void
-strprint()
-{
- char *wr;
- int i, val, isw;
- NODE *p = bcon(0);
-
- while (strpole != NULL) {
- setloc1(STRNG);
- deflab1(strpole->sym->soffset);
- isw = strpole->sym->stype == WCHAR_TYPE+ARY;
-
- i = 0;
- wr = strpole->sym->sname;
- while (*wr != 0) {
- if (*wr++ == '\\')
- val = esccon(&wr);
- else
- val = (unsigned char)wr[-1];
- if (isw) {
- p->n_lval = val;
- p->n_type = WCHAR_TYPE;
- ninval(i*(WCHAR_TYPE/SZCHAR),
- (MKSUE(WCHAR_TYPE))->suesize, p);
- } else
- bycode(val, i);
- i++;
- }
- if (isw) {
- p->n_lval = 0;
- ninval(i*(WCHAR_TYPE/SZCHAR),
- (MKSUE(WCHAR_TYPE))->suesize, p);
- } else {
- bycode(0, i++);
- bycode(-1, i);
- }
- strpole = strpole->next;
- }
- nfree(p);
-}
-
-#if 0
-/*
- * simulate byte v appearing in a list of integer values
- */
-void
-putbyte(int v)
-{
- NODE *p;
- p = bcon(v);
- incode( p, SZCHAR );
- tfree( p );
-// gotscal();
-}
-#endif
-
-/*
- * update the offset pointed to by poff; return the
- * offset of a value of size `size', alignment `alignment',
- * given that off is increasing
- */
-int
-upoff(int size, int alignment, int *poff)
-{
- int off;
-
- off = *poff;
- SETOFF(off, alignment);
- if (off < 0)
- cerror("structure or stack overgrown"); /* wrapped */
- *poff = off+size;
- return (off);
-}
-
-/*
- * allocate p with offset *poff, and update *poff
- */
-int
-oalloc(struct symtab *p, int *poff )
-{
- int al, off, tsz;
- int noff;
-
- /*
- * Only generate tempnodes if we are optimizing,
- * and only for integers, floats or pointers,
- * and not if the basic type is volatile.
- */
-/* XXX OLDSTYLE */
- if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) &&
- (p->stype < STRTY || ISPTR(p->stype)) &&
- !ISVOL((p->squal << TSHIFT)) && cisreg(p->stype)) {
- NODE *tn = tempnode(0, p->stype, p->sdf, p->ssue);
- p->soffset = tn->n_lval;
- p->sflags |= STNODE;
- nfree(tn);
- return 0;
- }
-
- al = talign(p->stype, p->ssue);
- noff = off = *poff;
- tsz = tsize(p->stype, p->sdf, p->ssue);
-#ifdef BACKAUTO
- if (p->sclass == AUTO) {
- noff = off + tsz;
- if (noff < 0)
- cerror("stack overflow");
- SETOFF(noff, al);
- off = -noff;
- } else
-#endif
- if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
- p->stype == SHORT || p->stype == USHORT)) {
- off = upoff(SZINT, ALINT, &noff);
-#ifndef RTOLBYTES
- off = noff - tsz;
-#endif
- } else {
- off = upoff(tsz, al, &noff);
- }
-
- if (p->sclass != REGISTER) {
- /* in case we are allocating stack space for register arguments */
- if (p->soffset == NOOFFSET)
- p->soffset = off;
- else if(off != p->soffset)
- return(1);
- }
-
- *poff = noff;
- return(0);
-}
-
-/*
- * Allocate space on the stack for dynamic arrays.
- * Strategy is as follows:
- * - first entry is a pointer to the dynamic datatype.
- * - if it's a one-dimensional array this will be the only entry used.
- * - if it's a multi-dimensional array the following (numdim-1) integers
- * will contain the sizes to multiply the indexes with.
- * - code to write the dimension sizes this will be generated here.
- * - code to allocate space on the stack will be generated here.
- */
-static void
-dynalloc(struct symtab *p, int *poff)
-{
- union dimfun *df;
- NODE *n, *nn, *tn, *pol;
- TWORD t;
- int i, no;
-
- /*
- * The pointer to the array is stored in a TEMP node, which number
- * is in the soffset field;
- */
- t = p->stype;
- p->sflags |= (STNODE|SDYNARRAY);
- p->stype = INCREF(p->stype); /* Make this an indirect pointer */
- tn = tempnode(0, p->stype, p->sdf, p->ssue);
- p->soffset = tn->n_lval;
-
- df = p->sdf;
-
- pol = NIL;
- for (i = 0; ISARY(t); t = DECREF(t), df++) {
- if (df->ddim >= 0)
- continue;
- n = arrstk[i++];
- nn = tempnode(0, INT, 0, MKSUE(INT));
- no = nn->n_lval;
- ecomp(buildtree(ASSIGN, nn, n)); /* Save size */
-
- df->ddim = -no;
- n = tempnode(no, INT, 0, MKSUE(INT));
- if (pol == NIL)
- pol = n;
- else
- pol = buildtree(MUL, pol, n);
- }
- /* Create stack gap */
- if (pol == NIL)
- uerror("aggregate dynamic array not allowed");
- else
- spalloc(tn, pol, tsize(t, 0, p->ssue));
- arrstkp = 0;
-}
-
-/*
- * allocate a field of width w
- * new is 0 if new entry, 1 if redefinition, -1 if alignment
- */
-int
-falloc(struct symtab *p, int w, int new, NODE *pty)
-{
- int al,sz,type;
-
- type = (new<0)? pty->n_type : p->stype;
-
- /* this must be fixed to use the current type in alignments */
- switch( new<0?pty->n_type:p->stype ){
-
- case ENUMTY: {
- struct suedef *sue;
- sue = new < 0 ? pty->n_sue : p->ssue;
- al = sue->suealign;
- sz = sue->suesize;
- break;
- }
-
- case CHAR:
- case UCHAR:
- al = ALCHAR;
- sz = SZCHAR;
- break;
-
- case SHORT:
- case USHORT:
- al = ALSHORT;
- sz = SZSHORT;
- break;
-
- case INT:
- case UNSIGNED:
- al = ALINT;
- sz = SZINT;
- break;
-
- default:
- if( new < 0 ) {
- uerror( "illegal field type" );
- al = ALINT;
- } else
- al = fldal( p->stype );
- sz =SZINT;
- }
-
- if( w > sz ) {
- uerror( "field too big");
- w = sz;
- }
-
- if( w == 0 ){ /* align only */
- SETOFF( strucoff, al );
- if( new >= 0 ) uerror( "zero size field");
- return(0);
- }
-
- if( strucoff%al + w > sz ) SETOFF( strucoff, al );
- if( new < 0 ) {
- strucoff += w; /* we know it will fit */
- return(0);
- }
-
- /* establish the field */
-
- if( new == 1 ) { /* previous definition */
- if( p->soffset != strucoff || p->sclass != (FIELD|w) ) return(1);
- }
- p->soffset = strucoff;
- strucoff += w;
- p->stype = type;
- fldty( p );
- return(0);
-}
-
-/*
- * handle unitialized declarations assumed to be not functions:
- * int a;
- * extern int a;
- * static int a;
- */
-void
-nidcl(NODE *p, int class)
-{
- struct symtab *sp;
- int commflag = 0;
-
- /* compute class */
- if (class == SNULL) {
- if (blevel > 1)
- class = AUTO;
- else if (blevel != 0 || instruct)
- cerror( "nidcl error" );
- else /* blevel = 0 */
- commflag = 1, class = EXTERN;
- }
-
- defid(p, class);
-
- sp = p->n_sp;
- /* check if forward decl */
- if (ISARY(sp->stype) && sp->sdf->ddim == 0)
- return;
-
- if (sp->sflags & SASG)
- return; /* already initialized */
-
- switch (class) {
- case EXTDEF:
- /* simulate initialization by 0 */
- simpleinit(p->n_sp, bcon(0));
- break;
- case EXTERN:
- if (commflag)
- lcommadd(p->n_sp);
- else
- extdec(p->n_sp);
- break;
- case STATIC:
- if (blevel == 0)
- lcommadd(p->n_sp);
- else
- lcommdec(p->n_sp);
- break;
- }
-}
-
-struct lcd {
- SLIST_ENTRY(lcd) next;
- struct symtab *sp;
-};
-
-static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw};
-
-/*
- * Add a local common statement to the printout list.
- */
-void
-lcommadd(struct symtab *sp)
-{
- struct lcd *lc, *lcp;
-
- lcp = NULL;
- SLIST_FOREACH(lc, &lhead, next) {
- if (lc->sp == sp)
- return; /* already exists */
- if (lc->sp == NULL && lcp == NULL)
- lcp = lc;
- }
- if (lcp == NULL) {
- lc = permalloc(sizeof(struct lcd));
- lc->sp = sp;
- SLIST_INSERT_LAST(&lhead, lc, next);
- } else
- lcp->sp = sp;
-}
-
-/*
- * Delete a local common statement.
- */
-void
-lcommdel(struct symtab *sp)
-{
- struct lcd *lc;
-
- SLIST_FOREACH(lc, &lhead, next) {
- if (lc->sp == sp) {
- lc->sp = NULL;
- return;
- }
- }
-}
-
-/*
- * Print out the remaining common statements.
- */
-void
-lcommprint(void)
-{
- struct lcd *lc;
-
- SLIST_FOREACH(lc, &lhead, next) {
- if (lc->sp != NULL) {
- if (lc->sp->sclass == STATIC)
- lcommdec(lc->sp);
- else
- commdec(lc->sp);
- }
- }
-}
-
-/*
- * Merges a type tree into one type. Returns one type node with merged types
- * and class stored in the su field. Frees all other nodes.
- * XXX - classes in typedefs?
- */
-NODE *
-typenode(NODE *p)
-{
- NODE *l, *sp = NULL;
- int class = 0, adj, noun, sign;
- TWORD qual = 0;
-
- adj = INT; /* INT, LONG or SHORT */
- noun = UNDEF; /* INT, CHAR or FLOAT */
- sign = 0; /* 0, SIGNED or UNSIGNED */
-
- /* Remove initial QUALIFIERs */
- if (p && p->n_op == QUALIFIER) {
- qual = p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
- /* Handle initial classes special */
- if (p && p->n_op == CLASS) {
- class = p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
- /* Remove more QUALIFIERs */
- if (p && p->n_op == QUALIFIER) {
- qual |= p->n_type;
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
-ag: if (p && p->n_op == TYPE) {
- if (p->n_left == NIL) {
-#ifdef CHAR_UNSIGNED
- if (p->n_type == CHAR)
- p->n_type = UCHAR;
-#endif
- if (p->n_type == SIGNED)
- p->n_type = INT;
-uni: p->n_lval = class;
- p->n_qual = qual >> TSHIFT;
- return p;
- } else if (p->n_left->n_op == QUALIFIER) {
- qual |= p->n_left->n_type;
- l = p->n_left;
- p->n_left = l->n_left;
- nfree(l);
- goto ag;
- } else if (ISSTR(p->n_type)) {
- /* Save node; needed for return */
- sp = p;
- p = p->n_left;
- }
- }
-
- while (p != NIL) {
- if (p->n_op == QUALIFIER) {
- qual |= p->n_type;
- goto next;
- }
- if (p->n_op == CLASS) {
- if (class != 0)
- uerror("too many storage classes");
- class = p->n_type;
- goto next;
- }
- if (p->n_op != TYPE)
- cerror("typenode got notype %d", p->n_op);
- switch (p->n_type) {
- case UCHAR:
- case USHORT: /* may come from typedef */
- if (sign != 0 || adj != INT)
- goto bad;
- noun = p->n_type;
- break;
- case SIGNED:
- case UNSIGNED:
- if (sign != 0)
- goto bad;
- sign = p->n_type;
- break;
- case LONG:
- if (adj == LONG) {
- adj = LONGLONG;
- break;
- }
- /* FALLTHROUGH */
- case SHORT:
- if (adj != INT)
- goto bad;
- adj = p->n_type;
- break;
- case INT:
- case CHAR:
- case FLOAT:
- case DOUBLE:
- if (noun != UNDEF)
- goto bad;
- noun = p->n_type;
- break;
- case VOID:
- if (noun != UNDEF || adj != INT)
- goto bad;
- adj = noun = VOID;
- break;
- case STRTY:
- case UNIONTY:
- break;
- default:
- goto bad;
- }
- next:
- l = p->n_left;
- nfree(p);
- p = l;
- }
-
- if (sp) {
- p = sp;
- goto uni;
- }
-
-#ifdef CHAR_UNSIGNED
- if (noun == CHAR && sign == 0)
- sign = UNSIGNED;
-#endif
- if (noun == UNDEF) {
- noun = INT;
- } else if (noun == FLOAT) {
- if (sign != 0 || adj == SHORT)
- goto bad;
- noun = (adj == LONG ? DOUBLE : FLOAT);
- } else if (noun == DOUBLE) {
- if (sign != 0 || adj == SHORT)
- goto bad;
- noun = (adj == LONG ? LDOUBLE : DOUBLE);
- } else if (noun == CHAR && adj != INT)
- goto bad;
-
- if (adj != INT && (noun != DOUBLE && noun != LDOUBLE))
- noun = adj;
- if (sign == UNSIGNED)
- noun += (UNSIGNED-INT);
-
- p = block(TYPE, NIL, NIL, noun, 0, 0);
- p->n_qual = qual >> TSHIFT;
- if (strunem != 0)
- class = strunem;
- p->n_lval = class;
- return p;
-
-bad: uerror("illegal type combination");
- return mkty(INT, 0, 0);
-}
-
-struct tylnk {
- struct tylnk *next;
- union dimfun df;
-};
-
-static void tyreduce(NODE *p, struct tylnk **, int *);
-
-static void
-tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim)
-{
- (*tylkp)->next = tmpalloc(sizeof(struct tylnk));
- *tylkp = (*tylkp)->next;
- (*tylkp)->next = NULL;
- (*tylkp)->df = dim;
- (*ntdim)++;
-}
-
-/* merge type typ with identifier idp */
-NODE *
-tymerge(NODE *typ, NODE *idp)
-{
- NODE *p;
- union dimfun *j;
- struct tylnk *base, tylnk, *tylkp;
- unsigned int t;
- int ntdim, i;
-
- if (typ->n_op != TYPE)
- cerror("tymerge: arg 1");
-
-#ifdef PCC_DEBUG
- if (ddebug > 2) {
- printf("tymerge(%p,%p)\n", typ, idp);
- fwalk(typ, eprint, 0);
- fwalk(idp, eprint, 0);
- }
-#endif
-
- idp->n_type = typ->n_type;
- idp->n_qual = (typ->n_qual << TSHIFT) | idp->n_qual; /* XXX ??? */
-
- tylkp = &tylnk;
- tylkp->next = NULL;
- ntdim = 0;
-
- tyreduce(idp, &tylkp, &ntdim);
- idp->n_sue = typ->n_sue;
-
- for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t))
- if (ISARY(t) || ISFTN(t))
- tylkadd(*j++, &tylkp, &ntdim);
-
- if (ntdim) {
- union dimfun *a = permalloc(sizeof(union dimfun) * ntdim);
- dimfuncnt += ntdim;
- for (i = 0, base = tylnk.next; base; base = base->next, i++)
- a[i] = base->df;
- idp->n_df = a;
- } else
- idp->n_df = NULL;
-
- /* now idp is a single node: fix up type */
-
- idp->n_type = ctype(idp->n_type);
- idp->n_qual = DECQAL(idp->n_qual);
-
- /* in case ctype has rewritten things */
- if ((t = BTYPE(idp->n_type)) != STRTY && t != UNIONTY && t != ENUMTY)
- idp->n_sue = MKSUE(t);
-
- if (idp->n_op != NAME) {
- for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
- nfree(p);
- nfree(p);
- idp->n_op = NAME;
- }
-
- return(idp);
-}
-
-/*
- * Retrieve all CM-separated argument types, sizes and dimensions and
- * put them in an array.
- * XXX - can only check first type level, side effects?
- */
-static union arglist *
-arglist(NODE *n)
-{
- union arglist *al;
- NODE *w = n, **ap;
- int num, cnt, i, j, k;
- TWORD ty;
-
-#ifdef PCC_DEBUG
- if (pdebug) {
- printf("arglist %p\n", n);
- fwalk(n, eprint, 0);
- }
-#endif
- /* First: how much to allocate */
- for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) {
- cnt++; /* Number of levels */
- num++; /* At least one per step */
- if (w->n_right->n_op == ELLIPSIS)
- continue;
- ty = w->n_right->n_type;
- if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
- BTYPE(ty) == ENUMTY)
- num++;
- while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
- ty = DECREF(ty);
- if (ty > BTMASK)
- num++;
- }
- cnt++;
- ty = w->n_type;
- if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
- BTYPE(ty) == ENUMTY)
- num++;
- while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
- ty = DECREF(ty);
- if (ty > BTMASK)
- num++;
- num += 2; /* TEND + last arg type */
-
- /* Second: Create list to work on */
- ap = tmpalloc(sizeof(NODE *) * cnt);
- al = permalloc(sizeof(union arglist) * num);
- arglistcnt += num;
-
- for (w = n, i = 0; w->n_op == CM; w = w->n_left)
- ap[i++] = w->n_right;
- ap[i] = w;
-
- /* Third: Create actual arg list */
- for (k = 0, j = i; j >= 0; j--) {
- if (ap[j]->n_op == ELLIPSIS) {
- al[k++].type = TELLIPSIS;
- ap[j]->n_op = ICON; /* for tfree() */
- continue;
- }
- /* Convert arrays to pointers */
- if (ISARY(ap[j]->n_type)) {
- ap[j]->n_type += (PTR-ARY);
- ap[j]->n_df++;
- }
- /* Convert (silently) functions to pointers */
- if (ISFTN(ap[j]->n_type))
- ap[j]->n_type = INCREF(ap[j]->n_type);
- ty = ap[j]->n_type;
- al[k++].type = ty;
- if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
- BTYPE(ty) == ENUMTY)
- al[k++].sue = ap[j]->n_sue;
- while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
- ty = DECREF(ty);
- if (ty > BTMASK)
- al[k++].df = ap[j]->n_df;
- }
- al[k++].type = TNULL;
- if (k > num)
- cerror("arglist: k%d > num%d", k, num);
- tfree(n);
- if (pdebug)
- alprint(al, 0);
- return al;
-}
-
-/*
- * build a type, and stash away dimensions,
- * from a parse tree of the declaration
- * the type is build top down, the dimensions bottom up
- */
-void
-tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim)
-{
- union dimfun dim;
- NODE *r = NULL;
- int o;
- TWORD t, q;
-
- o = p->n_op;
- if (o == NAME)
- return;
-
- t = INCREF(p->n_type);
- q = p->n_qual;
- switch (o) {
- case CALL:
- t += (FTN-PTR);
- dim.dfun = arglist(p->n_right);
- break;
- case UCALL:
- t += (FTN-PTR);
- dim.dfun = NULL;
- break;
- case LB:
- t += (ARY-PTR);
- if (p->n_right->n_op != ICON) {
- r = p->n_right;
- o = RB;
- } else {
- dim.ddim = p->n_right->n_lval;
- nfree(p->n_right);
-#ifdef notdef
- /* XXX - check dimensions at usage time */
- if (dim.ddim == 0 && p->n_left->n_op == LB)
- uerror("null dimension");
-#endif
- }
- break;
- }
-
- p->n_left->n_type = t;
- p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual;
- tyreduce(p->n_left, tylkp, ntdim);
-
- if (o == LB || o == (UCALL) || o == CALL)
- tylkadd(dim, tylkp, ntdim);
- if (o == RB) {
- dim.ddim = -1;
- tylkadd(dim, tylkp, ntdim);
- arrstk[arrstkp++] = r;
- }
-
- p->n_sp = p->n_left->n_sp;
- p->n_type = p->n_left->n_type;
- p->n_qual = p->n_left->n_qual;
-}
-
-static NODE *
-argcast(NODE *p, TWORD t, union dimfun *d, struct suedef *sue)
-{
- NODE *u, *r = talloc();
-
- r->n_op = NAME;
- r->n_type = t;
- r->n_qual = 0; /* XXX */
- r->n_df = d;
- r->n_sue = sue;
-
- u = buildtree(CAST, r, p);
- nfree(u->n_left);
- r = u->n_right;
- nfree(u);
- return r;
-}
-
-#ifndef NO_C_BUILTINS
-/*
- * replace an alloca function with direct allocation on stack.
- * return a destination temp node.
- */
-static NODE *
-builtin_alloca(NODE *f, NODE *a)
-{
- struct symtab *sp;
- NODE *t, *u;
-
-#ifdef notyet
- if (xnobuiltins)
- return NULL;
-#endif
-
- if (f->n_op != NAME)
- return NULL; /* not direct call */
- sp = f->n_sp;
-
- /* XXX - strcmp is bad, use pointer comparision, redo someday */
- if (strcmp(sp->sname, "__builtin_alloca")) /* use GCC name */
- return NULL; /* not alloca */
-
- if (a == NULL || a->n_op == CM) {
- uerror("wrong arg count for alloca");
- return NULL;
- }
- t = tempnode(0, VOID|PTR, 0, MKSUE(INT) /* XXX */);
- u = tempnode(t->n_lval, VOID|PTR, 0, MKSUE(INT) /* XXX */);
- spalloc(t, a, SZCHAR);
- tfree(f);
- return u;
-}
-#endif
-
-#ifdef PCC_DEBUG
-/*
- * Print a prototype.
- */
-static void
-alprint(union arglist *al, int in)
-{
- int i = 0, j;
-
- for (; al->type != TNULL; al++) {
- for (j = in; j > 0; j--)
- printf(" ");
- printf("arg %d: ", i++);
- tprint(stdout, al->type, 0);
- if (BTYPE(al->type) == STRTY ||
- BTYPE(al->type) == UNIONTY || BTYPE(al->type) == ENUMTY) {
- al++;
- printf("dim %d\n", al->df->ddim);
- }
- printf("\n");
- if (ISFTN(DECREF(al->type))) {
- al++;
- alprint(al->df->dfun, in+1);
- }
- }
- if (in == 0)
- printf("end arglist\n");
-}
-#endif
-/*
- * Do prototype checking and add conversions before calling a function.
- * Argument f is function and a is a CM-separated list of arguments.
- * Returns a merged node (via buildtree() of function and arguments.
- */
-NODE *
-doacall(NODE *f, NODE *a)
-{
- NODE *w, *r;
- union arglist *al;
- struct ap {
- struct ap *next;
- NODE *node;
- } *at, *apole = NULL;
- int argidx/* , hasarray = 0*/;
- TWORD type, arrt;
-
-#ifdef PCC_DEBUG
- if (ddebug) {
- printf("doacall.\n");
- fwalk(f, eprint, 0);
- if (a)
- fwalk(a, eprint, 0);
- }
-#endif
-
- /* First let MD code do something */
- calldec(f, a);
-/* XXX XXX hack */
- if ((f->n_op == CALL || f->n_op == CALL) &&
- f->n_left->n_op == ADDROF &&
- f->n_left->n_left->n_op == NAME &&
- (f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
- goto build;
-/* XXX XXX hack */
-
-#ifndef NO_C_BUILTINS
- /* check for alloca */
- if ((w = builtin_alloca(f, a)))
- return w;
-#endif
- /*
- * Do some basic checks.
- */
- if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) {
- if (Wimplicit_function_declaration) {
- if (f->n_sp != NULL)
- werror("no prototype for function '%s()'",
- f->n_sp->sname);
- else
- werror("no prototype for function pointer");
- }
- /* floats must be cast to double */
- if (a == NULL)
- goto build;
- for (w = a; w->n_op == CM; w = w->n_left) {
- if (w->n_right->n_type != FLOAT)
- continue;
- w->n_right = argcast(w->n_right, DOUBLE,
- NULL, MKSUE(DOUBLE));
- }
- if (a->n_type == FLOAT) {
- MKTY(a, DOUBLE, 0, 0);
- }
- goto build;
- }
- if (al->type == VOID) {
- if (a != NULL)
- uerror("function takes no arguments");
- goto build; /* void function */
- } else {
- if (a == NULL) {
- uerror("function needs arguments");
- goto build;
- }
- }
-#ifdef PCC_DEBUG
- if (pdebug) {
- printf("arglist for %p\n",
- f->n_sp != NULL ? f->n_sp->sname : "function pointer");
- alprint(al, 0);
- }
-#endif
-
- /*
- * Create a list of pointers to the nodes given as arg.
- */
- for (w = a; w->n_op == CM; w = w->n_left) {
- at = tmpalloc(sizeof(struct ap));
- at->node = w->n_right;
- at->next = apole;
- apole = at;
- }
- at = tmpalloc(sizeof(struct ap));
- at->node = w;
- at->next = apole;
- apole = at;
-
- /*
- * Do the typechecking by walking up the list.
- */
- argidx = 1;
- while (al->type != TNULL) {
- if (al->type == TELLIPSIS) {
- /* convert the rest of float to double */
- for (; apole; apole = apole->next) {
- if (apole->node->n_type != FLOAT)
- continue;
- MKTY(apole->node, DOUBLE, 0, 0);
- }
- goto build;
- }
- if (apole == NULL) {
- uerror("too few arguments to function");
- goto build;
- }
-/* al = prototyp, apole = argument till ftn */
-/* type = argumentets typ, arrt = prototypens typ */
- type = apole->node->n_type;
- arrt = al->type;
-#if 0
- if ((hasarray = ISARY(arrt)))
- arrt += (PTR-ARY);
-#endif
- if (ISARY(type))
- type += (PTR-ARY);
-
- /* Check structs */
- if (type <= BTMASK && arrt <= BTMASK) {
- if (type != arrt) {
- if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) {
-incomp: uerror("incompatible types for arg %d",
- argidx);
- } else {
- MKTY(apole->node, arrt, 0, 0)
- }
- } else if (ISSOU(BTYPE(type))) {
- if (apole->node->n_sue != al[1].sue)
- goto incomp;
- }
- goto out;
- }
-
- /* Hereafter its only pointers (or arrays) left */
- /* Check for struct/union intermixing with other types */
- if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
- ((arrt <= BTMASK) && ISSOU(BTYPE(arrt))))
- goto incomp;
-
- /* Check for struct/union compatibility */
- if (type == arrt) {
- if (ISSOU(BTYPE(type))) {
- if (apole->node->n_sue == al[1].sue)
- goto out;
- } else
- goto out;
- }
- if (BTYPE(arrt) == ENUMTY && BTYPE(type) == INT &&
- (arrt & ~BTMASK) == (type & ~BTMASK))
- goto skip; /* XXX enumty destroyed in optim() */
- if (BTYPE(arrt) == VOID && type > BTMASK)
- goto skip; /* void *f = some pointer */
- if (arrt > BTMASK && BTYPE(type) == VOID)
- goto skip; /* some *f = void pointer */
- if (apole->node->n_op == ICON && apole->node->n_lval == 0)
- goto skip; /* Anything assigned a zero */
-
- if ((type & ~BTMASK) == (arrt & ~BTMASK)) {
- /* do not complain for intermixed char/uchar */
- if ((BTYPE(type) == CHAR || BTYPE(type) == UCHAR) &&
- (BTYPE(arrt) == CHAR || BTYPE(arrt) == UCHAR))
- goto skip;
- }
-
- werror("implicit conversion of argument %d due to prototype",
- argidx);
-
-skip: if (ISSTR(BTYPE(arrt))) {
- MKTY(apole->node, arrt, 0, al[1].sue)
- } else {
- MKTY(apole->node, arrt, 0, 0)
- }
-
-out: al++;
- if (ISSTR(BTYPE(arrt)))
- al++;
-#if 0
- while (arrt > BTMASK && !ISFTN(arrt))
- arrt = DECREF(arrt);
- if (ISFTN(arrt) || hasarray)
- al++;
-#else
- while (arrt > BTMASK) {
- if (ISARY(arrt) || ISFTN(arrt)) {
- al++;
- break;
- }
- arrt = DECREF(arrt);
- }
-#endif
- apole = apole->next;
- argidx++;
- }
- if (apole != NULL)
- uerror("too many arguments to function");
-
-build: return buildtree(a == NIL ? UCALL : CALL, f, a);
-}
-
-static int
-chk2(TWORD type, union dimfun *dsym, union dimfun *ddef)
-{
- while (type > BTMASK) {
- switch (type & TMASK) {
- case ARY:
- /* may be declared without dimension */
- if (dsym->ddim == 0)
- dsym->ddim = ddef->ddim;
- if (ddef->ddim && dsym->ddim != ddef->ddim)
- return 1;
- dsym++, ddef++;
- break;
- case FTN:
- /* old-style function headers with function pointers
- * will most likely not have a prototype.
- * This is not considered an error. */
- if (ddef->dfun == NULL) {
-#ifdef notyet
- werror("declaration not a prototype");
-#endif
- } else if (chkftn(dsym->dfun, ddef->dfun))
- return 1;
- dsym++, ddef++;
- break;
- }
- type = DECREF(type);
- }
- return 0;
-}
-
-/*
- * Compare two function argument lists to see if they match.
- */
-int
-chkftn(union arglist *usym, union arglist *udef)
-{
- TWORD t2;
- int ty, tyn;
-
- if (usym == NULL)
- return 0;
- if (cftnsp != NULL && udef == NULL && usym->type == VOID)
- return 0; /* foo() { function with foo(void); prototype */
- if (udef == NULL && usym->type != TNULL)
- return 1;
- while (usym->type != TNULL) {
- if (usym->type == udef->type)
- goto done;
- /*
- * If an old-style declaration, then all types smaller than
- * int are given as int parameters.
- */
- if (intcompare) {
- ty = BTYPE(usym->type);
- tyn = BTYPE(udef->type);
- if (ty == tyn || ty != INT)
- return 1;
- if (tyn == CHAR || tyn == UCHAR ||
- tyn == SHORT || tyn == USHORT)
- goto done;
- return 1;
- } else
- return 1;
-
-done: ty = BTYPE(usym->type);
- t2 = usym->type;
- if (ISSTR(ty)) {
- usym++, udef++;
- if (usym->sue != udef->sue)
- return 1;
- }
-
- while (ISFTN(t2) == 0 && ISARY(t2) == 0 && t2 > BTMASK)
- t2 = DECREF(t2);
- if (t2 > BTMASK) {
- usym++, udef++;
- if (chk2(t2, usym->df, udef->df))
- return 1;
- }
- usym++, udef++;
- }
- if (usym->type != udef->type)
- return 1;
- return 0;
-}
-
-void
-fixtype(NODE *p, int class)
-{
- unsigned int t, type;
- int mod1, mod2;
- /* fix up the types, and check for legality */
-
- if( (type = p->n_type) == UNDEF ) return;
- if ((mod2 = (type&TMASK))) {
- t = DECREF(type);
- while( mod1=mod2, mod2 = (t&TMASK) ){
- if( mod1 == ARY && mod2 == FTN ){
- uerror( "array of functions is illegal" );
- type = 0;
- }
- else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
- uerror( "function returns illegal type" );
- type = 0;
- }
- t = DECREF(t);
- }
- }
-
- /* detect function arguments, watching out for structure declarations */
- if (instruct && ISFTN(type)) {
- uerror("function illegal in structure or union");
- type = INCREF(type);
- }
- p->n_type = type;
-}
-
-/*
- * give undefined version of class
- */
-int
-uclass(int class)
-{
- if (class == SNULL)
- return(EXTERN);
- else if (class == STATIC)
- return(USTATIC);
- else if (class == FORTRAN)
- return(UFORTRAN);
- else
- return(class);
-}
-
-int
-fixclass(int class, TWORD type)
-{
- /* first, fix null class */
- if (class == SNULL) {
- if (instruct&INSTRUCT)
- class = MOS;
- else if (instruct&INUNION)
- class = MOU;
- else if (blevel == 0)
- class = EXTDEF;
- else
- class = AUTO;
- }
-
- /* now, do general checking */
-
- if( ISFTN( type ) ){
- switch( class ) {
- default:
- uerror( "function has illegal storage class" );
- case AUTO:
- class = EXTERN;
- case EXTERN:
- case EXTDEF:
- case FORTRAN:
- case TYPEDEF:
- case STATIC:
- case UFORTRAN:
- case USTATIC:
- ;
- }
- }
-
- if( class&FIELD ){
- if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
- return( class );
- }
-
- switch( class ){
-
- case MOU:
- if( !(instruct&INUNION) ) uerror( "illegal MOU class" );
- return( class );
-
- case MOS:
- if( !(instruct&INSTRUCT) ) uerror( "illegal MOS class" );
- return( class );
-
- case MOE:
- if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal MOE class" );
- return( class );
-
- case REGISTER:
- if (blevel == 0)
- uerror( "illegal register declaration" );
- if (blevel == 1)
- return(PARAM);
- else
- return(AUTO);
-
- case AUTO:
- if( blevel < 2 ) uerror( "illegal ULABEL class" );
- return( class );
-
- case UFORTRAN:
- case FORTRAN:
-# ifdef NOFORTRAN
- NOFORTRAN; /* a condition which can regulate the FORTRAN usage */
-# endif
- if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
- else {
- type = DECREF(type);
- if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
- uerror( "fortran function has wrong type" );
- }
- }
- case STNAME:
- case UNAME:
- case ENAME:
- case EXTERN:
- case STATIC:
- case EXTDEF:
- case TYPEDEF:
- case USTATIC:
- return( class );
-
- default:
- cerror( "illegal class: %d", class );
- /* NOTREACHED */
-
- }
- return 0; /* XXX */
-}
-
-/*
- * Generates a goto statement; sets up label number etc.
- */
-void
-gotolabel(char *name)
-{
- struct symtab *s = lookup(name, SLBLNAME);
-
- if (s->soffset == 0)
- s->soffset = -getlab();
- branch(s->soffset < 0 ? -s->soffset : s->soffset);
-}
-
-/*
- * Sets a label for gotos.
- */
-void
-deflabel(char *name)
-{
- struct symtab *s = lookup(name, SLBLNAME);
-
- if (s->soffset > 0)
- uerror("label '%s' redefined", name);
- if (s->soffset == 0)
- s->soffset = getlab();
- if (s->soffset < 0)
- s->soffset = -s->soffset;
- plabel( s->soffset);
-}
-
-struct symtab *
-getsymtab(char *name, int flags)
-{
- struct symtab *s;
-
- if (flags & STEMP) {
- s = tmpalloc(sizeof(struct symtab));
- } else {
- s = permalloc(sizeof(struct symtab));
- symtabcnt++;
- }
- s->sname = name;
- s->snext = NULL;
- s->stype = UNDEF;
- s->squal = 0;
- s->sclass = SNULL;
- s->sflags = flags & SMASK;
- s->soffset = 0;
- s->slevel = blevel;
- return s;
-}
-
-#ifdef PCC_DEBUG
-static char *
-ccnames[] = { /* names of storage classes */
- "SNULL",
- "AUTO",
- "EXTERN",
- "STATIC",
- "REGISTER",
- "EXTDEF",
- "LABEL",
- "ULABEL",
- "MOS",
- "PARAM",
- "STNAME",
- "MOU",
- "UNAME",
- "TYPEDEF",
- "FORTRAN",
- "ENAME",
- "MOE",
- "UFORTRAN",
- "USTATIC",
- };
-
-char *
-scnames(int c)
-{
- /* return the name for storage class c */
- static char buf[12];
- if( c&FIELD ){
- snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ );
- return( buf );
- }
- return( ccnames[c] );
- }
-#endif
--- usr.bin/pcc/cc/ccom/init.c
+++ /dev/null
@@ -1,961 +0,0 @@
-/* $Id: init.c,v 1.30 2007/09/24 20:34:03 ragge Exp $ */
-
-/*
- * Copyright (c) 2004, 2007 Anders Magnusson (ragge at ludd.ltu.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 "pass1.h"
-#include <string.h>
-
-/*
- * Four machine-dependent routines may be called during initialization:
- *
- * instring(char *str) - Print out a string.
- * zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ.
- * infld(CONSZ off, int fsz, CONSZ val)
- * - sets the bitfield val starting at off and size fsz.
- * inval(CONSZ off, int fsz, NODE *)
- * - prints an integer constant which may have
- * a label associated with it, located at off and
- * size fsz.
- *
- * Initialization may be of different kind:
- * - Initialization at compile-time, all values are constants and laid
- * out in memory. Static or extern variables outside functions.
- * - Initialization at run-time, written to their values as code.
- *
- * Currently run-time-initialized variables are only initialized by using
- * move instructions. An optimization might be to detect that it is
- * initialized with constants and therefore copied from readonly memory.
- */
-
-/*
- * The base element(s) of an initialized variable is kept in a linked
- * list, allocated while initialized.
- *
- * When a scalar is found, entries are popped of the instk until it's
- * possible to find an entry for a new scalar; then onstk() is called
- * to get the correct type and size of that scalar.
- *
- * If a right brace is found, pop the stack until a matching left brace
- * were found while filling the elements with zeros. This left brace is
- * also marking where the current level is for designated initializations.
- *
- * Position entries are increased when traversing back down into the stack.
- */
-
-/*
- * Good-to-know entries from symtab:
- * soffset - # of bits from beginning of this structure.
- */
-
-/*
- * TO FIX:
- * - Alignment of structs on like i386 char members.
- */
-
-int idebug;
-
-/*
- * Struct used in array initialisation.
- */
-static struct instk {
- struct instk *in_prev; /* linked list */
- struct symtab **in_xp; /* member in structure initializations */
- struct symtab *in_sym; /* stab index */
- union dimfun *in_df; /* dimenston of array */
- TWORD in_t; /* type for this level */
- int in_n; /* number of arrays seen so far */
- int in_fl; /* flag which says if this level is controlled by {} */
-} *pstk, pbase;
-
-static struct symtab *csym;
-
-#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
-
-#ifdef PCC_DEBUG
-static void prtstk(struct instk *in);
-#endif
-
-/*
- * Linked lists for initializations.
- */
-struct ilist {
- struct ilist *next;
- CONSZ off; /* bit offset of this entry */
- int fsz; /* bit size of this entry */
- NODE *n; /* node containing this data info */
-};
-
-struct llist {
- SLIST_ENTRY(llist) next;
- CONSZ begsz; /* bit offset of this entry */
- struct ilist *il;
-} *curll;
-static SLIST_HEAD(, llist) lpole;
-static CONSZ basesz;
-static int numents; /* # of array entries allocated */
-
-static struct ilist *
-getil(struct ilist *next, CONSZ b, int sz, NODE *n)
-{
- struct ilist *il = tmpalloc(sizeof(struct ilist));
-
- il->off = b;
- il->fsz = sz;
- il->n = n;
- il->next = next;
- return il;
-}
-
-/*
- * Allocate a new struct defining a block of initializers appended to the
- * end of the llist. Return that entry.
- */
-static struct llist *
-getll(void)
-{
- struct llist *ll;
-
- ll = tmpalloc(sizeof(struct llist));
- ll->begsz = numents * basesz;
- ll->il = NULL;
- SLIST_INSERT_LAST(&lpole, ll, next);
- numents++;
- return ll;
-}
-
-/*
- * Return structure containing off bitnumber.
- * Allocate more entries, if needed.
- * This is not bright implemented.
- */
-static struct llist *
-setll(OFFSZ off)
-{
- struct llist *ll;
-
- /* Ensure that we have enough entries */
- while (off >= basesz * numents)
- (void)getll();
- SLIST_FOREACH(ll, &lpole, next)
- if (ll->begsz <= off && ll->begsz + basesz > off)
- break;
- return ll; /* ``cannot fail'' */
-}
-
-/*
- * beginning of initialization; allocate space to store initialized data.
- * remember storage class for writeout in endinit().
- * p is the newly declarated type.
- */
-void
-beginit(struct symtab *sp)
-{
- struct instk *is = &pbase;
- struct llist *ll;
-
-#ifdef PCC_DEBUG
- if (idebug)
- printf("beginit(), sclass %s\n", scnames(sp->sclass));
-#endif
-
- csym = sp;
-
- numents = 0; /* no entries in array list */
- if (ISARY(sp->stype))
- basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->ssue);
- else
- basesz = tsize(DECREF(sp->stype), sp->sdf, sp->ssue);
- SLIST_INIT(&lpole);
- curll = ll = getll(); /* at least first entry in list */
-
- /* first element */
- is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
- is->in_n = 0;
- is->in_t = sp->stype;
- is->in_sym = sp;
- is->in_df = sp->sdf;
- is->in_fl = 0;
- is->in_prev = NULL;
- pstk = is;
-}
-
-/*
- * Push a new entry on the initializer stack.
- * The new entry will be "decremented" to the new sub-type of the previous
- * entry when called.
- * Popping of entries is done elsewhere.
- */
-static void
-stkpush(void)
-{
- struct instk *is;
- struct symtab *sq, *sp;
- TWORD t;
-
- if (pstk == NULL) {
- sp = csym;
- t = 0;
- } else {
- t = pstk->in_t;
- sp = pstk->in_sym;
- }
-
-#ifdef PCC_DEBUG
- if (idebug) {
- printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass));
- tprint(stdout, t, 0);
- }
-#endif
-
- /*
- * Figure out what the next initializer will be, and push it on
- * the stack. If this is an array, just decrement type, if it
- * is a struct or union, extract the next element.
- */
- is = tmpalloc(sizeof(struct instk));
- is->in_fl = 0;
- is->in_n = 0;
- if (pstk == NULL) {
- /* stack empty */
- is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
- is->in_t = sp->stype;
- is->in_sym = sp;
- is->in_df = sp->sdf;
- } else if (ISSOU(t)) {
- sq = *pstk->in_xp;
- if (sq == NULL) {
- uerror("excess of initializing elements");
- } else {
- is->in_xp = ISSOU(sq->stype) ? sq->ssue->suelem : 0;
- is->in_t = sq->stype;
- is->in_sym = sq;
- is->in_df = sq->sdf;
- }
- } else if (ISARY(t)) {
- is->in_xp = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->suelem : 0;
- is->in_t = DECREF(t);
- is->in_sym = sp;
- if (pstk->in_df->ddim && pstk->in_n >= pstk->in_df->ddim) {
- werror("excess of initializing elements");
- pstk->in_n--;
- }
- if (ISARY(is->in_t))
- is->in_df = pstk->in_df+1;
- } else
- uerror("too many left braces");
- is->in_prev = pstk;
- pstk = is;
-
-#ifdef PCC_DEBUG
- if (idebug) {
- printf(" newtype ");
- tprint(stdout, is->in_t, 0);
- printf("\n");
- }
-#endif
-}
-
-/*
- * pop down to either next level that can handle a new initializer or
- * to the next braced level.
- */
-static void
-stkpop(void)
-{
-#ifdef PCC_DEBUG
- if (idebug)
- printf("stkpop\n");
-#endif
- for (; pstk; pstk = pstk->in_prev) {
- if (pstk->in_t == STRTY) {
- pstk->in_xp++;
- if (*pstk->in_xp != NULL)
- break;
- }
- if (ISSOU(pstk->in_t) && pstk->in_fl)
- break; /* need } */
- if (ISARY(pstk->in_t)) {
- pstk->in_n++;
- if (pstk->in_fl)
- break;
- if (pstk->in_df->ddim == 0 ||
- pstk->in_n < pstk->in_df->ddim)
- break; /* ger more elements */
- }
- }
-#ifdef PCC_DEBUG
- if (idebug > 1)
- prtstk(pstk);
-#endif
-}
-
-/*
- * Count how many elements an array may consist of.
- */
-static int
-acalc(struct instk *is, int n)
-{
- if (is == NULL || !ISARY(is->in_t))
- return 0;
- return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n;
-}
-
-/*
- * Find current bit offset of the top element on the stack from
- * the beginning of the aggregate.
- */
-static CONSZ
-findoff(void)
-{
- struct instk *is;
- OFFSZ off;
-
-#ifdef PCC_DEBUG
- if (ISARY(pstk->in_t) || ISSOU(pstk->in_t))
- cerror("findoff on bad type");
-#endif
-
- /*
- * Offset calculations. If:
- * - previous type is STRTY, soffset has in-struct offset.
- * - this type is ARY, offset is ninit*stsize.
- */
- for (off = 0, is = pstk; is; is = is->in_prev) {
- if (is->in_prev && is->in_prev->in_t == STRTY)
- off += is->in_sym->soffset;
- if (ISARY(is->in_t)) {
- /* suesize is the basic type, so adjust */
- TWORD t = is->in_t;
- OFFSZ o;
- while (ISARY(t))
- t = DECREF(t);
- o = ISPTR(t) ? SZPOINT(t) : is->in_sym->ssue->suesize;
- off += o * acalc(is, 1);
- while (is->in_prev && ISARY(is->in_prev->in_t)) {
- if (is->in_prev->in_prev &&
- is->in_prev->in_prev->in_t == STRTY)
- off += is->in_sym->soffset;
- is = is->in_prev;
- }
- }
- }
- if (idebug>1) {
- printf("findoff: off %lld\n", off);
- prtstk(pstk);
- }
- return off;
-}
-
-/*
- * Insert the node p with size fsz at position off.
- * Bit fields are already dealt with, so a node of correct type
- * with correct alignment and correct bit offset is given.
- */
-static void
-nsetval(CONSZ off, int fsz, NODE *p)
-{
- struct llist *ll;
- struct ilist *il;
-
- if (idebug>1)
- printf("setval: off %lld fsz %d p %p\n", off, fsz, p);
-
- if (fsz == 0)
- return;
-
- ll = setll(off);
- off -= ll->begsz;
- if (ll->il == NULL) {
- ll->il = getil(NULL, off, fsz, p);
- } else {
- il = ll->il;
- if (il->off > off) {
- ll->il = getil(ll->il, off, fsz, p);
- } else {
- for (il = ll->il; il->next; il = il->next)
- if (il->off <= off && il->next->off > off)
- break;
- if (il->off == off) {
- /* replace */
- nfree(il->n);
- il->n = p;
- } else
- il->next = getil(il->next, off, fsz, p);
- }
- }
-}
-
-/*
- * Align data and set correct location.
- */
-static void
-setscl(struct symtab *sp)
-{
- setloc1((sp->squal << TSHIFT) & CON ? RDATA : DATA);
- defalign(talign(sp->stype, sp->ssue));
- if (sp->sclass == EXTDEF ||
- (sp->sclass == STATIC && sp->slevel == 0)) {
- defnam(sp);
- } else {
- if (sp->soffset == NOOFFSET)
- cerror("setscl");
- deflab1(sp->soffset);
- }
-}
-
-/*
- * take care of generating a value for the initializer p
- * inoff has the current offset (last bit written)
- * in the current word being generated
- */
-void
-scalinit(NODE *p)
-{
- CONSZ woff;
- NODE *q;
- int fsz;
-
-#ifdef PCC_DEBUG
- if (idebug > 2) {
- printf("scalinit(%p)\n", p);
- fwalk(p, eprint, 0);
- prtstk(pstk);
- }
-#endif
-
- if (nerrors)
- return;
-
- p = optim(p);
-
- if (csym->sclass != AUTO && p->n_op != ICON &&
- p->n_op != FCON && p->n_op != NAME)
- cerror("scalinit not leaf");
-
- /* Out of elements? */
- if (pstk == NULL) {
- uerror("excess of initializing elements");
- return;
- }
-
- /*
- * Get to the simple type if needed.
- */
- while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
- stkpush();
-
- /* let buildtree do typechecking (and casting) */
- q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_sym->sdf,
- pstk->in_sym->ssue);
- p = buildtree(ASSIGN, q, p);
- nfree(p->n_left);
- q = optim(p->n_right);
- nfree(p);
-
- /* bitfield sizes are special */
- if (pstk->in_sym->sclass & FIELD)
- fsz = -(pstk->in_sym->sclass & FLDSIZ);
- else
- fsz = tsize(pstk->in_t, pstk->in_sym->sdf, pstk->in_sym->ssue);
- woff = findoff();
-
- nsetval(woff, fsz, q);
-
- stkpop();
-#ifdef PCC_DEBUG
- if (idebug > 2) {
- printf("scalinit e(%p)\n", p);
- }
-#endif
-}
-
-/*
- * Generate code to insert a value into a bitfield.
- */
-static void
-insbf(OFFSZ off, int fsz, int val)
-{
- struct symtab sym;
- NODE *p, *r;
- TWORD typ;
-
-#ifdef PCC_DEBUG
- if (idebug > 1)
- printf("insbf: off %lld fsz %d val %d\n", off, fsz, val);
-#endif
-
- if (fsz == 0)
- return;
-
- /* small opt: do char instead of bf asg */
- if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR)
- typ = CHAR;
- else
- typ = INT;
- /* Fake a struct reference */
- spname = csym;
- p = buildtree(ADDROF,
- buildtree(NAME, NIL, NIL), NIL);
- r = block(ICON, NIL, NIL, typ, 0, MKSUE(typ));
- sym.stype = typ;
- sym.squal = 0;
- sym.sdf = 0;
- sym.ssue = MKSUE(typ);
- sym.soffset = off;
- sym.sclass = typ == INT ? FIELD | fsz : MOU;
- r->n_sp = &sym;
- p = block(STREF, p, r, INT, 0, MKSUE(INT));
- ecode(buildtree(ASSIGN, stref(p), bcon(val)));
-}
-
-/*
- * Clear a bitfield, starting at off and size fsz.
- */
-static void
-clearbf(OFFSZ off, OFFSZ fsz)
-{
- /* Pad up to the next even initializer */
- if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) {
- int ba = ((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off;
- if (ba > fsz)
- ba = fsz;
- insbf(off, ba, 0);
- off += ba;
- fsz -= ba;
- }
- while (fsz >= SZCHAR) {
- insbf(off, SZCHAR, 0);
- off += SZCHAR;
- fsz -= SZCHAR;
- }
- if (fsz)
- insbf(off, fsz, 0);
-}
-
-/*
- * final step of initialization.
- * print out init nodes and generate copy code (if needed).
- */
-void
-endinit(void)
-{
- struct llist *ll;
- struct ilist *il;
- int fsz;
- OFFSZ lastoff, tbit;
-
-#ifdef PCC_DEBUG
- if (idebug)
- printf("endinit()\n");
-#endif
-
- if (csym->sclass != AUTO)
- setscl(csym);
-
- /* Calculate total block size */
- if (ISARY(csym->stype) && csym->sdf->ddim == 0) {
- tbit = numents*basesz; /* open-ended arrays */
- csym->sdf->ddim = numents;
- if (csym->sclass == AUTO) { /* Get stack space */
- csym->soffset = NOOFFSET;
- oalloc(csym, &autooff);
- }
- } else
- tbit = tsize(csym->stype, csym->sdf, csym->ssue);
-
- /* Traverse all entries and print'em out */
- lastoff = 0;
- SLIST_FOREACH(ll, &lpole, next) {
- for (il = ll->il; il; il = il->next) {
-#ifdef PCC_DEBUG
- if (idebug > 1) {
- printf("off %lld size %d val %lld type ",
- ll->begsz+il->off, il->fsz, il->n->n_lval);
- tprint(stdout, il->n->n_type, 0);
- printf("\n");
- }
-#endif
- fsz = il->fsz;
- if (csym->sclass == AUTO) {
- struct symtab sym;
- NODE *p, *r, *n;
-
- if (ll->begsz + il->off > lastoff)
- clearbf(lastoff,
- (ll->begsz + il->off) - lastoff);
-
- /* Fake a struct reference */
- spname = csym;
- p = buildtree(ADDROF,
- buildtree(NAME, NIL, NIL), NIL);
- n = il->n;
- r = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
- sym.stype = n->n_type;
- sym.squal = n->n_qual;
- sym.sdf = n->n_df;
- sym.ssue = n->n_sue;
- sym.soffset = ll->begsz + il->off;
- sym.sclass = fsz < 0 ? FIELD | -fsz : 0;
- r->n_sp = &sym;
- p = block(STREF, p, r, INT, 0, MKSUE(INT));
- ecode(buildtree(ASSIGN, stref(p), il->n));
- if (fsz < 0)
- fsz = -fsz;
-
- } else {
- if (ll->begsz + il->off > lastoff)
- zbits(lastoff,
- (ll->begsz + il->off) - lastoff);
- if (fsz < 0) {
- fsz = -fsz;
- infld(il->off, fsz, il->n->n_lval);
- } else
- ninval(il->off, fsz, il->n);
- nfree(il->n);
- }
- lastoff = ll->begsz + il->off + fsz;
- }
- }
- if (csym->sclass == AUTO) {
- clearbf(lastoff, tbit-lastoff);
- } else
- zbits(lastoff, tbit-lastoff);
-}
-
-/*
- * process an initializer's left brace
- */
-void
-ilbrace()
-{
-
-#ifdef PCC_DEBUG
- if (idebug)
- printf("ilbrace()\n");
-#endif
-
- if (pstk == NULL)
- return;
-
- stkpush();
- pstk->in_fl = 1; /* mark lbrace */
-#ifdef PCC_DEBUG
- if (idebug > 1)
- prtstk(pstk);
-#endif
-}
-
-/*
- * called when a '}' is seen
- */
-void
-irbrace()
-{
-#ifdef PCC_DEBUG
- if (idebug)
- printf("irbrace()\n");
- if (idebug > 2)
- prtstk(pstk);
-#endif
-
- if (pstk == NULL)
- return;
-
- /* Got right brace, search for corresponding in the stack */
- for (; pstk->in_prev != NULL; pstk = pstk->in_prev) {
- if(!pstk->in_fl)
- continue;
-
- /* we have one now */
-
- pstk->in_fl = 0; /* cancel { */
- if (ISARY(pstk->in_t))
- pstk->in_n = pstk->in_df->ddim;
- else if (pstk->in_t == STRTY) {
- while (pstk->in_xp[1] != NULL)
- pstk->in_xp++;
- }
- stkpop();
- return;
- }
-}
-
-/*
- * Create a new init stack based on given elements.
- */
-static void
-mkstack(NODE *p)
-{
-
-#ifdef PCC_DEBUG
- if (idebug)
- printf("mkstack: %p\n", p);
-#endif
-
- if (p == NULL)
- return;
- mkstack(p->n_left);
-
- switch (p->n_op) {
- case LB: /* Array index */
- if (p->n_right->n_op != ICON)
- cerror("mkstack");
- if (!ISARY(pstk->in_t))
- uerror("array indexing non-array");
- pstk->in_n = p->n_right->n_lval;
- nfree(p->n_right);
- break;
-
- case NAME:
- if (pstk->in_xp) {
- for (; pstk->in_xp[0]; pstk->in_xp++)
- if (pstk->in_xp[0]->sname == (char *)p->n_sp)
- break;
- if (pstk->in_xp[0] == NULL)
- uerror("member missing");
- } else {
- uerror("not a struct/union");
- }
- break;
- default:
- cerror("mkstack2");
- }
- nfree(p);
- stkpush();
-
-}
-
-/*
- * Initialize a specific element, as per C99.
- */
-void
-desinit(NODE *p)
-{
- int op = p->n_op;
-
- if (pstk == NULL)
- stkpush(); /* passed end of array */
- while (pstk->in_prev && pstk->in_fl == 0)
- pstk = pstk->in_prev; /* Empty stack */
-
- if (ISSOU(pstk->in_t))
- pstk->in_xp = pstk->in_sym->ssue->suelem;
-
- mkstack(p); /* Setup for assignment */
-
- /* pop one step if SOU, ilbrace will push */
- if (op == NAME)
- pstk = pstk->in_prev;
-
-#ifdef PCC_DEBUG
- if (idebug > 1) {
- printf("desinit e\n");
- prtstk(pstk);
- }
-#endif
-}
-
-/*
- * Convert a string to an array of char/wchar for asginit.
- */
-static void
-strcvt(NODE *p)
-{
- char *s;
- int i;
-
- for (s = p->n_sp->sname; *s != 0; ) {
- if (*s++ == '\\') {
- i = esccon(&s);
- } else
- i = (unsigned char)s[-1];
- asginit(bcon(i));
- }
- nfree(p);
-}
-
-/*
- * Do an assignment to a struct element.
- */
-void
-asginit(NODE *p)
-{
- int g;
-
-#ifdef PCC_DEBUG
- if (idebug)
- printf("asginit %p\n", p);
- if (idebug > 1 && p)
- fwalk(p, eprint, 0);
-#endif
-
- /* convert string to array of char */
- if (p && DEUNSIGN(p->n_type) == ARY+CHAR) {
- /*
- * ...but only if next element is ARY+CHAR, otherwise
- * just fall through.
- */
-
- /* HACKHACKHACK */
- struct instk *is = pstk;
-
- if (pstk == NULL)
- stkpush();
- while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
- stkpush();
- if (pstk->in_prev &&
- DEUNSIGN(pstk->in_prev->in_t) == ARY+CHAR) {
- pstk = pstk->in_prev;
- if ((g = pstk->in_fl) == 0)
- pstk->in_fl = 1; /* simulate ilbrace */
-
- strcvt(p);
- if (g == 0)
- irbrace();
- return;
- } else
- pstk = is; /* no array of char */
- /* END HACKHACKHACK */
- }
-
- if (p == NULL) { /* only end of compound stmt */
- irbrace();
- } else /* assign next element */
- scalinit(p);
-}
-
-#ifdef PCC_DEBUG
-void
-prtstk(struct instk *in)
-{
- int i, o = 0;
-
- printf("init stack:\n");
- for (; in != NULL; in = in->in_prev) {
- for (i = 0; i < o; i++)
- printf(" ");
- printf("%p) '%s' ", in, in->in_sym->sname);
- tprint(stdout, in->in_t, 0);
- printf(" %s ", scnames(in->in_sym->sclass));
- if (in->in_df && in->in_df->ddim)
- printf("arydim=%d ", in->in_df->ddim);
- printf("ninit=%d ", in->in_n);
- if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t))
- printf("stsize=%d ", in->in_sym->ssue->suesize);
- if (in->in_fl) printf("{ ");
- printf("soff=%d ", in->in_sym->soffset);
- if (in->in_t == STRTY) {
- if (in->in_xp && in->in_xp[0])
- printf("curel %s ", in->in_xp[0]->sname);
- else
- printf("END struct");
- }
- printf("\n");
- o++;
- }
-}
-#endif
-
-/*
- * Do a simple initialization.
- * At block 0, just print out the value, at higher levels generate
- * appropriate code.
- */
-void
-simpleinit(struct symtab *sp, NODE *p)
-{
- /* May be an initialization of an array of char by a string */
- if ((DEUNSIGN(p->n_type) == ARY+CHAR &&
- DEUNSIGN(sp->stype) == ARY+CHAR) ||
- (DEUNSIGN(p->n_type) == ARY+WCHAR_TYPE &&
- DEUNSIGN(sp->stype) == ARY+WCHAR_TYPE)) {
- /* Handle "aaa" as { 'a', 'a', 'a' } */
- beginit(sp);
- strcvt(p);
- if (csym->sdf->ddim == 0)
- scalinit(bcon(0)); /* Null-term arrays */
- endinit();
- return;
- }
-
- switch (sp->sclass) {
- case STATIC:
- case EXTDEF:
- spname = sp;
- p = optim(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
- setscl(sp);
- ninval(0, p->n_right->n_sue->suesize, p->n_right);
- tfree(p);
- break;
-
- case AUTO:
- case REGISTER:
- if (ISARY(sp->stype))
- cerror("no array init");
- spname = sp;
- ecomp(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
- break;
-
- default:
- uerror("illegal initialization");
- }
-}
--- usr.bin/pcc/cc/ccom/gcc_compat.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* $Id: gcc_compat.c,v 1.7 2006/05/13 06:35:36 ragge Exp $ */
-/*
- * Copyright (c) 2004 Anders Magnusson (ragge at 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.
- */
-
-/*
- * Routines to support some of the gcc extensions to C.
- */
-#ifdef GCC_COMPAT
-
-#include "pass1.h"
-#include "cgram.h"
-
-#include <string.h>
-
-static struct kw {
- char *name, *ptr;
- int rv;
-} kw[] = {
- { "__asm", NULL, C_ASM },
- { "__signed", NULL, 0 },
- { "__inline", NULL, C_FUNSPEC },
- { "__const", NULL, 0 },
- { "__asm__", NULL, C_ASM },
- { NULL, NULL, 0 },
-};
-
-void
-gcc_init()
-{
- struct kw *kwp;
-
- for (kwp = kw; kwp->name; kwp++)
- kwp->ptr = addname(kwp->name);
-
-}
-
-/*
- * See if a string matches a gcc keyword.
- */
-int
-gcc_keyword(char *str, NODE **n)
-{
- struct kw *kwp;
- int i;
-
- for (i = 0, kwp = kw; kwp->name; kwp++, i++)
- if (str == kwp->ptr)
- break;
- if (kwp->name == NULL)
- return 0;
- if (kwp->rv)
- return kwp->rv;
- switch (i) {
- case 1: /* __signed */
- *n = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
- return C_TYPE;
- case 3: /* __const */
- *n = block(QUALIFIER, NIL, NIL, CON, 0, 0);
- return C_QUALIFIER;
- }
- cerror("gcc_keyword");
- return 0;
-}
-
-static struct ren {
- struct ren *next;
- char *old, *new;
-} *renp;
-/*
- * Save a name for later renaming of a variable.
- */
-void
-gcc_rename(struct symtab *sp, char *newname)
-{
- struct ren *ren = permalloc(sizeof(struct ren));
-
- sp->sflags |= SRENAME;
- ren->old = sp->sname;
- ren->new = newstring(newname, strlen(newname)+1);
- ren->next = renp;
- renp = ren;
-}
-
-/*
- * Get a renamed variable.
- */
-char *
-gcc_findname(struct symtab *sp)
-{
- struct ren *w;
-
- if ((sp->sflags & SRENAME) == 0)
- return exname(sp->sname);
-
- for (w = renp; w; w = w->next) {
- if (w->old == sp->sname)
- return exname(w->new);
- }
- cerror("gcc_findname %s", sp->sname);
- return NULL;
-}
-#endif
--- usr.bin/pcc/cc/ccom/pass1.h
+++ /dev/null
@@ -1,394 +0,0 @@
-/* $Id: pass1.h,v 1.125 2007/09/09 10:01:01 ragge Exp $ */
-/*
- * 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 conditionsand 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 <sys/types.h>
-#include <stdarg.h>
-
-#include "manifest.h"
-
-#include "protos.h"
-#include "ccconfig.h"
-
-/*
- * Storage classes
- */
-#define SNULL 0
-#define AUTO 1
-#define EXTERN 2
-#define STATIC 3
-#define REGISTER 4
-#define EXTDEF 5
-/* #define LABEL 6*/
-/* #define ULABEL 7*/
-#define MOS 8
-#define PARAM 9
-#define STNAME 10
-#define MOU 11
-#define UNAME 12
-#define TYPEDEF 13
-#define FORTRAN 14
-#define ENAME 15
-#define MOE 16
-#define UFORTRAN 17
-#define USTATIC 18
-#define ILABEL 19
-
- /* field size is ORed in */
-#define FIELD 0100
-#define FLDSIZ 077
-extern char *scnames(int);
-
-/*
- * Symbol table flags
- */
-#define SNORMAL 0
-#define STAGNAME 01
-#define SLBLNAME 02
-#define SMOSNAME 03
-#define SSTRING 04
-#define NSTYPES 05
-#define SMASK 07
-
-#define SSET 00010
-#define SREF 00020
-#define SNOCREAT 00040
-#define STEMP 00100
-#define SDYNARRAY 00200
-#define SINLINE 00400
-#define STNODE 01000
-#ifdef GCC_COMPAT
-#define SRENAME 02000 /* Node is renamed */
-#endif
-#define SASG 04000
-
-#ifndef FIXDEF
-#define FIXDEF(p)
-#endif
-
- /* alignment of initialized quantities */
-#ifndef AL_INIT
-#define AL_INIT ALINT
-#endif
-
-struct rstack;
-struct symtab;
-union arglist;
-
-/*
- * Dimension/prototype information.
- * ddim > 0 holds the dimension of an array.
- * ddim < 0 is a dynamic array and refers to a tempnode.
- */
-union dimfun {
- int ddim; /* Dimension of an array */
- union arglist *dfun; /* Prototype index */
-};
-
-/*
- * Struct/union/enum definition.
- * The first element (size) is used for other types as well.
- */
-struct suedef {
- int suesize; /* Size of the struct */
- struct symtab **suelem;/* points to the list of elements */
- int suealign; /* Alignment of this struct */
-};
-
-/*
- * Argument list member info when storing prototypes.
- */
-union arglist {
- TWORD type;
- union dimfun *df;
- struct suedef *sue;
-};
-#define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
-#define TELLIPSIS INCREF(INCREF(MOETY))
-
-/*
- * Symbol table definition.
- *
- * The symtab_hdr struct is used to save label info in NAME and ICON nodes.
- */
-struct symtab_hdr {
- struct symtab *h_next; /* link to other symbols in the same scope */
- int h_offset; /* offset or value */
- char h_sclass; /* storage class */
- char h_slevel; /* scope level */
- short h_sflags; /* flags, see below */
-};
-
-struct symtab {
- struct symtab_hdr hdr;
- char *sname;
- TWORD stype; /* type word */
- TWORD squal; /* qualifier word */
- union dimfun *sdf; /* ptr to the dimension/prototype array */
- struct suedef *ssue; /* ptr to the definition table */
- int suse; /* line number of last use of the variable */
-};
-
-#define snext hdr.h_next
-#define soffset hdr.h_offset
-#define sclass hdr.h_sclass
-#define slevel hdr.h_slevel
-#define sflags hdr.h_sflags
-
-#define MKSUE(type) &btdims[type]
-extern struct suedef btdims[];
-
-/*
- * External definitions
- */
-struct swents { /* switch table */
- struct swents *next; /* Next struct in linked list */
- CONSZ sval; /* case value */
- int slab; /* associated label */
-};
-void genswitch(int, struct swents **, int);
-
-extern int blevel;
-extern int instruct, got_type;
-extern int oldstyle;
-
-extern int lineno, nerrors;
-
-extern char *ftitle;
-extern struct symtab *cftnsp;
-extern int autooff, maxautooff, argoff, strucoff;
-extern int brkflag;
-extern int lastloc;
-
-extern OFFSZ inoff;
-
-extern int reached;
-extern int isinlining;
-
-/* tunnel to buildtree for name id's */
-
-extern struct symtab *spname;
-
-extern int sdebug, idebug, pdebug;
-
-/* various labels */
-extern int brklab;
-extern int contlab;
-extern int flostat;
-extern int retlab;
-
-/*
- * Flags used in structures/unions
- */
-#define INSTRUCT 02
-#define INUNION 04
-
-/*
- * Flags used in the (elementary) flow analysis ...
- */
-#define FBRK 02
-#define FCONT 04
-#define FDEF 010
-#define FLOOP 020
-
-/* mark an offset which is undefined */
-
-#define NOOFFSET (-10201)
-
-/* declarations of various functions */
-extern NODE
- *buildtree(int, NODE *l, NODE *r),
- *mkty(unsigned, union dimfun *, struct suedef *),
- *rstruct(char *, int),
- *dclstruct(struct rstack *),
- *strend(char *),
- *wstrend(char *),
- *tymerge(NODE *typ, NODE *idp),
- *stref(NODE *),
- *offcon(OFFSZ, TWORD, union dimfun *, struct suedef *),
- *bcon(int),
- *bpsize(NODE *),
- *convert(NODE *, int),
- *pconvert(NODE *),
- *oconvert(NODE *),
- *ptmatch(NODE *),
- *tymatch(NODE *),
- *makety(NODE *, TWORD, TWORD, union dimfun *, struct suedef *),
- *block(int, NODE *, NODE *r, TWORD, union dimfun *, struct suedef *),
- *doszof(NODE *),
- *talloc(void),
- *optim(NODE *),
- *clocal(NODE *),
- *ccopy(NODE *),
- *btsize(TWORD, union dimfun *, struct suedef *),
- *tempnode(int, TWORD type, union dimfun *df, struct suedef *sue),
- *doacall(NODE *f, NODE *a);
-OFFSZ tsize(TWORD, union dimfun *, struct suedef *),
- psize(NODE *);
-NODE * typenode(NODE *new);
-void spalloc(NODE *, NODE *, OFFSZ);
-char *exname(char *);
-
-int oalloc(struct symtab *p, int *poff);
-void deflabel(char *);
-void deflab1(int);
-void setloc1(int);
-void gotolabel(char *);
-unsigned int esccon(char **sptr);
-void inline_start(char *name);
-void inline_end(void);
-void inline_addarg(struct interpass *);
-void inline_ref(char *);
-void inline_prtout(void);
-void ftnarg(NODE *);
-struct rstack *bstruct(char *, int);
-void moedef(char *);
-void beginit(struct symtab *);
-void simpleinit(struct symtab *, NODE *);
-struct symtab *lookup(char *name, int s);
-struct symtab *getsymtab(char *name, int flags);
-char *addstring(char *);
-char *addname(char *);
-char *newstring(char *, int len);
-void symclear(int level);
-void schedremove(struct symtab *p);
-struct symtab *hide(struct symtab *p);
-int talign(unsigned int, struct suedef *);
-void bfcode(struct symtab **, int);
-int chkftn(union arglist *, union arglist *);
-void branch(int);
-void cbranch(NODE *p, NODE *q);
-void extdec(struct symtab *);
-void commdec(struct symtab *);
-void lcommdec(struct symtab *);
-int falloc(struct symtab *p, int w, int new, NODE *pty);
-TWORD ctype(TWORD);
-void ninval(CONSZ off, int fsz, NODE *);
-void infld(CONSZ off, int fsz, CONSZ);
-void zbits(CONSZ off, int fsz);
-void indata(CONSZ, int);
-void instring(char *);
-void defnam(struct symtab *);
-void plabel(int lab);
-void bjobcode(void);
-void ejobcode(int);
-void calldec(NODE *, NODE *);
-int cisreg(TWORD);
-char *tmpsprintf(char *fmt, ...);
-char *tmpvsprintf(char *fmt, va_list ap);
-void asginit(NODE *);
-void desinit(NODE *);
-void endinit(void);
-void ilbrace(void);
-void irbrace(void);
-void scalinit(NODE *p);
-int ftoint(NODE *, CONSZ **);
-void p1print(char *fmt, ...);
-char *copst(int);
-int cdope(int);
-void myp2tree(NODE *);
-void lcommprint(void);
-void lcommdel(struct symtab *);
-
-#ifdef GCC_COMPAT
-void gcc_init(void);
-int gcc_keyword(char *, NODE **);
-void gcc_rename(struct symtab *sp, char *newname);
-char *gcc_findname(struct symtab *sp);
-#endif
-
-#ifdef STABS
-void stabs_init(void);
-void stabs_file(char *);
-void stabs_line(int);
-void stabs_rbrac(int);
-void stabs_lbrac(int);
-void stabs_func(struct symtab *);
-void stabs_newsym(struct symtab *);
-void stabs_chgsym(struct symtab *);
-void stabs_struct(struct symtab *p, struct suedef *sue);
-#endif
-
-#ifndef CHARCAST
-/* to make character constants into character connstants */
-/* this is a macro to defend against cross-compilers, etc. */
-#define CHARCAST(x) (char)(x)
-#endif
-
-/*
- * C compiler first pass extra defines.
- */
-#define QUALIFIER (MAXOP+1)
-#define CLASS (MAXOP+2)
-#define RB (MAXOP+3)
-#define DOT (MAXOP+4)
-#define ELLIPSIS (MAXOP+5)
-#define TYPE (MAXOP+6)
-#define LB (MAXOP+7)
-#define COMOP (MAXOP+8)
-#define QUEST (MAXOP+9)
-#define COLON (MAXOP+10)
-#define ANDAND (MAXOP+11)
-#define OROR (MAXOP+12)
-#define NOT (MAXOP+13)
-#define CAST (MAXOP+14)
-/* #define STRING (MAXOP+15) */
-
-/* The following must be in the same order as their NOASG counterparts */
-#define PLUSEQ (MAXOP+16)
-#define MINUSEQ (MAXOP+17)
-#define DIVEQ (MAXOP+18)
-#define MODEQ (MAXOP+19)
-#define MULEQ (MAXOP+20)
-#define ANDEQ (MAXOP+21)
-#define OREQ (MAXOP+22)
-#define EREQ (MAXOP+23)
-#define LSEQ (MAXOP+24)
-#define RSEQ (MAXOP+25)
-
-#define UNASG (-(PLUSEQ-PLUS))+
-
-#define INCR (MAXOP+26)
-#define DECR (MAXOP+27)
-/*
- * The following types are only used in pass1.
- */
-#define SIGNED (MAXTYPES+1)
-#define BOOL (MAXTYPES+2)
-
-
-#define coptype(o) (cdope(o)&TYFLG)
-#define clogop(o) (cdope(o)&LOGFLG)
-#define casgop(o) (cdope(o)&ASGFLG)
-
--- usr.bin/pcc/cc/ccom/main.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* $Id: main.c,v 1.72 2007/09/25 06:43:06 ragge Exp $ */
-
-/*
- * Copyright (c) 2002 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 <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "pass1.h"
-#include "pass2.h"
-
-int sflag, nflag, oflag, kflag;
-int lflag, odebug, rdebug, radebug, vdebug, s2debug, udebug, x2debug;
-#if !defined(MULTIPASS) || defined(PASST)
-int iTflag, oTflag;
-#endif
-int xdebug, mdebug, sdebug, gflag, c2debug, pdebug;
-int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
- Wimplicit_function_declaration;
-int xssaflag, xtailcallflag, xtemps, xdeljumps;
-
-int e2debug, t2debug, f2debug, b2debug;
-
-struct suedef btdims[24];
-char *prgname;
-
-static void prtstats(void);
-
-static struct {
- char *n; int *f;
-} flagstr[] = {
- { "strict-prototypes", &Wstrict_prototypes, },
- { "missing-prototypes", &Wmissing_prototypes, },
- { "implicit-int", &Wimplicit_int, },
- { "implicit-function-declaration", &Wimplicit_function_declaration, },
- { NULL, NULL, },
-};
-
-static void
-usage(void)
-{
- (void)fprintf(stderr, "usage: %s [option] [infile] [outfile]...\n",
- prgname);
- exit(1);
-}
-
-static void
-segvcatch(int a)
-{
- fprintf(stderr, "%sinternal compiler error: %s, line %d\n",
- nerrors ? "" : "major ", ftitle, lineno);
- fflush(stderr);
- exit(1);
-}
-
-/*
- * "emulate" the gcc warning flags.
- */
-static void
-Wflags(char *str)
-{
- int i, found = 0, all;
-
- if (strcmp(str, "implicit") == 0) {
- Wimplicit_int = Wimplicit_function_declaration = 1;
- return;
- }
- all = strcmp(str, "W") == 0;
- for (i = 0; flagstr[i].n; i++)
- if (all || strcmp(flagstr[i].n, str) == 0) {
- *flagstr[i].f = 1;
- found++;
- }
- if (found == 0)
- usage();
-}
-
-
-/* control multiple files */
-int
-main(int argc, char *argv[])
-{
-
- int ch;
-
- prgname = argv[0];
-
- while ((ch = getopt(argc, argv, "VlwX:Z:W:sOT:gx:kv")) != -1)
- switch (ch) {
-#if !defined(MULTIPASS) || defined(PASS1)
- case 'X':
- while (*optarg)
- switch (*optarg++) {
- case 'd': ++ddebug; break; /* declarations */
- case 'i': ++idebug; break; /* initializations */
- case 'b': ++bdebug; break;
- case 't': ++tdebug; break;
- case 'e': ++edebug; break; /* pass1 exit */
- case 'x': ++xdebug; break; /* MD code */
- case 's': ++sdebug; break;
- case 'n': ++nflag; break;
- case 'o': ++oflag; break;
- case 'p': ++pdebug; break; /* prototype */
- default:
- fprintf(stderr, "unknown X flag '%c'\n",
- optarg[-1]);
- exit(1);
- }
-#endif
- break;
-#if !defined(MULTIPASS) || defined(PASST)
- case 'T':
- while (*optarg)
- switch (*optarg++) {
- case 'i': ++iTflag; break;
- case 'o': ++oTflag; break;
- case 'n': ++nflag; break;
- default:
- fprintf(stderr, "unknown T flag '%c'\n",
- optarg[-1]);
- exit(1);
- }
-#endif
- break;
-#if !defined(MULTIPASS) || defined(PASS2)
- case 'Z':
- while (*optarg)
- switch (*optarg++) {
- case 'f': /* instruction matching */
- ++f2debug;
- break;
- case 'e': /* print tree upon pass2 enter */
- ++e2debug;
- break;
- case 'o': ++odebug; break;
- case 'r': /* register alloc/graph coloring */
- ++rdebug;
- break;
- case 'a': ++radebug; break;
- case 'b': /* basic block and SSA building */
- ++b2debug;
- break;
- case 'c': /* code printout */
- ++c2debug;
- break;
- case 'm': ++mdebug; break;
- case 'v': ++vdebug; break;
- case 't': ++t2debug; break;
- case 's': /* shape matching */
- ++s2debug;
- break;
- case 'u': /* Sethi-Ullman debugging */
- ++udebug;
- break;
- case 'x': ++x2debug; break;
- case 'n': ++nflag; break;
- default:
- fprintf(stderr, "unknown Z flag '%c'\n",
- optarg[-1]);
- exit(1);
- }
-#endif
- break;
-
- case 'k': /* PIC code */
- ++kflag;
- break;
-
- case 'l': /* linenos */
- ++lflag;
- break;
-
- case 'g': /* Debugging */
- gflag = 1;
- break;
-
- case 's': /* Statistics */
- ++sflag;
- break;
-
- case 'W': /* Enable different warnings */
- Wflags(optarg);
- break;
-
- case 'x': /* Different optimizations */
- if (strcmp(optarg, "ssa") == 0)
- xssaflag++;
- else if (strcmp(optarg, "tailcall") == 0)
- xtailcallflag++;
- else if (strcmp(optarg, "temps") == 0)
- xtemps++;
- else if (strcmp(optarg, "deljumps") == 0)
- xdeljumps++;
- else
- usage();
- break;
- case 'v':
- printf("ccom: %s\n", VERSSTR);
- break;
-
- case '?':
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 0) {
- if (freopen(argv[0], "r", stdin) == NULL) {
- fprintf(stderr, "open input file '%s':",
- argv[0]);
- perror(NULL);
- exit(1);
- }
- if (argc != 1)
- if (freopen(argv[1], "w", stdout) == NULL) {
- fprintf(stderr, "open output file '%s':",
- argv[1]);
- perror(NULL);
- exit(1);
- }
- }
-
- mkdope();
- signal(SIGSEGV, segvcatch);
- fregs = FREGS; /* number of free registers */
- lineno = 1;
-#ifdef GCC_COMPAT
- gcc_init();
-#endif
-
- /* dimension table initialization */
-
- btdims[VOID].suesize = 0;
- btdims[BOOL].suesize = SZBOOL;
- btdims[CHAR].suesize = SZCHAR;
- btdims[INT].suesize = SZINT;
- btdims[FLOAT].suesize = SZFLOAT;
- btdims[DOUBLE].suesize = SZDOUBLE;
- btdims[LDOUBLE].suesize = SZLDOUBLE;
- btdims[LONG].suesize = SZLONG;
- btdims[LONGLONG].suesize = SZLONGLONG;
- btdims[SHORT].suesize = SZSHORT;
- btdims[UCHAR].suesize = SZCHAR;
- btdims[USHORT].suesize = SZSHORT;
- btdims[UNSIGNED].suesize = SZINT;
- btdims[ULONG].suesize = SZLONG;
- btdims[ULONGLONG].suesize = SZLONGLONG;
- /* starts past any of the above */
- reached = 1;
-
- bjobcode();
-
-#ifdef STABS
- if (gflag) {
- stabs_file(argc ? argv[0] : "");
- stabs_init();
- }
-#endif
-
- (void) yyparse();
- yyaccpt();
-
- ejobcode( nerrors ? 1 : 0 );
- if (!nerrors)
- lcommprint();
-
- if (sflag)
- prtstats();
- return(nerrors?1:0);
-
-}
-
-void
-prtstats(void)
-{
- extern int nametabs, namestrlen, tmpallocsize, permallocsize;
- extern int lostmem, arglistcnt, dimfuncnt, inlnodecnt, inlstatcnt;
- extern int symtabcnt, suedefcnt;
-
- fprintf(stderr, "Name table entries: %d pcs\n", nametabs);
- fprintf(stderr, "Name string size: %d B\n", namestrlen);
- fprintf(stderr, "Permanent allocated memory: %d B\n", permallocsize);
- fprintf(stderr, "Temporary allocated memory: %d B\n", tmpallocsize);
- fprintf(stderr, "Lost memory: %d B\n", lostmem);
- fprintf(stderr, "Argument list unions: %d pcs\n", arglistcnt);
- fprintf(stderr, "Dimension/function unions: %d pcs\n", dimfuncnt);
- fprintf(stderr, "Struct/union/enum blocks: %d pcs\n", suedefcnt);
- fprintf(stderr, "Inline node count: %d pcs\n", inlnodecnt);
- fprintf(stderr, "Inline control blocks: %d pcs\n", inlstatcnt);
- fprintf(stderr, "Permanent symtab entries: %d pcs\n", symtabcnt);
-}
--- usr.bin/pcc/cc/ccom/cgram.y
+++ /dev/null
@@ -1,1400 +0,0 @@
-/* $Id: cgram.y,v 1.170 2007/09/16 19:25:33 ragge Exp $ */
-
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-/*
- * Comments for this grammar file. Ragge 021123
- *
- * ANSI support required rewrite of the function header and declaration
- * rules almost totally.
- *
- * The lex/yacc shared keywords are now split from the keywords used
- * in the rest of the compiler, to simplify use of other frontends.
- */
-
-/*
- * At last count, there were 3 shift/reduce and no reduce/reduce conflicts
- * Two was funct_idn and the third was "dangling else".
- */
-
-/*
- * Token used in C lex/yacc communications.
- */
-%token C_WSTRING /* a wide string constant */
-%token C_STRING /* a string constant */
-%token C_ICON /* an integer constant */
-%token C_FCON /* a floating point constant */
-%token C_NAME /* an identifier */
-%token C_TYPENAME /* a typedef'd name */
-%token C_ANDAND /* && */
-%token C_OROR /* || */
-%token C_GOTO /* unconditional goto */
-%token C_RETURN /* return from function */
-%token C_TYPE /* a type */
-%token C_CLASS /* a storage class */
-%token C_ASOP /* assignment ops */
-%token C_RELOP /* <=, <, >=, > */
-%token C_EQUOP /* ==, != */
-%token C_DIVOP /* /, % */
-%token C_SHIFTOP /* <<, >> */
-%token C_INCOP /* ++, -- */
-%token C_UNOP /* !, ~ */
-%token C_STROP /* ., -> */
-%token C_STRUCT
-%token C_IF
-%token C_ELSE
-%token C_SWITCH
-%token C_BREAK
-%token C_CONTINUE
-%token C_WHILE
-%token C_DO
-%token C_FOR
-%token C_DEFAULT
-%token C_CASE
-%token C_SIZEOF
-%token C_ENUM
-%token C_ELLIPSIS
-%token C_QUALIFIER
-%token C_FUNSPEC
-%token C_ASM
-
-/*
- * Precedence
- */
-%left ','
-%right '=' C_ASOP
-%right '?' ':'
-%left C_OROR
-%left C_ANDAND
-%left '|'
-%left '^'
-%left '&'
-%left C_EQUOP
-%left C_RELOP
-%left C_SHIFTOP
-%left '+' '-'
-%left '*' C_DIVOP
-%right C_UNOP
-%right C_INCOP C_SIZEOF
-%left '[' '(' C_STROP
-%{
-# include "pass1.h"
-# include <stdarg.h>
-# include <string.h>
-# include <stdlib.h>
-
-static int fun_inline; /* Reading an inline function */
-int oldstyle; /* Current function being defined */
-int noretype;
-static struct symtab *xnf;
-#ifdef GCC_COMPAT
-char *renname; /* for renaming of variables */
-#endif
-
-
-static NODE *bdty(int op, ...);
-static void fend(void);
-static void fundef(NODE *tp, NODE *p);
-static void olddecl(NODE *p);
-static struct symtab *init_declarator(NODE *tn, NODE *p, int assign);
-static void resetbc(int mask);
-static void swend(void);
-static void addcase(NODE *p);
-static void adddef(void);
-static void savebc(void);
-static void swstart(int);
-static NODE * structref(NODE *p, int f, char *name);
-static char *mkpstr(char *str);
-static struct symtab *clbrace(NODE *);
-
-/*
- * State for saving current switch state (when nested switches).
- */
-struct savbc {
- struct savbc *next;
- int brklab;
- int contlab;
- int flostat;
- int swx;
-} *savbc, *savctx;
-
-%}
-
-%union {
- int intval;
- NODE *nodep;
- struct symtab *symp;
- struct rstack *rp;
- char *strp;
-}
-
- /* define types */
-%start ext_def_list
-
-%type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart
- type_qualifier_list
-%type <nodep> e .e term enum_dcl struct_dcl cast_type funct_idn declarator
- direct_declarator elist type_specifier merge_attribs
- parameter_declaration abstract_declarator initializer
- parameter_type_list parameter_list addrlbl
- declaration_specifiers pointer direct_abstract_declarator
- specifier_qualifier_list merge_specifiers nocon_e
- identifier_list arg_param_list arg_declaration arg_dcl_list
- designator_list designator
-%type <strp> string wstring C_STRING C_WSTRING
-%type <rp> enum_head str_head
-%type <symp> xnfdeclarator clbrace
-
-%type <intval> C_CLASS C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
- C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
-%type <nodep> C_TYPE C_QUALIFIER C_ICON C_FCON
-%type <strp> C_NAME C_TYPENAME
-
-%%
-
-ext_def_list: ext_def_list external_def
- | { ftnend(); }
- ;
-
-external_def: function_definition { blevel = 0; }
- | declaration { blevel = 0; symclear(0); }
- | asmstatement ';'
- | ';'
- | error { blevel = 0; }
- ;
-
-function_definition:
- /* Ansi (or K&R header without parameter types) */
- declaration_specifiers declarator {
- fundef($1, $2);
- } compoundstmt { fend(); }
- /* Same as above but without declaring function type */
- | declarator {
- noretype = 1;
- fundef(mkty(INT, 0, MKSUE(INT)), $1);
- } compoundstmt { fend(); noretype = 0; }
- /* K&R function without type declaration */
- | declarator {
- noretype = 1;
- if (oldstyle == 0)
- uerror("bad declaration in ansi function");
- fundef(mkty(INT, 0, MKSUE(INT)), $1);
- } arg_dcl_list compoundstmt { fend(); noretype = 0; }
- /* K&R function with type declaration */
- | declaration_specifiers declarator {
- if (oldstyle == 0)
- uerror("bad declaration in ansi function");
- fundef($1, $2);
- } arg_dcl_list compoundstmt { fend(); }
- ;
-
-/*
- * Returns a node pointer or NULL, if no types at all given.
- * Type trees are checked for correctness and merged into one
- * type node in typenode().
- */
-declaration_specifiers:
- merge_attribs { $$ = typenode($1); }
- ;
-
-merge_attribs: C_CLASS { $$ = block(CLASS, NIL, NIL, $1, 0, 0); }
- | C_CLASS merge_attribs { $$ = block(CLASS, $2, NIL, $1,0,0);}
- | type_specifier { $$ = $1; }
- | type_specifier merge_attribs { $1->n_left = $2; $$ = $1; }
- | C_QUALIFIER { $$ = $1; }
- | C_QUALIFIER merge_attribs { $1->n_left = $2; $$ = $1; }
- | function_specifiers { $$ = NIL; }
- | function_specifiers merge_attribs { $$ = $2; }
- ;
-
-function_specifiers:
- C_FUNSPEC {
- if (fun_inline)
- uerror("too many inline");
- fun_inline = 1;
- }
- ;
-
-type_specifier: C_TYPE { $$ = $1; }
- | C_TYPENAME {
- struct symtab *sp = lookup($1, 0);
- $$ = mkty(sp->stype, sp->sdf, sp->ssue);
- $$->n_sp = sp;
- }
- | struct_dcl { $$ = $1; }
- | enum_dcl { $$ = $1; }
- ;
-
-/*
- * Adds a pointer list to front of the declarators.
- * Note the UMUL right node pointer usage.
- */
-declarator: pointer direct_declarator {
- $$ = $1; $1->n_right->n_left = $2;
- }
- | direct_declarator { $$ = $1; }
- ;
-
-/*
- * Return an UMUL node type linked list of indirections.
- */
-pointer: '*' { $$ = bdty(UMUL, NIL); $$->n_right = $$; }
- | '*' type_qualifier_list {
- $$ = bdty(UMUL, NIL);
- $$->n_qual = $2;
- $$->n_right = $$;
- }
- | '*' pointer {
- $$ = bdty(UMUL, $2);
- $$->n_right = $2->n_right;
- }
- | '*' type_qualifier_list pointer {
- $$ = bdty(UMUL, $3);
- $$->n_qual = $2;
- $$->n_right = $3->n_right;
- }
- ;
-
-type_qualifier_list:
- C_QUALIFIER { $$ = $1->n_type; nfree($1); }
- | type_qualifier_list C_QUALIFIER {
- $$ = $1 | $2->n_type; nfree($2);
- }
- ;
-
-/*
- * Sets up a function declarator. The call node will have its parameters
- * connected to its right node pointer.
- */
-direct_declarator: C_NAME { $$ = bdty(NAME, $1); }
- | '(' declarator ')' { $$ = $2; }
- | direct_declarator '[' nocon_e ']' {
- $$ = block(LB, $1, $3, INT, 0, MKSUE(INT));
- }
- | direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
- | direct_declarator '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, $1, $4);
- }
- | direct_declarator '(' notype identifier_list ')' {
- $$ = bdty(CALL, $1, $4);
- if (blevel != 0)
- uerror("function declaration in bad context");
- oldstyle = 1;
- }
- | direct_declarator '(' ')' { $$ = bdty(UCALL, $1); }
- ;
-
-notype: { /* extern int notype, doproto; notype = 0; doproto=1; printf("notype\n"); */ }
- ;
-
-identifier_list: C_NAME { $$ = bdty(NAME, $1); $$->n_type = FARG; }
- | identifier_list ',' C_NAME {
- $$ = bdty(NAME, $3);
- $$->n_type = FARG;
- $$ = block(CM, $1, $$, 0, 0, 0);
- }
- ;
-
-/*
- * Returns as parameter_list, but can add an additional ELLIPSIS node.
- * Calls revert() to get the parameter list in the forward order.
- */
-parameter_type_list:
- parameter_list { $$ = $1; }
- | parameter_list ',' C_ELLIPSIS {
- $$ = block(CM, $1, block(ELLIPSIS, NIL, NIL, 0, 0, 0),
- 0, 0, 0);
- }
- ;
-
-/*
- * Returns a linked lists of nodes of op CM with parameters on
- * its right and additional CM nodes of its left pointer.
- * No CM nodes if only one parameter.
- */
-parameter_list: parameter_declaration { $$ = $1; }
- | parameter_list ',' parameter_declaration {
- $$ = block(CM, $1, $3, 0, 0, 0);
- }
- ;
-
-/*
- * Returns a node pointer to the declaration.
- */
-parameter_declaration:
- declaration_specifiers declarator {
- $$ = tymerge($1, $2);
- nfree($1);
- }
- | declaration_specifiers abstract_declarator {
- $$ = tymerge($1, $2);
- nfree($1);
- }
- | declaration_specifiers {
- $$ = tymerge($1, bdty(NAME, NULL));
- nfree($1);
- }
- ;
-
-abstract_declarator:
- pointer { $$ = $1; $1->n_right->n_left = bdty(NAME, NULL); }
- | direct_abstract_declarator { $$ = $1; }
- | pointer direct_abstract_declarator {
- $$ = $1; $1->n_right->n_left = $2;
- }
- ;
-
-direct_abstract_declarator:
- '(' abstract_declarator ')' { $$ = $2; }
- | '[' ']' { $$ = bdty(LB, bdty(NAME, NULL), 0); }
- | '[' con_e ']' { $$ = bdty(LB, bdty(NAME, NULL), $2); }
- | direct_abstract_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
- | direct_abstract_declarator '[' con_e ']' {
- $$ = bdty(LB, $1, $3);
- }
- | '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
- | '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, bdty(NAME, NULL), $3);
- }
- | direct_abstract_declarator '(' ')' {
- $$ = bdty(UCALL, $1);
- }
- | direct_abstract_declarator '(' notype parameter_type_list ')' {
- $$ = bdty(CALL, $1, $4);
- }
- ;
-
-/*
- * K&R arg declaration, between ) and {
- */
-arg_dcl_list: arg_declaration
- | arg_dcl_list arg_declaration
- ;
-
-
-arg_declaration: declaration_specifiers arg_param_list ';' {
- nfree($1);
- }
- ;
-
-arg_param_list: declarator { olddecl(tymerge($<nodep>0, $1)); }
- | arg_param_list ',' declarator {
- olddecl(tymerge($<nodep>0, $3));
- }
- ;
-
-/*
- * Declarations in beginning of blocks.
- */
-declaration_list: declaration
- | declaration_list declaration
- ;
-
-/*
- * Here starts the old YACC code.
- */
-
-stmt_list: stmt_list statement
- | { bccode(); }
- ;
-
-/*
- * Variables are declared in init_declarator.
- */
-declaration: declaration_specifiers ';' { nfree($1); goto inl; }
- | declaration_specifiers init_declarator_list ';' {
- nfree($1);
- inl:
- fun_inline = 0;
- }
- ;
-
-/*
- * Normal declaration of variables. curtype contains the current type node.
- * Returns nothing, variables are declared in init_declarator.
- */
-init_declarator_list:
- init_declarator
- | init_declarator_list ',' { $<nodep>$ = $<nodep>0; } init_declarator
- ;
-
-enum_dcl: enum_head '{' moe_list optcomma '}' { $$ = dclstruct($1); }
- | C_ENUM C_NAME { $$ = rstruct($2,0); }
- | C_ENUM C_TYPENAME { $$ = rstruct($2,0); }
- ;
-
-enum_head: C_ENUM { $$ = bstruct(NULL,0); }
- | C_ENUM C_NAME { $$ = bstruct($2,0); }
- | C_ENUM C_TYPENAME { $$ = bstruct($2,0); }
- ;
-
-moe_list: moe
- | moe_list ',' moe
- ;
-
-moe: C_NAME { moedef( $1 ); }
- | C_NAME '=' con_e { strucoff = $3; moedef( $1 ); }
- ;
-
-struct_dcl: str_head '{' struct_dcl_list '}' { $$ = dclstruct($1); }
- | C_STRUCT C_NAME { $$ = rstruct($2,$1); }
- | C_STRUCT C_TYPENAME { $$ = rstruct($2,$1); }
- | str_head '{' '}' {
-#ifndef GCC_COMPAT
- werror("gcc extension");
-#endif
- $$ = dclstruct($1);
- }
- ;
-
-str_head: C_STRUCT { $$ = bstruct(NULL, $1); }
- | C_STRUCT C_NAME { $$ = bstruct($2,$1); }
- | C_STRUCT C_TYPENAME { $$ = bstruct($2,$1); }
- ;
-
-struct_dcl_list: struct_declaration
- | struct_dcl_list struct_declaration
- ;
-
-struct_declaration:
- specifier_qualifier_list struct_declarator_list ';' {
- nfree($1);
- }
- ;
-
-specifier_qualifier_list:
- merge_specifiers { $$ = typenode($1); }
- ;
-
-merge_specifiers: type_specifier merge_specifiers { $1->n_left = $2;$$ = $1; }
- | type_specifier { $$ = $1; }
- | C_QUALIFIER merge_specifiers { $1->n_left = $2; $$ = $1; }
- | C_QUALIFIER { $$ = $1; }
- ;
-
-struct_declarator_list:
- struct_declarator { }
- | struct_declarator_list ',' { $<nodep>$=$<nodep>0; }
- struct_declarator { }
- ;
-
-struct_declarator: declarator {
- tymerge($<nodep>0, $1);
- $1->n_sp = getsymtab((char *)$1->n_sp, SMOSNAME); /* XXX */
- defid($1, $<nodep>0->n_lval);
- nfree($1);
- }
- | ':' con_e {
- if (!(instruct&INSTRUCT))
- uerror( "field outside of structure" );
- falloc(NULL, $2, -1, $<nodep>0);
- }
- | declarator ':' con_e {
- if (!(instruct&INSTRUCT))
- uerror( "field outside of structure" );
- if( $3<0 || $3 >= FIELD ){
- uerror( "illegal field size" );
- $3 = 1;
- }
- if ($1->n_op == NAME) {
- tymerge($<nodep>0, $1);
- $1->n_sp = getsymtab((char *)$1->n_sp,SMOSNAME);
- defid($1, FIELD|$3);
- nfree($1);
- } else
- uerror("illegal declarator");
- }
- ;
-
- /* always preceeded by attributes */
-xnfdeclarator: declarator { $$ = xnf = init_declarator($<nodep>0, $1, 1); }
- ;
-
-/*
- * Handles declarations and assignments.
- * Returns nothing.
- */
-init_declarator: declarator { init_declarator($<nodep>0, $1, 0); }
- | declarator C_ASM '(' string ')' {
-#ifdef GCC_COMPAT
- renname = $4;
- init_declarator($<nodep>0, $1, 0);
-#else
- werror("gcc extension");
- init_declarator($<nodep>0, $1, 0);
-#endif
- }
- | xnfdeclarator '=' e { simpleinit($1, $3); xnf = NULL; }
- | xnfdeclarator '=' begbr init_list optcomma '}' {
- endinit();
- xnf = NULL;
- }
- | xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
- ;
-
-begbr: '{' { beginit($<symp>-1); }
- ;
-
-initializer: e %prec ',' { $$ = $1; }
- | addrlbl { $$ = $1; }
- | ibrace init_list optcomma '}' { $$ = NULL; }
- ;
-
-init_list: designation initializer { asginit($2); }
- | init_list ',' designation initializer { asginit($4); }
- ;
-
-designation: designator_list '=' { desinit($1); }
- | { /* empty */ }
- ;
-
-designator_list: designator { $$ = $1; }
- | designator_list designator { $$ = $2; $$->n_left = $1; }
- ;
-
-designator: '[' con_e ']' { $$ = bdty(LB, NULL, $2); }
- | C_STROP C_NAME { $$ = bdty(NAME, $2); }
- ;
-
-optcomma : /* VOID */
- | ','
- ;
-
-ibrace: '{' { ilbrace(); }
- ;
-
-/* STATEMENTS */
-
-compoundstmt: begin declaration_list stmt_list '}' {
-#ifdef STABS
- if (gflag && blevel > 2)
- stabs_rbrac(blevel);
-#endif
- --blevel;
- if( blevel == 1 )
- blevel = 0;
- symclear(blevel); /* Clean ut the symbol table */
- if (autooff > maxautooff)
- maxautooff = autooff;
- autooff = savctx->contlab;
- savctx = savctx->next;
- }
- | begin stmt_list '}' {
-#ifdef STABS
- if (gflag && blevel > 2)
- stabs_rbrac(blevel);
-#endif
- --blevel;
- if( blevel == 1 )
- blevel = 0;
- symclear(blevel); /* Clean ut the symbol table */
- if (autooff > maxautooff)
- maxautooff = autooff;
- autooff = savctx->contlab;
- savctx = savctx->next;
- }
- ;
-
-begin: '{' {
- struct savbc *bc = tmpalloc(sizeof(struct savbc));
- if (blevel == 1) {
-#ifdef STABS
- if (gflag)
- stabs_line(lineno);
-#endif
- dclargs();
- }
-#ifdef STABS
- if (gflag && blevel > 1)
- stabs_lbrac(blevel+1);
-#endif
- ++blevel;
- oldstyle = 0;
- bc->contlab = autooff;
- bc->next = savctx;
- savctx = bc;
- }
- ;
-
-statement: e ';' { ecomp( $1 ); }
- | compoundstmt
- | ifprefix statement { plabel($1); reached = 1; }
- | ifelprefix statement {
- if ($1 != NOLAB) {
- plabel( $1);
- reached = 1;
- }
- }
- | whprefix statement {
- branch(contlab);
- plabel( brklab );
- if( (flostat&FBRK) || !(flostat&FLOOP))
- reached = 1;
- else
- reached = 0;
- resetbc(0);
- }
- | doprefix statement C_WHILE '(' e ')' ';' {
- plabel(contlab);
- if (flostat & FCONT)
- reached = 1;
- if (reached)
- cbranch($5, bcon($1));
- else
- tfree($5);
- plabel( brklab);
- reached = 1;
- resetbc(0);
- }
- | forprefix .e ')' statement
- { plabel( contlab );
- if( flostat&FCONT ) reached = 1;
- if( $2 ) ecomp( $2 );
- branch($1);
- plabel( brklab );
- if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
- else reached = 0;
- resetbc(0);
- }
- | switchpart statement
- { if( reached ) branch( brklab );
- plabel( $1 );
- swend();
- plabel( brklab);
- if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
- resetbc(FCONT);
- }
- | C_BREAK ';' {
- if (brklab == NOLAB)
- uerror("illegal break");
- else if (reached)
- branch(brklab);
- flostat |= FBRK;
- reached = 0;
- }
- | C_CONTINUE ';' {
- if (contlab == NOLAB)
- uerror("illegal continue");
- else
- branch(contlab);
- flostat |= FCONT;
- goto rch;
- }
- | C_RETURN ';' {
- branch(retlab);
- if (cftnsp->stype != VOID && noretype &&
- cftnsp->stype != VOID+FTN)
- uerror("return value required");
- rch:
- if (!reached)
- werror( "statement is not reached");
- reached = 0;
- }
- | C_RETURN e ';' {
- register NODE *temp;
-
- spname = cftnsp;
- temp = buildtree( NAME, NIL, NIL );
- temp->n_type = DECREF(temp->n_type);
- temp = buildtree(RETURN, temp, $2);
-
- if (temp->n_type == VOID)
- ecomp(temp->n_right);
- else
- ecomp(buildtree(FORCE, temp->n_right, NIL));
- nfree(temp->n_left);
- nfree(temp);
- branch(retlab);
- reached = 0;
- }
- | C_GOTO C_NAME ';' { gotolabel($2); goto rch; }
- | C_GOTO '*' e ';' {
- ecomp(block(GOTO, $3, NIL, INT, 0, 0));
- }
- | asmstatement ';'
- | ';'
- | error ';'
- | error '}'
- | label statement
- ;
-
-asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); }
- ;
-
-label: C_NAME ':' { deflabel($1); reached = 1; }
- | C_CASE e ':' { addcase($2); reached = 1; }
- | C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
- ;
-
-doprefix: C_DO {
- savebc();
- if (!reached)
- werror("loop not entered at top");
- brklab = getlab();
- contlab = getlab();
- plabel( $$ = getlab());
- reached = 1;
- }
- ;
-ifprefix: C_IF '(' e ')' {
- cbranch(buildtree(NOT, $3, NIL), bcon($$ = getlab()));
- reached = 1;
- }
- ;
-ifelprefix: ifprefix statement C_ELSE {
- if (reached)
- branch($$ = getlab());
- else
- $$ = NOLAB;
- plabel( $1);
- reached = 1;
- }
- ;
-
-whprefix: C_WHILE '(' e ')' {
- savebc();
- if (!reached)
- werror("loop not entered at top");
- if ($3->n_op == ICON && $3->n_lval != 0)
- flostat = FLOOP;
- plabel( contlab = getlab());
- reached = 1;
- brklab = getlab();
- if (flostat == FLOOP)
- tfree($3);
- else
- cbranch(buildtree(NOT, $3, NIL), bcon(brklab));
- }
- ;
-forprefix: C_FOR '(' .e ';' .e ';' {
- if ($3)
- ecomp($3);
- else if (!reached)
- werror("loop not entered at top");
- savebc();
- contlab = getlab();
- brklab = getlab();
- plabel( $$ = getlab());
- reached = 1;
- if ($5)
- cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
- else
- flostat |= FLOOP;
- }
- ;
-switchpart: C_SWITCH '(' e ')' {
- NODE *p;
- int num;
-
- savebc();
- brklab = getlab();
- if ($3->n_type != INT) {
- /* must cast to integer */
- p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
- p = buildtree(CAST, p, $3);
- $3 = p->n_right;
- nfree(p->n_left);
- nfree(p);
- }
-// ecomp( buildtree( FORCE, $3, NIL ) );
- p = tempnode(0, INT, 0, MKSUE(INT));
- num = p->n_lval;
- ecomp(buildtree(ASSIGN, p, $3));
- branch( $$ = getlab());
- swstart(num);
- reached = 0;
- }
- ;
-/* EXPRESSIONS */
-con_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
- $$ = icons( $2 );
- instruct=$<intval>1;
- }
- ;
-
-nocon_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
- instruct=$<intval>1;
- $$ = $2;
- }
- ;
-
-.e: e
- | { $$=0; }
- ;
-
-elist: e %prec ','
- | elist ',' e { $$ = buildtree(CM, $1, $3); }
- ;
-
-/*
- * Precedence order of operators.
- */
-e: e ',' e { $$ = buildtree(COMOP, $1, $3); }
- | e '=' e { $$ = buildtree(ASSIGN, $1, $3); }
- | e C_ASOP e { $$ = buildtree($2, $1, $3); }
- | e '?' e ':' e {
- $$=buildtree(QUEST, $1, buildtree(COLON, $3, $5));
- }
- | e C_OROR e { $$ = buildtree($2, $1, $3); }
- | e C_ANDAND e { $$ = buildtree($2, $1, $3); }
- | e '|' e { $$ = buildtree(OR, $1, $3); }
- | e '^' e { $$ = buildtree(ER, $1, $3); }
- | e '&' e { $$ = buildtree(AND, $1, $3); }
- | e C_EQUOP e { $$ = buildtree($2, $1, $3); }
- | e C_RELOP e { $$ = buildtree($2, $1, $3); }
- | e C_SHIFTOP e { $$ = buildtree($2, $1, $3); }
- | e '+' e { $$ = buildtree(PLUS, $1, $3); }
- | e '-' e { $$ = buildtree(MINUS, $1, $3); }
- | e C_DIVOP e { $$ = buildtree($2, $1, $3); }
- | e '*' e { $$ = buildtree(MUL, $1, $3); }
- | e '=' addrlbl { $$ = buildtree(ASSIGN, $1, $3); }
- | term
- ;
-
-addrlbl: C_ANDAND C_NAME {
-#ifdef GCC_COMPAT
- struct symtab *s = lookup($2, SLBLNAME);
- if (s->soffset == 0)
- s->soffset = -getlab();
- spname = s;
- $$ = buildtree(ADDROF, buildtree(NAME, NIL, NIL), NIL);
-#else
- uerror("gcc extension");
-#endif
- }
- ;
-
-term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); }
- | '*' term { $$ = buildtree(UMUL, $2, NIL); }
- | '&' term {
- if( ISFTN($2->n_type) || ISARY($2->n_type) ){
-#ifdef notdef
- werror( "& before array or function: ignored" );
-#endif
- $$ = $2;
- } else
- $$ = buildtree(ADDROF, $2, NIL);
- }
- | '-' term { $$ = buildtree(UMINUS, $2, NIL ); }
- | '+' term { $$ = $2; }
- | C_UNOP term { $$ = buildtree( $1, $2, NIL ); }
- | C_INCOP term {
- $$ = buildtree($1 == INCR ? PLUSEQ : MINUSEQ,
- $2, bcon(1));
- }
- | C_SIZEOF term { $$ = doszof($2); }
- | '(' cast_type ')' term %prec C_INCOP {
- $$ = buildtree(CAST, $2, $4);
- nfree($$->n_left);
- nfree($$);
- $$ = $$->n_right;
- }
- | C_SIZEOF '(' cast_type ')' %prec C_SIZEOF {
- $$ = doszof($3);
- }
- | '(' cast_type ')' clbrace init_list '}' {
- endinit();
- spname = $4;
- $$ = buildtree(NAME, NIL, NIL);
- }
- | term '[' e ']' {
- $$ = buildtree( UMUL,
- buildtree( PLUS, $1, $3 ), NIL );
- }
- | funct_idn ')' { $$ = doacall($1, NIL); }
- | funct_idn elist ')' { $$ = doacall($1, $2); }
- | term C_STROP C_NAME { $$ = structref($1, $2, $3); }
- | term C_STROP C_TYPENAME { $$ = structref($1, $2, $3); }
- | C_NAME {
- spname = lookup($1, 0);
- /* recognize identifiers in initializations */
- if (blevel==0 && spname->stype == UNDEF) {
- register NODE *q;
- werror("undeclared initializer name %s",
- spname->sname);
- q = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
- q->n_sp = spname;
- defid(q, EXTERN);
- nfree(q);
- }
- if (spname->sflags & SINLINE)
- inline_ref($1);
- $$ = buildtree(NAME, NIL, NIL);
- spname->suse = -lineno;
- if (spname->sflags & SDYNARRAY)
- $$ = buildtree(UMUL, $$, NIL);
- }
- | C_ICON { $$ = $1; }
- | C_FCON { $$ = $1; }
- | string { $$ = strend($1); /* get string contents */ }
- | wstring { $$ = wstrend($1); }
- | '(' e ')' { $$=$2; }
- ;
-
-clbrace: '{' { $$ = clbrace($<nodep>-1); }
- ;
-
-string: C_STRING {
- int len = strlen($1) + 1;
- $$ = tmpalloc(len);
- strlcpy($$, $1, len);
- }
- | string C_STRING {
- int len = strlen($1) + strlen($2) + 1;
- $$ = tmpalloc(len);
- strlcpy($$, $1, len);
- strlcat($$, $2, len);
- }
- ;
-
-wstring: C_WSTRING {
- int len = strlen($1) + 1;
- $$ = tmpalloc(len);
- strlcpy($$, $1, len);
- }
- | string C_WSTRING {
- int len = strlen($1) + strlen($2) + 1;
- $$ = tmpalloc(len);
- strlcpy($$, $1, len);
- strlcat($$, $2, len);
- }
- ;
-
-cast_type: specifier_qualifier_list {
- $$ = tymerge($1, bdty(NAME, NULL));
- nfree($1);
- }
- | specifier_qualifier_list abstract_declarator {
- $$ = tymerge($1, $2);
- nfree($1);
- }
- ;
-
-funct_idn: C_NAME '(' {
- struct symtab *s = lookup($1, 0);
- if (s->stype == UNDEF) {
- register NODE *q;
- q = block(NAME, NIL, NIL, FTN|INT, 0, MKSUE(INT));
- q->n_sp = s;
- defid(q, EXTERN);
- nfree(q);
- }
- if (s->sflags & SINLINE)
- inline_ref($1);
- spname = s;
- $$ = buildtree(NAME, NIL, NIL);
- s->suse = -lineno;
- }
- | term '('
- ;
-%%
-
-NODE *
-mkty(TWORD t, union dimfun *d, struct suedef *sue)
-{
- return block(TYPE, NIL, NIL, t, d, sue);
-}
-
-static NODE *
-bdty(int op, ...)
-{
- va_list ap;
- register NODE *q;
-
- va_start(ap, op);
- q = block(op, NIL, NIL, INT, 0, MKSUE(INT));
-
- switch (op) {
- case UMUL:
- case UCALL:
- q->n_left = va_arg(ap, NODE *);
- q->n_rval = 0;
- break;
-
- case CALL:
- q->n_left = va_arg(ap, NODE *);
- q->n_right = va_arg(ap, NODE *);
- break;
-
- case LB:
- q->n_left = va_arg(ap, NODE *);
- q->n_right = bcon(va_arg(ap, int));
- break;
-
- case NAME:
- q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */
- break;
-
- default:
- cerror("bad bdty");
- }
- va_end(ap);
-
- return q;
-}
-
-static void
-savebc(void)
-{
- struct savbc *bc = tmpalloc(sizeof(struct savbc));
-
- bc->brklab = brklab;
- bc->contlab = contlab;
- bc->flostat = flostat;
- bc->next = savbc;
- savbc = bc;
- flostat = 0;
-}
-
-static void
-resetbc(int mask)
-{
- flostat = savbc->flostat | (flostat&mask);
- contlab = savbc->contlab;
- brklab = savbc->brklab;
- savbc = savbc->next;
-}
-
-struct swdef {
- struct swdef *next; /* Next in list */
- int deflbl; /* Label for "default" */
- struct swents *ents; /* Linked sorted list of case entries */
- int nents; /* # of entries in list */
- int num; /* Node value will end up in */
-} *swpole;
-
-/*
- * add case to switch
- */
-static void
-addcase(NODE *p)
-{
- struct swents *w, *sw = tmpalloc(sizeof(struct swents));
-
- p = optim(p); /* change enum to ints */
- if (p->n_op != ICON || p->n_sp != NULL) {
- uerror( "non-constant case expression");
- return;
- }
- if (swpole == NULL) {
- uerror("case not in switch");
- return;
- }
-
- sw->sval = p->n_lval;
- plabel( sw->slab = getlab());
- w = swpole->ents;
- if (swpole->ents == NULL) {
- sw->next = NULL;
- swpole->ents = sw;
- } else if (swpole->ents->next == NULL) {
- if (swpole->ents->sval == sw->sval) {
- uerror("duplicate case in switch");
- } else if (swpole->ents->sval < sw->sval) {
- sw->next = NULL;
- swpole->ents->next = sw;
- } else {
- sw->next = swpole->ents;
- swpole->ents = sw;
- }
- } else {
- while (w->next->next != NULL && w->next->sval < sw->sval) {
- w = w->next;
- }
- if (w->next->sval == sw->sval) {
- uerror("duplicate case in switch");
- } else if (w->next->sval > sw->sval) {
- sw->next = w->next;
- w->next = sw;
- } else {
- sw->next = NULL;
- w->next->next = sw;
- }
- }
- swpole->nents++;
- tfree(p);
-}
-
-/*
- * add default case to switch
- */
-static void
-adddef(void)
-{
- if (swpole == NULL)
- uerror("default not inside switch");
- else if (swpole->deflbl != 0)
- uerror("duplicate default in switch");
- else
- plabel( swpole->deflbl = getlab());
-}
-
-static void
-swstart(int num)
-{
- struct swdef *sw = tmpalloc(sizeof(struct swdef));
-
- sw->deflbl = sw->nents = 0;
- sw->ents = NULL;
- sw->next = swpole;
- sw->num = num;
- swpole = sw;
-}
-
-/*
- * end a switch block
- */
-static void
-swend(void)
-{
- struct swents *sw, **swp;
- int i;
-
- sw = tmpalloc(sizeof(struct swents));
- swp = tmpalloc(sizeof(struct swents *) * (swpole->nents+1));
-
- sw->slab = swpole->deflbl;
- swp[0] = sw;
-
- for (i = 1; i <= swpole->nents; i++) {
- swp[i] = swpole->ents;
- swpole->ents = swpole->ents->next;
- }
- genswitch(swpole->num, swp, swpole->nents);
-
- swpole = swpole->next;
-}
-
-/*
- * Declare a variable or prototype.
- */
-static struct symtab *
-init_declarator(NODE *tn, NODE *p, int assign)
-{
- int class = tn->n_lval;
- NODE *typ;
-
- typ = tymerge(tn, p);
- typ->n_sp = lookup((char *)typ->n_sp, 0); /* XXX */
-
- if (fun_inline && ISFTN(typ->n_type))
- typ->n_sp->sflags |= SINLINE;
-
- if (ISFTN(typ->n_type) == 0) {
- setloc1(DATA);
- if (assign) {
- defid(typ, class);
- typ->n_sp->sflags |= SASG;
- lcommdel(typ->n_sp);
- } else {
- nidcl(typ, class);
- }
- } else {
- if (assign)
- uerror("cannot initialise function");
- defid(typ, uclass(class));
- }
- nfree(p);
- return typ->n_sp;
-}
-
-/*
- * Declare a function.
- */
-static void
-fundef(NODE *tp, NODE *p)
-{
- extern int prolab;
- struct symtab *s;
- int class = tp->n_lval, oclass;
- char *c;
-
- setloc1(PROG);
- /* Enter function args before they are clobbered in tymerge() */
- /* Typecheck against prototype will be done in defid(). */
- ftnarg(p);
-
- tymerge(tp, p);
- s = p->n_sp = lookup((char *)p->n_sp, 0); /* XXX */
-
- oclass = s->sclass;
- if (class == STATIC && oclass == EXTERN)
- werror("%s was first declared extern, then static", s->sname);
-
- if ((oclass == SNULL || oclass == USTATIC) &&
- class == STATIC && fun_inline) {
- /* Unreferenced, store it for (eventual) later use */
- /* Ignore it if it not declared static */
- s->sflags |= SINLINE;
- inline_start(s->sname);
- }
- if (class == EXTERN)
- class = SNULL; /* same result */
-
- cftnsp = s;
- defid(p, class);
- prolab = getlab();
- c = cftnsp->sname;
-#ifdef GCC_COMPAT
- c = gcc_findname(cftnsp);
-#endif
- send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
- cftnsp->sclass == EXTDEF, prolab);
- blevel = 1;
-#ifdef STABS
- if (gflag)
- stabs_func(s);
-#endif
- nfree(tp);
- nfree(p);
-
-}
-
-static void
-fend(void)
-{
- if (blevel)
- cerror("function level error");
- ftnend();
- fun_inline = 0;
- cftnsp = NULL;
-}
-
-static NODE *
-structref(NODE *p, int f, char *name)
-{
- NODE *r;
-
- if (f == DOT)
- p = buildtree(ADDROF, p, NIL);
- r = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
- r->n_name = name;
- return buildtree(STREF, p, r);
-}
-
-static void
-olddecl(NODE *p)
-{
- struct symtab *s;
-
- s = lookup((char *)p->n_sp, 0);
- if (s->slevel != 1 || s->stype == UNDEF)
- uerror("parameter '%s' not defined", s->sname);
- else if (s->stype != FARG)
- uerror("parameter '%s' redefined", s->sname);
- s->stype = p->n_type;
- s->sdf = p->n_df;
- s->ssue = p->n_sue;
- nfree(p);
-}
-
-void
-branch(int lbl)
-{
- int r = reached++;
- ecomp(block(GOTO, bcon(lbl), NIL, INT, 0, 0));
- reached = r;
-}
-
-/*
- * Create a printable string based on an encoded string.
- */
-static char *
-mkpstr(char *str)
-{
- char *s, *os;
- int v, l = strlen(str)+1;
-
- os = s = isinlining ? permalloc(l) : tmpalloc(l);
- for (; *str; ) {
- if (*str++ == '\\')
- v = esccon(&str);
- else
- v = str[-1];
- *s++ = v;
- }
- *s = 0;
- return os;
-}
-
-static struct symtab *
-clbrace(NODE *p)
-{
- struct symtab *sp;
-
- if (blevel == 0 && xnf != NULL)
- cerror("no level0 compound literals");
-
- sp = getsymtab("cl", STEMP);
- sp->stype = p->n_type;
- sp->squal = p->n_qual;
- sp->sdf = p->n_df;
- sp->ssue = p->n_sue;
- sp->sclass = blevel ? AUTO : STATIC;
- if (!ISARY(sp->stype) || sp->sdf->ddim != 0) {
- sp->soffset = NOOFFSET;
- oalloc(sp, &autooff);
- }
- tfree(p);
- beginit(sp);
- return sp;
-}
--- usr.bin/pcc/cc/ccom/ccom.1
+++ /dev/null
@@ -1,152 +0,0 @@
-.\" $Id: ccom.1,v 1.2 2007/09/26 14:48:49 ragge Exp $
-.\" $NetBSD$
-.\" $OpenBSD$
-."\
-.\" Copyright (c) 2007 Jeremy C. Reed <reed at 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 14, 2007
-.Dt ccom 1
-.Os
-.Sh NAME
-.Nm ccom
-.Nd C compiler
-.Sh SYNOPSIS
-.Nm
-.Op Fl X Ar flags
-.Op infile
-.Op outfile
-.Pp
-.Sh DESCRIPTION
-The
-.Nm
-utility provides a C compiler.
-The frontend is usually
-.Xr pcc 1 .
-It is \fBnot\fR intended to be run directly.
-.Pp
-.Nm
-reads the C source from
-.Ar infile
-or standard input and writes the assembler source
-to
-.Ar outfile
-or to standard output.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl g
-Enable debugging.
-.\" built into binary, explain stabs?
-.It Fl s
-Print statistics to standard error when complete.
-This includes:
-name table entries, name string size, permanent allocated memory,
-temporary allocated memory, lost memory, argument list unions,
-dimension/function unions, struct/union/enum blocks, inline node count,
-inline control blocks, and permanent symtab entries.
-.\" TODO: explain units for above?
-.It Fl W Ar flags
-Report warnings.
-(Do some basic checks.)
-NOTE! These are subject to change RSN!
-.Ar Flags
-is one or more of the following:
-.Bl -tag -width Ds
-.It Sy implicit
-Implies
-.Sy implicit-int
-and
-.Sy implicit-function-declaration .
-.It Sy implicit-int
-TODO
-.It Sy implicit-function-declaration
-Report if no prototype for function.
-.It Sy missing-prototypes
-TODO
-.It Sy strict-prototypes
-TODO
-.El
-.\"
-.It Fl x Ar optimizations
-.Ar optimizations
-is one or more of the following:
-.Bl -tag -width deljumps
-.It Sy deljumps
-Delete redundant jumps and dead code.
-.It Sy ssa
-Convert statements into SSA form for optimization. Not yet finished.
-.It Sy tailcall
-Currently not implemented.
-.It Sy temps
-Setting this flag allow variables to be put into registers, for further
-optimization by the register allocator.
-.El
-.\"
-.It Fl X Ar C specific debugging flags
-.Ar Flags
-is one or more of the following:
-.Bl -tag -width Ds
-.It Sy b
-Building of parse trees
-.It Sy d
-Declarations, more d gives more output
-.It Sy t
-Type conversions
-.It Sy i
-Initializations
-.It Sy e
-Pass1 trees at exit
-.It Sy x
-Target-specific flag, used in machine-dependent code
-.El
-.\"
-.It Fl Z Ar Code generator (pass2) specific debugging flags
-.Ar Flags
-is one or more of the following:
-.Bl -tag -width Ds
-.It Sy e
-Trees when entering pass2
-.It Sy o
-Instruction generator
-.It Sy f
-Instruction matcher, may provide much output
-.It Sy r
-Register allocator
-.It Sy t
-Type matching in instruction generator
-.It Sy s
-Shape matching in instruction generator
-.It Sy u
-Sethi-Ullman computations
-.It Sy x
-Target-specific flag, used in machine-dependent code
-.El
-.Sh SEE ALSO
-.Xr as 1 ,
-.Xr cpp 1 ,
-.Xr pcc 1
-.Sh HISTORY
-The
-.Nm
-compiler is based on the original Portable C Compiler by S. C.
-Johnson, written in the late 70's.
-Even though much of the compiler has been rewritten, some of the
-basics still remain.
-About 50% of the frontend code and 80% of the backend code has been
-rewritten.
-Most is written by Anders Magnusson, with the exception of
-the data-flow analysis part and the SSA conversion code which is
-written by Peter A Jonsson, and the Mips port that were written as
-part of a project by undergraduate students at Lulea University of
-Technology.
--- usr.bin/pcc/cc/ccom/trees.c
+++ /dev/null
@@ -1,2451 +0,0 @@
-/* $Id: trees.c,v 1.163 2007/09/16 08:26:39 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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 conditionsand 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.
- */
-/*
- * Some of the changes from 32V include:
- * - Understand "void" as type.
- * - Handle enums as ints everywhere.
- * - Convert some C-specific ops into branches.
- */
-
-# include "pass1.h"
-# include "pass2.h"
-
-# include <stdarg.h>
-
-static void chkpun(NODE *p);
-static int opact(NODE *p);
-static int moditype(TWORD);
-static NODE *strargs(NODE *);
-static void rmcops(NODE *p);
-
-int lastloc = -1;
-
-/* some special actions, used in finding the type of nodes */
-# define NCVT 01
-# define PUN 02
-# define TYPL 04
-# define TYPR 010
-# define TYMATCH 040
-# define LVAL 0100
-# define CVTO 0200
-# define CVTL 0400
-# define CVTR 01000
-# define PTMATCH 02000
-# define OTHER 04000
-# define NCVTR 010000
-
-/* node conventions:
-
- NAME: rval>0 is stab index for external
- rval<0 is -inlabel number
- lval is offset in bits
- ICON: lval has the value
- rval has the STAB index, or - label number,
- if a name whose address is in the constant
- rval = NONAME means no name
- REG: rval is reg. identification cookie
-
- */
-
-int bdebug = 0;
-
-NODE *
-buildtree(int o, NODE *l, NODE *r)
-{
- NODE *p, *q;
- int actions;
- int opty;
- struct symtab *sp = NULL; /* XXX gcc */
- NODE *lr, *ll;
- char *name;
- struct symtab **elem;
-
-#ifdef PCC_DEBUG
- if (bdebug) {
- printf("buildtree(%s, %p, %p)\n", copst(o), l, r);
- if (l) fwalk(l, eprint, 0);
- if (r) fwalk(r, eprint, 0);
- }
-#endif
- opty = coptype(o);
-
- /* check for constants */
-
- if( opty == UTYPE && l->n_op == ICON ){
-
- switch( o ){
-
- case NOT:
- case UMINUS:
- case COMPL:
- if( conval( l, o, l ) ) return(l);
- break;
- }
- } else if (o == NOT && l->n_op == FCON) {
- l = clocal(block(SCONV, l, NIL, INT, 0, MKSUE(INT)));
- } else if( o == UMINUS && l->n_op == FCON ){
- l->n_dcon = -l->n_dcon;
- return(l);
-
- } else if( o==QUEST && l->n_op==ICON ) {
- CONSZ c = l->n_lval;
- nfree(l);
- if (c) {
- tfree(r->n_right);
- l = r->n_left;
- nfree(r);
- return(l);
- } else {
- tfree(r->n_left);
- l = r->n_right;
- nfree(r);
- return(l);
- }
- } else if( opty == BITYPE && l->n_op == ICON && r->n_op == ICON ){
-
- switch( o ){
-
- case PLUS:
- case MINUS:
- case MUL:
- case DIV:
- case MOD:
- /*
- * Do type propagation for simple types here.
- * The constant value is correct anyway.
- * Maybe this op shortcut should be removed?
- */
- if (l->n_sp == NULL && r->n_sp == NULL &&
- l->n_type < BTMASK && r->n_type < BTMASK) {
- if (l->n_type > r->n_type)
- r->n_type = l->n_type;
- else
- l->n_type = r->n_type;
- }
- /* FALLTHROUGH */
- case ULT:
- case UGT:
- case ULE:
- case UGE:
- case LT:
- case GT:
- case LE:
- case GE:
- case EQ:
- case NE:
- case ANDAND:
- case OROR:
- case AND:
- case OR:
- case ER:
- case LS:
- case RS:
- if( conval( l, o, r ) ) {
- nfree(r);
- return(l);
- }
- break;
- }
- } else if (opty == BITYPE && (l->n_op == FCON || l->n_op == ICON) &&
- (r->n_op == FCON || r->n_op == ICON) && (o == PLUS || o == MINUS ||
- o == MUL || o == DIV)) {
- switch(o){
- case PLUS:
- case MINUS:
- case MUL:
- case DIV:
- if (l->n_op == ICON)
- l->n_dcon = l->n_lval;
- if (r->n_op == ICON)
- r->n_dcon = r->n_lval;
- switch (o) {
- case PLUS:
- l->n_dcon += r->n_dcon; break;
- case MINUS:
- l->n_dcon -= r->n_dcon; break;
- case MUL:
- l->n_dcon *= r->n_dcon; break;
- case DIV:
- if (r->n_dcon == 0)
- uerror("division by 0.");
- else
- l->n_dcon /= r->n_dcon;
- }
- l->n_op = FCON;
- l->n_type = DOUBLE;
- l->n_sue = MKSUE(DOUBLE);
- nfree(r);
- return(l);
- }
- }
-
- /* its real; we must make a new node */
-
- p = block(o, l, r, INT, 0, MKSUE(INT));
-
- actions = opact(p);
-
- if (actions & LVAL) { /* check left descendent */
- if (notlval(p->n_left)) {
- uerror("lvalue required");
-#ifdef notyet
- } else {
- if ((l->n_type > BTMASK && ISCON(l->n_qual)) ||
- (l->n_type <= BTMASK && ISCON(l->n_qual << TSHIFT)))
- if (blevel > 0)
- uerror("lvalue is declared const");
-#endif
- }
- }
-
- if( actions & NCVTR ){
- p->n_left = pconvert( p->n_left );
- }
- else if( !(actions & NCVT ) ){
- switch( opty ){
-
- case BITYPE:
- p->n_right = pconvert( p->n_right );
- case UTYPE:
- p->n_left = pconvert( p->n_left );
-
- }
- }
-
- if ((actions&PUN) && (o!=CAST))
- chkpun(p);
-
- if( actions & (TYPL|TYPR) ){
-
- q = (actions&TYPL) ? p->n_left : p->n_right;
-
- p->n_type = q->n_type;
- p->n_qual = q->n_qual;
- p->n_df = q->n_df;
- p->n_sue = q->n_sue;
- }
-
- if( actions & CVTL ) p = convert( p, CVTL );
- if( actions & CVTR ) p = convert( p, CVTR );
- if( actions & TYMATCH ) p = tymatch(p);
- if( actions & PTMATCH ) p = ptmatch(p);
-
- if( actions & OTHER ){
- l = p->n_left;
- r = p->n_right;
-
- switch(o){
-
- case NAME:
- sp = spname;
- if (sp->sflags & STNODE) {
- /* Generated for optimizer */
- p->n_op = TEMP;
- p->n_type = sp->stype;
- p->n_sue = sp->ssue;
- p->n_df = sp->sdf;
- p->n_lval = sp->soffset;
- break;
- }
-
-#ifdef GCC_COMPAT
- /* Get a label name */
- if (sp->sflags == SLBLNAME) {
- p->n_type = VOID;
- p->n_sue = MKSUE(VOID);
- p->n_lval = 0;
- p->n_sp = sp;
- break;
- } else
-#endif
- if (sp->stype == UNDEF) {
- uerror("%s undefined", sp->sname);
- /* make p look reasonable */
- p->n_type = INT;
- p->n_sue = MKSUE(INT);
- p->n_df = NULL;
- p->n_sp = sp;
- p->n_lval = 0;
- defid(p, SNULL);
- break;
- }
- p->n_type = sp->stype;
- p->n_qual = sp->squal;
- p->n_df = sp->sdf;
- p->n_sue = sp->ssue;
- p->n_lval = 0;
- p->n_sp = sp;
- /* special case: MOETY is really an ICON... */
- if (p->n_type == MOETY) {
- p->n_sp = NULL;
- p->n_lval = sp->soffset;
- p->n_df = NULL;
- p->n_type = ENUMTY;
- p->n_op = ICON;
- }
- break;
-
- case STREF:
- /* p->x turned into *(p+offset) */
- /* rhs must be a name; check correctness */
-
- /* Find member symbol struct */
- if (l->n_type != PTR+STRTY && l->n_type != PTR+UNIONTY){
- uerror("struct or union required");
- break;
- }
-
- if ((elem = l->n_sue->suelem) == NULL)
- uerror("undefined struct or union");
-
- name = r->n_name;
- for (; *elem != NULL; elem++) {
- sp = *elem;
- if (sp->sname == name)
- break;
- }
- if (*elem == NULL)
- uerror("member '%s' not declared", name);
-
- r->n_sp = sp;
- p = stref(p);
- break;
-
- case UMUL:
- if (l->n_op == ADDROF) {
- nfree(p);
- p = l->n_left;
- nfree(l);
- }
- if( !ISPTR(l->n_type))uerror("illegal indirection");
- p->n_type = DECREF(l->n_type);
- p->n_qual = DECREF(l->n_qual);
- p->n_df = l->n_df;
- p->n_sue = l->n_sue;
- break;
-
- case ADDROF:
- switch( l->n_op ){
-
- case UMUL:
- nfree(p);
- p = l->n_left;
- nfree(l);
- case TEMP:
- case NAME:
- p->n_type = INCREF(l->n_type);
- p->n_qual = INCQAL(l->n_qual);
- p->n_df = l->n_df;
- p->n_sue = l->n_sue;
- break;
-
- case COMOP:
- nfree(p);
- lr = buildtree(ADDROF, l->n_right, NIL);
- p = buildtree( COMOP, l->n_left, lr );
- nfree(l);
- break;
-
- case QUEST:
- lr = buildtree( ADDROF, l->n_right->n_right, NIL );
- ll = buildtree( ADDROF, l->n_right->n_left, NIL );
- nfree(p); nfree(l->n_right);
- p = buildtree( QUEST, l->n_left, buildtree( COLON, ll, lr ) );
- nfree(l);
- break;
-
- default:
- uerror("unacceptable operand of &: %d", l->n_op );
- break;
- }
- break;
-
- case LS:
- case RS: /* must make type size at least int... */
- if (p->n_type == CHAR || p->n_type == SHORT) {
- p->n_left = makety(l, INT, 0, 0, MKSUE(INT));
- } else if (p->n_type == UCHAR || p->n_type == USHORT) {
- p->n_left = makety(l, UNSIGNED, 0, 0,
- MKSUE(UNSIGNED));
- }
- l = p->n_left;
- p->n_type = l->n_type;
- p->n_qual = l->n_qual;
- p->n_df = l->n_df;
- p->n_sue = l->n_sue;
-
- /* FALLTHROUGH */
- case LSEQ:
- case RSEQ: /* ...but not for assigned types */
- if(tsize(r->n_type, r->n_df, r->n_sue) > SZINT)
- p->n_right = makety(r, INT, 0, 0, MKSUE(INT));
- break;
-
- case RETURN:
- case ASSIGN:
- case CAST:
- /* structure assignment */
- /* take the addresses of the two sides; then make an
- * operator using STASG and
- * the addresses of left and right */
-
- {
- struct suedef *sue;
- TWORD t;
- union dimfun *d;
-
- if (l->n_sue != r->n_sue)
- uerror("assignment of different structures");
-
- r = buildtree(ADDROF, r, NIL);
- t = r->n_type;
- d = r->n_df;
- sue = r->n_sue;
-
- l = block(STASG, l, r, t, d, sue);
-
- if( o == RETURN ){
- nfree(p);
- p = l;
- break;
- }
-
- p->n_op = UMUL;
- p->n_left = l;
- p->n_right = NIL;
- break;
- }
- case COLON:
- /* structure colon */
-
- if (l->n_sue != r->n_sue)
- uerror( "type clash in conditional" );
- break;
-
- case CALL:
- p->n_right = r = strargs(p->n_right);
- case UCALL:
- if (!ISPTR(l->n_type))
- uerror("illegal function");
- p->n_type = DECREF(l->n_type);
- if (!ISFTN(p->n_type))
- uerror("illegal function");
- p->n_type = DECREF(p->n_type);
- p->n_df = l->n_df;
- p->n_sue = l->n_sue;
- if (l->n_op == ADDROF && l->n_left->n_op == NAME &&
- l->n_left->n_sp != NULL && l->n_left->n_sp != NULL &&
- (l->n_left->n_sp->sclass == FORTRAN ||
- l->n_left->n_sp->sclass == UFORTRAN)) {
- p->n_op += (FORTCALL-CALL);
- }
- if (p->n_type == STRTY || p->n_type == UNIONTY) {
- /* function returning structure */
- /* make function really return ptr to str., with * */
-
- p->n_op += STCALL-CALL;
- p->n_type = INCREF(p->n_type);
- p = clocal(p); /* before recursing */
- p = buildtree(UMUL, p, NIL);
-
- }
- break;
-
- default:
- cerror( "other code %d", o );
- }
-
- }
-
- /*
- * Allow (void)0 casts.
- * XXX - anything on the right side must be possible to cast.
- * XXX - remove void types further on.
- */
- if (p->n_op == CAST && p->n_type == VOID &&
- p->n_right->n_op == ICON)
- p->n_right->n_type = VOID;
-
- if (actions & CVTO)
- p = oconvert(p);
- p = clocal(p);
-
-#ifdef PCC_DEBUG
- if (bdebug) {
- printf("End of buildtree:\n");
- fwalk(p, eprint, 0);
- }
-#endif
-
- return(p);
-
- }
-
-/*
- * Do a conditional branch.
- */
-void
-cbranch(NODE *p, NODE *q)
-{
- p = buildtree(CBRANCH, p, q);
- if (p->n_left->n_op == ICON) {
- if (p->n_left->n_lval != 0)
- branch(q->n_lval); /* branch always */
- tfree(p);
- tfree(q);
- return;
- }
- ecomp(p);
-}
-
-NODE *
-strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */
-
- if( p->n_op == CM ){
- p->n_left = strargs( p->n_left );
- p->n_right = strargs( p->n_right );
- return( p );
- }
-
- if( p->n_type == STRTY || p->n_type == UNIONTY ){
- p = block(STARG, p, NIL, p->n_type, p->n_df, p->n_sue);
- p->n_left = buildtree( ADDROF, p->n_left, NIL );
- p = clocal(p);
- }
- return( p );
-}
-
-/*
- * apply the op o to the lval part of p; if binary, rhs is val
- */
-int
-conval(NODE *p, int o, NODE *q)
-{
- int i, u;
- CONSZ val;
- U_CONSZ v1, v2;
-
- val = q->n_lval;
- u = ISUNSIGNED(p->n_type) || ISUNSIGNED(q->n_type);
- if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
-
- if (p->n_sp != NULL && q->n_sp != NULL)
- return(0);
- if (q->n_sp != NULL && o != PLUS)
- return(0);
- if (p->n_sp != NULL && o != PLUS && o != MINUS)
- return(0);
- v1 = p->n_lval;
- v2 = q->n_lval;
- switch( o ){
-
- case PLUS:
- p->n_lval += val;
- if (p->n_sp == NULL) {
- p->n_rval = q->n_rval;
- p->n_type = q->n_type;
- }
- break;
- case MINUS:
- p->n_lval -= val;
- break;
- case MUL:
- p->n_lval *= val;
- break;
- case DIV:
- if (val == 0)
- uerror("division by 0");
- else {
- if (u) {
- v1 /= v2;
- p->n_lval = v1;
- } else
- p->n_lval /= val;
- }
- break;
- case MOD:
- if (val == 0)
- uerror("division by 0");
- else {
- if (u) {
- v1 %= v2;
- p->n_lval = v1;
- } else
- p->n_lval %= val;
- }
- break;
- case AND:
- p->n_lval &= val;
- break;
- case OR:
- p->n_lval |= val;
- break;
- case ER:
- p->n_lval ^= val;
- break;
- case LS:
- i = val;
- p->n_lval = p->n_lval << i;
- break;
- case RS:
- i = val;
- if (u) {
- v1 = v1 >> i;
- p->n_lval = v1;
- } else
- p->n_lval = p->n_lval >> i;
- break;
-
- case UMINUS:
- p->n_lval = - p->n_lval;
- break;
- case COMPL:
- p->n_lval = ~p->n_lval;
- break;
- case NOT:
- p->n_lval = !p->n_lval;
- break;
- case LT:
- p->n_lval = p->n_lval < val;
- break;
- case LE:
- p->n_lval = p->n_lval <= val;
- break;
- case GT:
- p->n_lval = p->n_lval > val;
- break;
- case GE:
- p->n_lval = p->n_lval >= val;
- break;
- case ULT:
- p->n_lval = v1 < v2;
- break;
- case ULE:
- p->n_lval = v1 <= v2;
- break;
- case UGT:
- p->n_lval = v1 > v2;
- break;
- case UGE:
- p->n_lval = v1 >= v2;
- break;
- case EQ:
- p->n_lval = p->n_lval == val;
- break;
- case NE:
- p->n_lval = p->n_lval != val;
- break;
- case ANDAND:
- p->n_lval = p->n_lval && val;
- break;
- case OROR:
- p->n_lval = p->n_lval || val;
- break;
- default:
- return(0);
- }
- return(1);
- }
-
-/*
- * Checks p for the existance of a pun. This is called when the op of p
- * is ASSIGN, RETURN, CAST, COLON, or relational.
- * One case is when enumerations are used: this applies only to lint.
- * In the other case, one operand is a pointer, the other integer type
- * we check that this integer is in fact a constant zero...
- * in the case of ASSIGN, any assignment of pointer to integer is illegal
- * this falls out, because the LHS is never 0.
- */
-void
-chkpun(NODE *p)
-{
- union dimfun *d1, *d2;
- NODE *q;
- int t1, t2;
-
- t1 = p->n_left->n_type;
- t2 = p->n_right->n_type;
-
- switch (p->n_op) {
- case RETURN:
- /* return of void allowed but nothing else */
- if (t1 == VOID && t2 == VOID)
- return;
- if (t1 == VOID) {
- werror("returning value from void function");
- return;
- }
- if (t2 == VOID) {
- uerror("using void value");
- return;
- }
- case COLON:
- if (t1 == VOID && t2 == VOID)
- return;
- break;
- default:
- if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID))
- return uerror("value of void expression used");
- break;
- }
-
- /* allow void pointer assignments in any direction */
- if (BTYPE(t1) == VOID && (t2 & TMASK))
- return;
- if (BTYPE(t2) == VOID && (t1 & TMASK))
- return;
-
-#ifdef notdef
- /* C99 says that enums always should be handled as ints */
- /* check for enumerations */
- if (t1==ENUMTY || t2==ENUMTY) {
- if( clogop( p->n_op ) && p->n_op != EQ && p->n_op != NE ) {
- werror( "comparison of enums" );
- return;
- }
- if (t1==ENUMTY && t2==ENUMTY) {
- if (p->n_left->n_sue!=p->n_right->n_sue)
- werror("enumeration type clash, "
- "operator %s", copst(p->n_op));
- return;
- }
- if ((t1 == ENUMTY && t2 <= BTMASK) ||
- (t2 == ENUMTY && t1 <= BTMASK))
- return;
- }
-#endif
-
- if (ISPTR(t1) || ISARY(t1))
- q = p->n_right;
- else
- q = p->n_left;
-
- if (!ISPTR(q->n_type) && !ISARY(q->n_type)) {
- if (q->n_op != ICON || q->n_lval != 0)
- werror("illegal combination of pointer and integer");
- } else {
- d1 = p->n_left->n_df;
- d2 = p->n_right->n_df;
- if (t1 == t2) {
- if (p->n_left->n_sue != p->n_right->n_sue)
- werror("illegal structure pointer combination");
- return;
- }
- for (;;) {
- if (ISARY(t1) || ISPTR(t1)) {
- if (!ISARY(t2) && !ISPTR(t2))
- break;
- if (ISARY(t1) && ISARY(t2) && d1->ddim != d2->ddim) {
- werror("illegal array size combination");
- return;
- }
- if (ISARY(t1))
- ++d1;
- if (ISARY(t2))
- ++d2;
- } else if (ISFTN(t1)) {
- if (chkftn(d1->dfun, d2->dfun)) {
- werror("illegal function "
- "pointer combination");
- return;
- }
- ++d1;
- ++d2;
- } else
- break;
- t1 = DECREF(t1);
- t2 = DECREF(t2);
- }
- werror("illegal pointer combination");
- }
-}
-
-NODE *
-stref(NODE *p)
-{
- NODE *r;
- struct suedef *sue;
- union dimfun *d;
- TWORD t, q;
- int dsc;
- OFFSZ off;
- struct symtab *s;
-
- /* make p->x */
- /* this is also used to reference automatic variables */
-
- s = p->n_right->n_sp;
- nfree(p->n_right);
- r = p->n_left;
- nfree(p);
- p = pconvert(r);
-
- /* make p look like ptr to x */
-
- if (!ISPTR(p->n_type))
- p->n_type = PTR+UNIONTY;
-
- t = INCREF(s->stype);
- q = INCQAL(s->squal);
- d = s->sdf;
- sue = s->ssue;
-
- p = makety(p, t, q, d, sue);
-
- /* compute the offset to be added */
-
- off = s->soffset;
- dsc = s->sclass;
-
- if (dsc & FIELD) { /* make fields look like ints */
- off = (off/ALINT)*ALINT;
- sue = MKSUE(INT);
- }
- if (off != 0) {
- p = block(PLUS, p, offcon(off, t, d, sue), t, d, sue);
- p->n_qual = q;
- p = optim(p);
- }
-
- p = buildtree(UMUL, p, NIL);
-
- /* if field, build field info */
-
- if (dsc & FIELD) {
- p = block(FLD, p, NIL, s->stype, 0, s->ssue);
- p->n_qual = q;
- p->n_rval = PKFIELD(dsc&FLDSIZ, s->soffset%ALINT);
- }
-
- p = clocal(p);
- return p;
-}
-
-int
-notlval(p) register NODE *p; {
-
- /* return 0 if p an lvalue, 1 otherwise */
-
- again:
-
- switch( p->n_op ){
-
- case FLD:
- p = p->n_left;
- goto again;
-
- case NAME:
- case OREG:
- case UMUL:
- if( ISARY(p->n_type) || ISFTN(p->n_type) ) return(1);
- case TEMP:
- case REG:
- return(0);
-
- default:
- return(1);
-
- }
-
- }
-/* make a constant node with value i */
-NODE *
-bcon(int i)
-{
- register NODE *p;
-
- p = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
- p->n_lval = i;
- p->n_sp = NULL;
- return(clocal(p));
-}
-
-NODE *
-bpsize(NODE *p)
-{
- return(offcon(psize(p), p->n_type, p->n_df, p->n_sue));
-}
-
-/*
- * p is a node of type pointer; psize returns the
- * size of the thing pointed to
- */
-OFFSZ
-psize(NODE *p)
-{
-
- if (!ISPTR(p->n_type)) {
- uerror("pointer required");
- return(SZINT);
- }
- /* note: no pointers to fields */
- return(tsize(DECREF(p->n_type), p->n_df, p->n_sue));
-}
-
-/*
- * convert an operand of p
- * f is either CVTL or CVTR
- * operand has type int, and is converted by the size of the other side
- * convert is called when an integer is to be added to a pointer, for
- * example in arrays or structures.
- */
-NODE *
-convert(NODE *p, int f)
-{
- union dimfun *df;
- TWORD ty, ty2;
- NODE *q, *r, *s, *rv;
-
- if (f == CVTL) {
- q = p->n_left;
- s = p->n_right;
- } else {
- q = p->n_right;
- s = p->n_left;
- }
- ty2 = ty = DECREF(s->n_type);
- while (ISARY(ty))
- ty = DECREF(ty);
-
- r = offcon(tsize(ty, s->n_df, s->n_sue), s->n_type, s->n_df, s->n_sue);
- ty = ty2;
- rv = bcon(1);
- df = s->n_df;
- while (ISARY(ty)) {
- rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) :
- tempnode(-df->ddim, INT, 0, MKSUE(INT)));
- df++;
- ty = DECREF(ty);
- }
- rv = clocal(block(PMCONV, rv, r, INT, 0, MKSUE(INT)));
- rv = optim(rv);
-
- r = block(PMCONV, q, rv, INT, 0, MKSUE(INT));
- r = clocal(r);
- /*
- * Indexing is only allowed with integer arguments, so insert
- * SCONV here if arg is not an integer.
- * XXX - complain?
- */
- if (r->n_type != INT)
- r = clocal(block(SCONV, r, NIL, INT, 0, MKSUE(INT)));
- if (f == CVTL)
- p->n_left = r;
- else
- p->n_right = r;
- return(p);
-}
-
-/*
- * change enums to ints, or appropriate types
- */
-void
-econvert( p ) register NODE *p; {
-
-
- register TWORD ty;
-
- if( (ty=BTYPE(p->n_type)) == ENUMTY || ty == MOETY ) {
- if (p->n_sue->suesize == SZCHAR)
- ty = INT;
- else if (p->n_sue->suesize == SZINT)
- ty = INT;
- else if (p->n_sue->suesize == SZSHORT)
- ty = INT;
- else if (p->n_sue->suesize == SZLONGLONG)
- ty = LONGLONG;
- else
- ty = LONG;
- ty = ctype(ty);
- p->n_sue = MKSUE(ty);
- MODTYPE(p->n_type,ty);
- if (p->n_op == ICON && ty != LONG && ty != LONGLONG)
- p->n_type = INT, p->n_sue = MKSUE(INT);
- }
-}
-
-NODE *
-pconvert( p ) register NODE *p; {
-
- /* if p should be changed into a pointer, do so */
-
- if( ISARY( p->n_type) ){
- p->n_type = DECREF( p->n_type );
- ++p->n_df;
- return( buildtree( ADDROF, p, NIL ) );
- }
- if( ISFTN( p->n_type) )
- return( buildtree( ADDROF, p, NIL ) );
-
- return( p );
- }
-
-NODE *
-oconvert(p) register NODE *p; {
- /* convert the result itself: used for pointer and unsigned */
-
- switch(p->n_op) {
-
- case LE:
- case LT:
- case GE:
- case GT:
- if( ISUNSIGNED(p->n_left->n_type) || ISUNSIGNED(p->n_right->n_type) ) p->n_op += (ULE-LE);
- case EQ:
- case NE:
- return( p );
-
- case MINUS:
- return( clocal( block( PVCONV,
- p, bpsize(p->n_left), INT, 0, MKSUE(INT))));
- }
-
- cerror( "illegal oconvert: %d", p->n_op );
-
- return(p);
- }
-
-/*
- * makes the operands of p agree; they are
- * either pointers or integers, by this time
- * with MINUS, the sizes must be the same
- * with COLON, the types must be the same
- */
-NODE *
-ptmatch(NODE *p)
-{
- struct suedef *sue, *sue2;
- union dimfun *d, *d2;
- TWORD t1, t2, t, q1, q2, q;
- int o;
-
- o = p->n_op;
- t = t1 = p->n_left->n_type;
- q = q1 = p->n_left->n_qual;
- t2 = p->n_right->n_type;
- q2 = p->n_right->n_qual;
- d = p->n_left->n_df;
- d2 = p->n_right->n_df;
- sue = p->n_left->n_sue;
- sue2 = p->n_right->n_sue;
-
- switch( o ){
-
- case ASSIGN:
- case RETURN:
- case CAST:
- { break; }
-
- case MINUS:
- { if( psize(p->n_left) != psize(p->n_right) ){
- uerror( "illegal pointer subtraction");
- }
- break;
- }
- case COLON:
- if (t1 != t2) {
- /*
- * Check for void pointer types. They are allowed
- * to cast to/from any pointers.
- */
- if (ISPTR(t1) && ISPTR(t2) &&
- (BTYPE(t1) == VOID || BTYPE(t2) == VOID))
- break;
- uerror("illegal types in :");
- }
- break;
-
- default: /* must work harder: relationals or comparisons */
-
- if( !ISPTR(t1) ){
- t = t2;
- q = q2;
- d = d2;
- sue = sue2;
- break;
- }
- if( !ISPTR(t2) ){
- break;
- }
-
- /* both are pointers */
- if( talign(t2,sue2) < talign(t,sue) ){
- t = t2;
- q = q2;
- sue = sue2;
- }
- break;
- }
-
- p->n_left = makety( p->n_left, t, q, d, sue );
- p->n_right = makety( p->n_right, t, q, d, sue );
- if( o!=MINUS && !clogop(o) ){
-
- p->n_type = t;
- p->n_qual = q;
- p->n_df = d;
- p->n_sue = sue;
- }
-
- return(clocal(p));
- }
-
-int tdebug = 0;
-
-NODE *
-tymatch(p) register NODE *p; {
-
- /* satisfy the types of various arithmetic binary ops */
-
- /* rules are:
- if assignment, type of LHS
- if any doubles, make double
- else if any float make float
- else if any longlongs, make long long
- else if any longs, make long
- else etcetc.
- if either operand is unsigned, the result is...
- */
-
- TWORD t1, t2, t, tu;
- int o, lu, ru;
-
- o = p->n_op;
-
- t1 = p->n_left->n_type;
- t2 = p->n_right->n_type;
-
- lu = ru = 0;
- if( ISUNSIGNED(t1) ){
- lu = 1;
- t1 = DEUNSIGN(t1);
- }
- if( ISUNSIGNED(t2) ){
- ru = 1;
- t2 = DEUNSIGN(t2);
- }
-
- if (t1 == ENUMTY || t1 == MOETY)
- t1 = INT; /* XXX */
- if (t2 == ENUMTY || t2 == MOETY)
- t2 = INT; /* XXX */
-#if 0
- if ((t1 == CHAR || t1 == SHORT) && o!= RETURN)
- t1 = INT;
- if (t2 == CHAR || t2 == SHORT)
- t2 = INT;
-#endif
-
- if (t1 == LDOUBLE || t2 == LDOUBLE)
- t = LDOUBLE;
- else if (t1 == DOUBLE || t2 == DOUBLE)
- t = DOUBLE;
- else if (t1 == FLOAT || t2 == FLOAT)
- t = FLOAT;
- else if (t1==LONGLONG || t2 == LONGLONG)
- t = LONGLONG;
- else if (t1==LONG || t2==LONG)
- t = LONG;
- else /* if (t1==INT || t2==INT) */
- t = INT;
-#if 0
- else if (t1==SHORT || t2==SHORT)
- t = SHORT;
- else
- t = CHAR;
-#endif
-
- if( casgop(o) ){
- tu = p->n_left->n_type;
- t = t1;
- } else {
- tu = ((ru|lu) && UNSIGNABLE(t))?ENUNSIGN(t):t;
- }
-
- /* because expressions have values that are at least as wide
- as INT or UNSIGNED, the only conversions needed
- are those involving FLOAT/DOUBLE, and those
- from LONG to INT and ULONG to UNSIGNED */
-
-
- if (t != t1 || (ru && !lu))
- p->n_left = makety( p->n_left, tu, 0, 0, MKSUE(tu));
-
- if (t != t2 || o==CAST || (lu && !ru))
- p->n_right = makety(p->n_right, tu, 0, 0, MKSUE(tu));
-
- if( casgop(o) ){
- p->n_type = p->n_left->n_type;
- p->n_df = p->n_left->n_df;
- p->n_sue = p->n_left->n_sue;
- }
- else if( !clogop(o) ){
- p->n_type = tu;
- p->n_df = NULL;
- p->n_sue = MKSUE(t);
- }
-
-#ifdef PCC_DEBUG
- if (tdebug) {
- printf("tymatch(%p): ", p);
- tprint(stdout, t1, 0);
- printf(" %s ", copst(o));
- tprint(stdout, t2, 0);
- printf(" => ");
- tprint(stdout, tu, 0);
- printf("\n");
- }
-#endif
-
- return(p);
- }
-
-/*
- * make p into type t by inserting a conversion
- */
-NODE *
-makety(NODE *p, TWORD t, TWORD q, union dimfun *d, struct suedef *sue)
-{
-
- if (p->n_type == ENUMTY && p->n_op == ICON)
- econvert(p);
- if (t == p->n_type) {
- p->n_df = d;
- p->n_sue = sue;
- p->n_qual = q;
- return(p);
- }
-
- if ((p->n_type == FLOAT || p->n_type == DOUBLE || p->n_type == LDOUBLE)
- && (t == FLOAT || t == DOUBLE || t == LDOUBLE) && p->n_op == FCON) {
- p->n_type = t;
- p->n_qual = q;
- p->n_df = d;
- p->n_sue = sue;
- return(p);
- }
-
- if (t & TMASK) {
- /* non-simple type */
- p = block(PCONV, p, NIL, t, d, sue);
- p->n_qual = q;
- return clocal(p);
- }
-
- if (p->n_op == ICON) {
- if (t == DOUBLE || t == FLOAT) {
- p->n_op = FCON;
- if (ISUNSIGNED(p->n_type))
- p->n_dcon = (U_CONSZ) p->n_lval;
- else
- p->n_dcon = p->n_lval;
- p->n_type = t;
- p->n_qual = q;
- p->n_sue = MKSUE(t);
- return (clocal(p));
- }
- }
- p = block(SCONV, p, NIL, t, d, sue);
- p->n_qual = q;
- return clocal(p);
-
-}
-
-NODE *
-block(int o, NODE *l, NODE *r, TWORD t, union dimfun *d, struct suedef *sue)
-{
- register NODE *p;
-
- p = talloc();
- p->n_rval = 0;
- p->n_op = o;
- p->n_lval = 0; /* Protect against large lval */
- p->n_left = l;
- p->n_right = r;
- p->n_type = t;
- p->n_qual = 0;
- p->n_df = d;
- p->n_sue = sue;
-#if !defined(MULTIPASS)
- /* p->n_reg = */p->n_su = 0;
- p->n_regw = 0;
-#endif
- return(p);
- }
-
-int
-icons(p) register NODE *p; {
- /* if p is an integer constant, return its value */
- int val;
-
- if( p->n_op != ICON ){
- uerror( "constant expected");
- val = 1;
- }
- else {
- val = p->n_lval;
- if( val != p->n_lval ) uerror( "constant too big for cross-compiler" );
- }
- tfree( p );
- return(val);
-}
-
-/*
- * the intent of this table is to examine the
- * operators, and to check them for
- * correctness.
- *
- * The table is searched for the op and the
- * modified type (where this is one of the
- * types INT (includes char and short), LONG,
- * DOUBLE (includes FLOAT), and POINTER
- *
- * The default action is to make the node type integer
- *
- * The actions taken include:
- * PUN check for puns
- * CVTL convert the left operand
- * CVTR convert the right operand
- * TYPL the type is determined by the left operand
- * TYPR the type is determined by the right operand
- * TYMATCH force type of left and right to match,by inserting conversions
- * PTMATCH like TYMATCH, but for pointers
- * LVAL left operand must be lval
- * CVTO convert the op
- * NCVT do not convert the operands
- * OTHER handled by code
- * NCVTR convert the left operand, not the right...
- *
- */
-
-# define MINT 01 /* integer */
-# define MDBI 02 /* integer or double */
-# define MSTR 04 /* structure */
-# define MPTR 010 /* pointer */
-# define MPTI 020 /* pointer or integer */
-# define MENU 040 /* enumeration variable or member */
-
-int
-opact(NODE *p)
-{
- int mt12, mt1, mt2, o;
-
- mt1 = mt2 = mt12 = 0;
-
- switch (coptype(o = p->n_op)) {
- case BITYPE:
- mt12=mt2 = moditype(p->n_right->n_type);
- case UTYPE:
- mt12 &= (mt1 = moditype(p->n_left->n_type));
- break;
- }
-
- switch( o ){
-
- case NAME :
- case ICON :
- case FCON :
- case CALL :
- case UCALL:
- case UMUL:
- { return( OTHER ); }
- case UMINUS:
- if( mt1 & MDBI ) return( TYPL );
- break;
-
- case COMPL:
- if( mt1 & MINT ) return( TYPL );
- break;
-
- case ADDROF:
- return( NCVT+OTHER );
- case NOT:
-/* case INIT: */
- case CM:
- case CBRANCH:
- case ANDAND:
- case OROR:
- return( 0 );
-
- case MUL:
- case DIV:
- if ((mt1&MDBI) && (mt2&MENU)) return( TYMATCH );
- if ((mt2&MDBI) && (mt1&MENU)) return( TYMATCH );
- if( mt12 & MDBI ) return( TYMATCH );
- break;
-
- case MOD:
- case AND:
- case OR:
- case ER:
- if( mt12 & MINT ) return( TYMATCH );
- break;
-
- case LS:
- case RS:
- if( mt12 & MINT ) return( TYPL+OTHER );
- break;
-
- case EQ:
- case NE:
- case LT:
- case LE:
- case GT:
- case GE:
- if( mt12 & MDBI ) return( TYMATCH+CVTO );
- else if( mt12 & MPTR ) return( PTMATCH+PUN );
- else if( mt12 & MPTI ) return( PTMATCH+PUN );
- else break;
-
- case QUEST:
- case COMOP:
- if( mt2&MENU ) return( TYPR+NCVTR );
- return( TYPR );
-
- case STREF:
- return( NCVTR+OTHER );
-
- case FORCE:
- return( TYPL );
-
- case COLON:
- if( mt12 & MDBI ) return( TYMATCH );
- else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
- else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
- else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
- else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
- break;
-
- case ASSIGN:
- case RETURN:
- if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
- case CAST:
- if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
-#if 0
- else if(mt1&MENU && mt2&MDBI) return( TYPL+LVAL+TYMATCH );
- else if(mt2&MENU && mt1&MDBI) return( TYPL+LVAL+TYMATCH );
- else if( (mt1&MENU)||(mt2&MENU) )
- return( LVAL+NCVT+TYPL+PTMATCH+PUN );
-#endif
- else if( mt1 & MPTR) return( LVAL+PTMATCH+PUN );
- else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
- break;
-
- case LSEQ:
- case RSEQ:
- if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
- break;
-
- case MULEQ:
- case DIVEQ:
- if( mt12 & MDBI ) return( LVAL+TYMATCH );
- break;
-
- case MODEQ:
- case ANDEQ:
- case OREQ:
- case EREQ:
- if (mt12 & MINT)
- return(LVAL+TYMATCH);
- break;
-
- case PLUSEQ:
- case MINUSEQ:
- case INCR:
- case DECR:
- if (mt12 & MDBI)
- return(TYMATCH+LVAL);
- else if ((mt1&MPTR) && (mt2&MINT))
- return(TYPL+LVAL+CVTR);
- break;
-
- case MINUS:
- if (mt12 & MPTR)
- return(CVTO+PTMATCH+PUN);
- if (mt2 & MPTR)
- break;
- /* FALLTHROUGH */
- case PLUS:
- if (mt12 & MDBI)
- return(TYMATCH);
- else if ((mt1&MPTR) && (mt2&MINT))
- return(TYPL+CVTR);
- else if ((mt1&MINT) && (mt2&MPTR))
- return(TYPR+CVTL);
-
- }
- uerror("operands of %s have incompatible types", copst(o));
- return(NCVT);
-}
-
-int
-moditype(TWORD ty)
-{
- switch (ty) {
-
- case ENUMTY:
- case MOETY:
- return( MENU|MINT|MDBI|MPTI );
-
- case STRTY:
- case UNIONTY:
- return( MSTR );
-
- case BOOL:
- case CHAR:
- case SHORT:
- case UCHAR:
- case USHORT:
- case UNSIGNED:
- case ULONG:
- case ULONGLONG:
- case INT:
- case LONG:
- case LONGLONG:
- return( MINT|MDBI|MPTI );
- case FLOAT:
- case DOUBLE:
- case LDOUBLE:
- return( MDBI );
- default:
- return( MPTR|MPTI );
-
- }
-}
-
-int tvaloff = 100;
-
-/*
- * Returns a TEMP node with temp number nr.
- * If nr == 0, return a node with a new number.
- */
-NODE *
-tempnode(int nr, TWORD type, union dimfun *df, struct suedef *sue)
-{
- NODE *r;
-
- r = block(TEMP, NIL, NIL, type, df, sue);
- r->n_lval = nr ? nr : tvaloff;
- tvaloff += szty(type);
- return r;
-}
-
-/*
- * Do sizeof on p.
- */
-NODE *
-doszof(NODE *p)
-{
- union dimfun *df;
- TWORD ty;
- NODE *rv;
-
- /*
- * Arrays may be dynamic, may need to make computations.
- */
-
- rv = bcon(1);
- df = p->n_df;
- ty = p->n_type;
- while (ISARY(ty)) {
- rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) :
- tempnode(-df->ddim, INT, 0, MKSUE(INT)));
- df++;
- ty = DECREF(ty);
- }
- rv = buildtree(MUL, rv, bcon(tsize(ty, p->n_df, p->n_sue)/SZCHAR));
- tfree(p);
- return rv;
-}
-
-#ifdef PCC_DEBUG
-void
-eprint(NODE *p, int down, int *a, int *b)
-{
- int ty;
-
- *a = *b = down+1;
- while( down > 1 ){
- printf( "\t" );
- down -= 2;
- }
- if( down ) printf( " " );
-
- ty = coptype( p->n_op );
-
- printf("%p) %s, ", p, copst(p->n_op));
- if (ty == LTYPE) {
- printf(CONFMT, p->n_lval);
- printf(", %d, ", p->n_rval);
- }
- tprint(stdout, p->n_type, p->n_qual);
- printf( ", %p, %p\n", p->n_df, p->n_sue );
-}
-# endif
-
-void
-prtdcon(NODE *p)
-{
- int o = p->n_op, i;
-
- if (o != FCON)
- return;
-
- /* Write float constants to memory */
- /* Should be volontary per architecture */
-
- setloc1(RDATA);
- defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
- ALDOUBLE : ALLDOUBLE );
- deflab1(i = getlab());
- ninval(0, btdims[p->n_type].suesize, p);
- p->n_op = NAME;
- p->n_lval = 0;
- p->n_sp = tmpalloc(sizeof(struct symtab_hdr));
- p->n_sp->sclass = ILABEL;
- p->n_sp->soffset = i;
-}
-
-extern int negrel[];
-
-/*
- * Walk up through the tree from the leaves,
- * removing constant operators.
- */
-static void
-logwalk(NODE *p)
-{
- int o = coptype(p->n_op);
- NODE *l, *r;
-
- l = p->n_left;
- r = p->n_right;
- switch (o) {
- case LTYPE:
- return;
- case BITYPE:
- logwalk(r);
- case UTYPE:
- logwalk(l);
- }
- if (!clogop(p->n_op))
- return;
- if (p->n_op == NOT && l->n_op == ICON) {
- p->n_lval = l->n_lval == 0;
- nfree(l);
- p->n_op = ICON;
- }
- if (l->n_op == ICON && r->n_op == ICON) {
- if (conval(l, p->n_op, r) == 0) {
- /*
- * people sometimes tend to do really odd compares,
- * like "if ("abc" == "def")" etc.
- * do it runtime instead.
- */
- } else {
- p->n_lval = l->n_lval;
- p->n_op = ICON;
- nfree(l);
- nfree(r);
- }
- }
-}
-
-/*
- * Removes redundant logical operators for branch conditions.
- */
-static void
-fixbranch(NODE *p, int label)
-{
-
- logwalk(p);
-
- if (p->n_op == ICON) {
- if (p->n_lval != 0)
- branch(label);
- nfree(p);
- } else {
- if (!clogop(p->n_op)) /* Always conditional */
- p = buildtree(NE, p, bcon(0));
- ecode(buildtree(CBRANCH, p, bcon(label)));
- }
-}
-
-/*
- * Write out logical expressions as branches.
- */
-static void
-andorbr(NODE *p, int true, int false)
-{
- NODE *q;
- int o, lab;
-
- lab = -1;
- switch (o = p->n_op) {
- case EQ:
- case NE:
- /*
- * Remove redundant EQ/NE nodes.
- */
- while (((o = p->n_left->n_op) == EQ || o == NE) &&
- p->n_right->n_op == ICON) {
- o = p->n_op;
- q = p->n_left;
- if (p->n_right->n_lval == 0) {
- nfree(p->n_right);
- *p = *q;
- nfree(q);
- if (o == EQ)
- p->n_op = negrel[p->n_op - EQ];
-// p->n_op = NE; /* toggla */
- } else if (p->n_right->n_lval == 1) {
- nfree(p->n_right);
- *p = *q;
- nfree(q);
- if (o == NE)
- p->n_op = negrel[p->n_op - EQ];
-// p->n_op = EQ; /* toggla */
- } else
- break; /* XXX - should always be false */
-
- }
- /* FALLTHROUGH */
- case LE:
- case LT:
- case GE:
- case GT:
-calc: if (true < 0) {
- p->n_op = negrel[p->n_op - EQ];
- true = false;
- false = -1;
- }
-
- rmcops(p->n_left);
- rmcops(p->n_right);
- fixbranch(p, true);
- if (false >= 0)
- branch(false);
- break;
-
- case ULE:
- case UGT:
- /* Convert to friendlier ops */
- if (p->n_right->n_op == ICON && p->n_right->n_lval == 0)
- p->n_op = o == ULE ? EQ : NE;
- goto calc;
-
- case UGE:
- case ULT:
- /* Already true/false by definition */
- if (p->n_right->n_op == ICON && p->n_right->n_lval == 0) {
- if (true < 0) {
- o = o == ULT ? UGE : ULT;
- true = false;
- }
- rmcops(p->n_left);
- ecode(p->n_left);
- rmcops(p->n_right);
- ecode(p->n_right);
- nfree(p);
- if (o == UGE) /* true */
- branch(true);
- break;
- }
- goto calc;
-
- case ANDAND:
- lab = false<0 ? getlab() : false ;
- andorbr(p->n_left, -1, lab);
- andorbr(p->n_right, true, false);
- if (false < 0)
- plabel( lab);
- nfree(p);
- break;
-
- case OROR:
- lab = true<0 ? getlab() : true;
- andorbr(p->n_left, lab, -1);
- andorbr(p->n_right, true, false);
- if (true < 0)
- plabel( lab);
- nfree(p);
- break;
-
- case NOT:
- andorbr(p->n_left, false, true);
- nfree(p);
- break;
-
- default:
- rmcops(p);
- if (true >= 0)
- fixbranch(p, true);
- if (false >= 0) {
- if (true >= 0)
- branch(false);
- else
- fixbranch(buildtree(EQ, p, bcon(0)), false);
- }
- }
-}
-
-/*
- * Massage the output trees to remove C-specific nodes:
- * COMOPs are split into separate statements.
- * QUEST/COLON are rewritten to branches.
- * ANDAND/OROR/NOT are rewritten to branches for lazy-evaluation.
- * CBRANCH conditions are rewritten for lazy-evaluation.
- */
-static void
-rmcops(NODE *p)
-{
- TWORD type;
- NODE *q, *r;
- int o, ty, lbl, lbl2, tval = 0;
-
-again:
- o = p->n_op;
- ty = coptype(o);
- switch (o) {
- case QUEST:
-
- /*
- * Create a branch node from ?:
- * || and && must be taken special care of.
- */
- type = p->n_type;
- andorbr(p->n_left, -1, lbl = getlab());
-
- /* Make ASSIGN node */
- /* Only if type is not void */
- q = p->n_right->n_left;
- if (type != VOID) {
- r = tempnode(0, q->n_type, q->n_df, q->n_sue);
- tval = r->n_lval;
- q = buildtree(ASSIGN, r, q);
- }
- rmcops(q);
- ecode(q); /* Done with assign */
- branch(lbl2 = getlab());
- plabel( lbl);
-
- q = p->n_right->n_right;
- if (type != VOID) {
- r = tempnode(tval, q->n_type, q->n_df, q->n_sue);
- q = buildtree(ASSIGN, r, q);
- }
- rmcops(q);
- ecode(q); /* Done with assign */
-
- plabel( lbl2);
-
- nfree(p->n_right);
- if (p->n_type != VOID) {
- r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
- *p = *r;
- nfree(r);
- } else
- p->n_op = ICON;
- break;
-
- case ULE:
- case ULT:
- case UGE:
- case UGT:
- case EQ:
- case NE:
- case LE:
- case LT:
- case GE:
- case GT:
- case ANDAND:
- case OROR:
- case NOT:
-#ifdef SPECIAL_CCODES
-#error fix for private CCODES handling
-#else
- r = talloc();
- *r = *p;
- andorbr(r, -1, lbl = getlab());
- q = tempnode(0, p->n_type, p->n_df, p->n_sue);
- tval = q->n_lval;
- r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
- ecode(buildtree(ASSIGN, q, bcon(1)));
- branch(lbl2 = getlab());
- plabel( lbl);
- ecode(buildtree(ASSIGN, r, bcon(0)));
- plabel( lbl2);
- r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
- *p = *r;
- nfree(r);
-#endif
- break;
- case CBRANCH:
- andorbr(p->n_left, p->n_right->n_lval, -1);
- nfree(p->n_right);
- p->n_op = ICON; p->n_type = VOID;
- break;
- case COMOP:
- rmcops(p->n_left);
- ecode(p->n_left);
- /* Now when left tree is dealt with, rm COMOP */
- q = p->n_right;
- *p = *p->n_right;
- nfree(q);
- goto again;
-
- default:
- if (ty == LTYPE)
- return;
- rmcops(p->n_left);
- if (ty == BITYPE)
- rmcops(p->n_right);
- }
-}
-
-/*
- * Return 1 if an assignment is found.
- */
-static int
-has_se(NODE *p)
-{
- if (cdope(p->n_op) & ASGFLG)
- return 1;
- if (coptype(p->n_op) == LTYPE)
- return 0;
- if (has_se(p->n_left))
- return 1;
- if (coptype(p->n_op) == BITYPE)
- return has_se(p->n_right);
- return 0;
-}
-
-/*
- * Find and convert asgop's to separate statements.
- * Be careful about side effects.
- * assign tells whether ASSIGN should be considered giving
- * side effects or not.
- */
-static NODE *
-delasgop(NODE *p)
-{
- NODE *q, *r;
- int tval;
-
- if (p->n_op == INCR || p->n_op == DECR) {
- /*
- * Rewrite x++ to (x += 1) -1; and deal with it further down.
- * Pass2 will remove -1 if unneccessary.
- */
- q = ccopy(p);
- tfree(p->n_left);
- q->n_op = (p->n_op==INCR)?PLUSEQ:MINUSEQ;
- p->n_op = (p->n_op==INCR)?MINUS:PLUS;
- p->n_left = delasgop(q);
-
- } else if ((cdope(p->n_op)&ASGOPFLG) &&
- p->n_op != RETURN && p->n_op != CAST) {
- NODE *l = p->n_left;
- NODE *ll = l->n_left;
-
- if (has_se(l)) {
- q = tempnode(0, ll->n_type, ll->n_df, ll->n_sue);
- tval = q->n_lval;
- r = tempnode(tval, ll->n_type, ll->n_df,ll->n_sue);
- l->n_left = q;
- /* Now the left side of node p has no side effects. */
- /* side effects on the right side must be obeyed */
- p = delasgop(p);
-
- r = buildtree(ASSIGN, r, ll);
- r = delasgop(r);
- ecode(r);
- } else {
-#if 0 /* Cannot call buildtree() here, it would invoke double add shifts */
- p->n_right = buildtree(UNASG p->n_op, ccopy(l),
- p->n_right);
-#else
- p->n_right = block(UNASG p->n_op, ccopy(l),
- p->n_right, p->n_type, p->n_df, p->n_sue);
-#endif
- p->n_op = ASSIGN;
- p->n_right = delasgop(p->n_right);
- p->n_right = clocal(p->n_right);
- }
-
- } else {
- if (coptype(p->n_op) == LTYPE)
- return p;
- p->n_left = delasgop(p->n_left);
- if (coptype(p->n_op) == BITYPE)
- p->n_right = delasgop(p->n_right);
- }
- return p;
-}
-
-int edebug = 0;
-void
-ecomp(NODE *p)
-{
-
-#ifdef PCC_DEBUG
- if (edebug)
- fwalk(p, eprint, 0);
-#endif
- if (!reached) {
- werror("statement not reached");
- reached = 1;
- }
- p = optim(p);
- rmcops(p);
- p = delasgop(p);
- setloc1(PROG);
- if (p->n_op == ICON && p->n_type == VOID)
- tfree(p);
- else
- ecode(p);
-}
-
-#if defined(MULTIPASS)
-void
-p2tree(NODE *p)
-{
- struct symtab *q;
- int ty;
-
-# ifdef MYP2TREE
- MYP2TREE(p); /* local action can be taken here; then return... */
-# endif
-
- ty = coptype(p->n_op);
-
- printf("%d\t", p->n_op);
-
- if (ty == LTYPE) {
- printf(CONFMT, p->n_lval);
- printf("\t");
- }
- if (ty != BITYPE) {
- if (p->n_op == NAME || p->n_op == ICON)
- printf("0\t");
- else
- printf("%d\t", p->n_rval);
- }
-
- printf("%o\t", p->n_type);
-
- /* handle special cases */
-
- switch (p->n_op) {
-
- case NAME:
- case ICON:
- /* print external name */
- if ((q = p->n_sp) != NULL) {
- if ((q->sclass == STATIC && q->slevel > 0) ||
- q->sclass == ILABEL) {
- printf(LABFMT, q->soffset);
- } else
- printf("%s\n", exname(q->sname));
- } else
- printf("\n");
- break;
-
- case STARG:
- case STASG:
- case STCALL:
- case USTCALL:
- /* print out size */
- /* use lhs size, in order to avoid hassles
- * with the structure `.' operator
- */
-
- /* note: p->left not a field... */
- printf(CONFMT, (CONSZ)tsize(STRTY, p->n_left->n_df,
- p->n_left->n_sue));
- printf("\t%d\t\n", talign(STRTY, p->n_left->n_sue));
- break;
-
- default:
- printf( "\n" );
- }
-
- if (ty != LTYPE)
- p2tree(p->n_left);
- if (ty == BITYPE)
- p2tree(p->n_right);
-}
-#else
-void
-p2tree(NODE *p)
-{
- struct symtab *q;
- int ty;
-
-# ifdef MYP2TREE
- MYP2TREE(p); /* local action can be taken here; then return... */
-# endif
-
- ty = coptype(p->n_op);
-
- switch( p->n_op ){
-
- case NAME:
- case ICON:
- if ((q = p->n_sp) != NULL) {
- if ((q->sclass == STATIC && q->slevel > 0) ||
-#ifdef GCC_COMPAT
- q->sflags == SLBLNAME ||
-#endif
- q->sclass == ILABEL) {
- char *cp = (isinlining ?
- permalloc(32) : tmpalloc(32));
- int n = q->soffset;
- if (n < 0)
- n = -n;
- snprintf(cp, 32, LABFMT, n);
- p->n_name = cp;
- } else {
-#ifdef GCC_COMPAT
- p->n_name = gcc_findname(q);
-#else
- p->n_name = exname(q->sname);
-#endif
- }
- } else
- p->n_name = "";
- break;
-
- case STASG:
- /* STASG used for stack array init */
- if (ISARY(p->n_type)) {
- int size1 = tsize(p->n_type, p->n_left->n_df,
- p->n_left->n_sue)/SZCHAR;
- p->n_stsize = tsize(p->n_type, p->n_right->n_df,
- p->n_right->n_sue)/SZCHAR;
- if (size1 < p->n_stsize)
- p->n_stsize = size1;
- p->n_stalign = talign(p->n_type,
- p->n_left->n_sue)/SZCHAR;
- break;
- }
- /* FALLTHROUGH */
- case STARG:
- case STCALL:
- case USTCALL:
- /* set up size parameters */
- p->n_stsize = (tsize(STRTY, p->n_left->n_df,
- p->n_left->n_sue)+SZCHAR-1)/SZCHAR;
- p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR;
- break;
-
- default:
- p->n_name = "";
- }
-
- if( ty != LTYPE ) p2tree( p->n_left );
- if( ty == BITYPE ) p2tree( p->n_right );
- }
-
-#endif
-
-/*
- * Change void data types into char.
- */
-static void
-delvoid(NODE *p)
-{
- /* Convert "PTR undef" (void *) to "PTR uchar" */
- if (BTYPE(p->n_type) == VOID)
- p->n_type = (p->n_type & ~BTMASK) | UCHAR;
- if (BTYPE(p->n_type) == BOOL) {
- if (p->n_op == SCONV && p->n_type == BOOL) {
- /* create a jump and a set */
- NODE *q, *r, *s;
- int l, val;
-
- q = talloc();
- *q = *p;
- q->n_type = BOOL_TYPE;
- r = tempnode(0, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
- val = r->n_lval;
- s = tempnode(val, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
- *p = *s;
- q = buildtree(ASSIGN, r, q);
- cbranch(buildtree(EQ, q, bcon(0)), bcon(l = getlab()));
- ecode(buildtree(ASSIGN, s, bcon(1)));
- plabel(l);
- } else
- p->n_type = (p->n_type & ~BTMASK) | BOOL_TYPE;
- }
-
-}
-
-void
-ecode(NODE *p)
-{
- /* walk the tree and write out the nodes.. */
-
- if (nerrors)
- return;
-
- p = optim(p);
- p = delasgop(p);
- walkf(p, prtdcon);
- walkf(p, delvoid);
-#ifdef PCC_DEBUG
- if (xdebug) {
- printf("Fulltree:\n");
- fwalk(p, eprint, 0);
- }
-#endif
- p2tree(p);
-#if !defined(MULTIPASS)
- send_passt(IP_NODE, p);
-#endif
-}
-
-/*
- * Send something further on to the next pass.
- */
-void
-send_passt(int type, ...)
-{
- struct interpass *ip;
- struct interpass_prolog *ipp;
- extern int crslab;
- va_list ap;
- int sz;
-
- va_start(ap, type);
- if (type == IP_PROLOG || type == IP_EPILOG)
- sz = sizeof(struct interpass_prolog);
- else
- sz = sizeof(struct interpass);
-
- ip = isinlining ? permalloc(sz) : tmpalloc(sz);
- ip->type = type;
- ip->lineno = lineno;
- switch (type) {
- case IP_NODE:
- if (lastloc != PROG)
- setloc1(PROG);
- ip->ip_node = va_arg(ap, NODE *);
- break;
- case IP_EPILOG:
- case IP_PROLOG:
- setloc1(PROG);
- ipp = (struct interpass_prolog *)ip;
- ipp->ipp_regs = va_arg(ap, int);
- ipp->ipp_autos = va_arg(ap, int);
- ipp->ipp_name = va_arg(ap, char *);
- ipp->ipp_type = va_arg(ap, TWORD);
- ipp->ipp_vis = va_arg(ap, int);
- ip->ip_lbl = va_arg(ap, int);
- ipp->ip_tmpnum = tvaloff;
- ipp->ip_lblnum = crslab;
- if (type == IP_PROLOG)
- ipp->ip_lblnum--;
- break;
- case IP_DEFLAB:
- ip->ip_lbl = va_arg(ap, int);
- break;
- case IP_ASM:
- if (blevel == 0) { /* outside function */
- printf("\t%s\n", va_arg(ap, char *));
- va_end(ap);
- lastloc = -1;
- return;
- }
- ip->ip_asm = va_arg(ap, char *);
- break;
- default:
- cerror("bad send_passt type %d", type);
- }
- va_end(ap);
- if (isinlining)
- inline_addarg(ip);
- else
- pass2_compile(ip);
- if (type == IP_EPILOG)
- lastloc = PROG;
-}
-
-char *
-copst(int op)
-{
- if (op <= MAXOP)
- return opst[op];
-#define SNAM(x,y) case x: return #y;
- switch (op) {
- SNAM(QUALIFIER,QUALIFIER)
- SNAM(CLASS,CLASS)
- SNAM(RB,])
- SNAM(DOT,.)
- SNAM(ELLIPSIS,...)
- SNAM(LB,[)
- SNAM(TYPE,TYPE)
- SNAM(COMOP,COMOP)
- SNAM(QUEST,?)
- SNAM(COLON,:)
- SNAM(ANDAND,&&)
- SNAM(OROR,||)
- SNAM(NOT,!)
- SNAM(CAST,CAST)
- SNAM(PLUSEQ,+=)
- SNAM(MINUSEQ,-=)
- SNAM(MULEQ,*=)
- SNAM(DIVEQ,/=)
- SNAM(MODEQ,%=)
- SNAM(ANDEQ,&=)
- SNAM(OREQ,|=)
- SNAM(EREQ,^=)
- SNAM(LSEQ,<<=)
- SNAM(RSEQ,>>=)
- SNAM(INCR,++)
- SNAM(DECR,--)
- default:
- cerror("bad copst %d", op);
- }
- return 0; /* XXX gcc */
-}
-
-int
-cdope(int op)
-{
- if (op <= MAXOP)
- return dope[op];
- switch (op) {
- case QUALIFIER:
- case CLASS:
- case RB:
- case DOT:
- case ELLIPSIS:
- case TYPE:
- return LTYPE;
- case COMOP:
- case QUEST:
- case COLON:
- case LB:
- return BITYPE;
- case ANDAND:
- case OROR:
- return BITYPE|LOGFLG;
- case NOT:
- return UTYPE|LOGFLG;
- case CAST:
- return BITYPE|ASGFLG|ASGOPFLG;
- case PLUSEQ:
- return BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG;
- case MINUSEQ:
- return BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG;
- case MULEQ:
- return BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG;
- case OREQ:
- case EREQ:
- case ANDEQ:
- return BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG;
- case DIVEQ:
- return BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG;
- case MODEQ:
- return BITYPE|DIVFLG|ASGFLG|ASGOPFLG;
- case LSEQ:
- case RSEQ:
- return BITYPE|SHFFLG|ASGFLG|ASGOPFLG;
- case INCR:
- case DECR:
- return BITYPE|ASGFLG;
- }
- return 0; /* XXX gcc */
-}
-
-/*
- * make a fresh copy of p
- */
-NODE *
-ccopy(NODE *p)
-{
- NODE *q;
-
- q = talloc();
- *q = *p;
-
- switch (coptype(q->n_op)) {
- case BITYPE:
- q->n_right = ccopy(p->n_right);
- case UTYPE:
- q->n_left = ccopy(p->n_left);
- }
-
- return(q);
-}
-
-/*
- * set PROG-seg label.
- */
-void
-plabel(int label)
-{
- setloc1(PROG);
- reached = 1; /* Will this always be correct? */
- send_passt(IP_DEFLAB, label);
-}
--- usr.bin/pcc/cc/ccom/stabs.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* $Id: stabs.c,v 1.15 2007/09/15 07:37:44 ragge Exp $ */
-
-/*
- * Copyright (c) 2004 Anders Magnusson (ragge at 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.
- */
-
-/*
- * Simple implementation of the "stabs" debugging format.
- * Not complete but at least makes it possible to set breakpoints,
- * examine simple variables and do stack traces.
- * Based on the stabs documentation that follows gdb.
- */
-
-#include "pass1.h"
-
-#ifdef STABS
-
-#include <sys/types.h>
-#include <stab.h>
-#include <stdarg.h>
-#include <string.h>
-
-#define STABHASH 256
-#define INTNUM 1 /* internal number of type "int" */
-#define BIT2BYTE(x) ((x)/SZCHAR)
-
-#ifndef STABLBL
-#error macdefs.h must define STABLBL
-#endif
-
-/*
- * Local type mapping
- * Types are defined as a typeword, a dimension pointer (in the case
- * of arrays) and struct/union/enum declarations.
- * Function prototypes are ignored.
- */
-static struct stabtype {
- struct stabtype *next; /* linked list */
- TWORD type; /* pcc type number */
- union dimfun *df; /* dimension of arrays */
- struct suedef *sue; /* struct/union/enum declarations */
- int num; /* local type number */
-} *stabhash[STABHASH];
-static int ntypes;
-static char *curfun;
-static int stablbl = 10;
-
-void ptype(char *name, int num, int inhnum, long long min, long long max);
-struct stabtype *addtype(TWORD, union dimfun *, struct suedef *);
-struct stabtype *findtype(TWORD t, union dimfun *df, struct suedef *sue);
-void printtype(struct symtab *s, char *str, int len);
-void cprint(int p2, char *fmt, ...);
-
-#define MAXPSTR 100
-
-extern int isinlining;
-#define savestabs isinlining
-
-/*
- * Output type definitions for the stab debugging format.
- * Note that "int" is always internal number 1.
- */
-void
-stabs_init()
-{
- struct stabtype *st;
-
-#define ADDTYPE(y) addtype(y, NULL, MKSUE(y))
-
- ptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT);
-
- st = ADDTYPE(CHAR);
- ptype("char", st->num, st->num, 0, MAX_CHAR);
- ptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT);
- ptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG);
- ptype("long long", ADDTYPE(LONGLONG)->num, INTNUM,
- MIN_LONGLONG, MAX_LONGLONG);
- ptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR);
- ptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT);
- ptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED);
- ptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG);
- ptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM,
- 0, MAX_ULONGLONG);
-
- ptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0);
- ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0);
- ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0);
- st = ADDTYPE(VOID);
- cprint(savestabs, ".stabs \"void:t%d=r%d\",%d,0,0,0\n",
- st->num, st->num, N_LSYM);
-
-}
-
-/*
- * Print a type in stabs format
- */
-void
-ptype(char *name, int num, int inhnum, long long min, long long max)
-{
- cprint(savestabs, ".stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0",
- name, num, inhnum, min, max, N_LSYM);
-}
-
-/*
- * Add a new local type to the hash table.
- * The search key is the (type, df, sue) triple.
- */
-struct stabtype *
-addtype(TWORD t, union dimfun *df, struct suedef *sue)
-{
- struct stabtype *st;
-
- st = permalloc(sizeof(struct stabtype));
- st->type = t;
- st->df = df;
- st->sue = sue;
- st->num = ++ntypes;
- st->next = stabhash[t & (STABHASH-1)];
- stabhash[t & (STABHASH-1)] = st;
- return st;
-}
-
-/*
- * Search for a given type and return a type pointer (or NULL).
- */
-struct stabtype *
-findtype(TWORD t, union dimfun *df, struct suedef *sue)
-{
- struct stabtype *st;
- union dimfun *dw, *dx;
- TWORD tw;
-
- st = stabhash[t & (STABHASH-1)];
- for (; st; st = st->next) {
- if (t != st->type || sue != st->sue)
- continue;
- /* Ok, type and sue matches, check dimensions */
- if (st->df == NULL)
- return st; /* no arrays, got match */
- dw = st->df;
- dx = df;
- tw = t;
- for (; tw > BTMASK; tw = DECREF(tw)) {
- if (ISARY(tw)) {
- if (dw->ddim == dx->ddim)
- dw++, dx++;
- else
- break;
- }
- }
- if (tw <= BTMASK)
- return st;
- }
- return NULL;
-}
-
-/*
- * Print current line number.
- */
-void
-stabs_line(int line)
-{
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", N_SLINE, line, stablbl, curfun);
- cprint(1, STABLBL ":", stablbl++);
-}
-
-/*
- * Start of block.
- */
-void
-stabs_lbrac(int blklvl)
-{
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s",
- N_LBRAC, blklvl, stablbl, curfun);
- cprint(1, STABLBL ":", stablbl++);
-}
-
-/*
- * End of block.
- */
-void
-stabs_rbrac(int blklvl)
-{
- cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s\n",
- N_RBRAC, blklvl, stablbl, curfun);
- cprint(1, STABLBL ":", stablbl++);
-}
-
-/*
- * Print current file and set mark.
- */
-void
-stabs_file(char *fname)
-{
- static char *mainfile;
-
- if (mainfile == NULL)
- mainfile = fname; /* first call */
- cprint(savestabs, ".stabs \"%s\",%d,0,0," STABLBL,
- fname, fname == mainfile ? N_SO : N_SOL, stablbl);
- cprint(savestabs, STABLBL ":", stablbl++);
-}
-
-/*
- * Print beginning of function.
- */
-void
-stabs_func(struct symtab *s)
-{
- char str[MAXPSTR];
-
- curfun = s->sname;
-#ifdef GCC_COMPAT
- curfun = gcc_findname(cftnsp);
-#endif
- printtype(s, str, sizeof(str));
- cprint(savestabs, ".stabs \"%s:%c%s\",%d,0,%d,%s",
- curfun, s->sclass == STATIC ? 'f' : 'F', str,
- N_FUN, BIT2BYTE(s->ssue->suesize), exname(curfun));
-}
-
-/*
- * Print a (complex) type.
- * Will also create subtypes.
- * Printed string is like "20=*21=*1".
- */
-void
-printtype(struct symtab *s, char *ostr, int len)
-{
- struct stabtype *st;
- union dimfun *df = s->sdf;
- struct suedef *sue = s->ssue;
- TWORD t = s->stype;
- int op = 0;
-
- /* Print out not-yet-found types */
- if (ISFTN(t))
- t = DECREF(t);
- st = findtype(t, df, sue);
- while (st == NULL && t > BTMASK) {
- st = addtype(t, df, sue);
- op+=snprintf(ostr+op, len - op, "%d=", st->num);
- if (ISFTN(t))
- ostr[op++] = 'f';
- else if (ISPTR(t))
- ostr[op++] = '*';
- else if (ISARY(t)) {
- op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1);
- } else
- cerror("printtype: notype");
- if (ISARY(t))
- df++;
- t = DECREF(t);
- st = findtype(t, df, sue);
- if (op > MAXPSTR-10)
- cerror("printtype: too difficult expression");
- }
- /* print out basic type. may have to be entered in case of sue */
- snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num);
- /* snprintf here null-terminated the string */
-}
-
-void
-stabs_newsym(struct symtab *s)
-{
- char *sname;
- char ostr[MAXPSTR];
-
- if (ISFTN(s->stype))
- return; /* functions are handled separate */
-
- if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS ||
- s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE ||
- s->sclass == TYPEDEF || (s->sclass & FIELD))
- return; /* XXX - fix structs */
-
- sname = s->sname;
-#ifdef GCC_COMPAT
- sname = gcc_findname(s);
-#endif
-
- printtype(s, ostr, sizeof(ostr));
- switch (s->sclass) {
- case PARAM:
- cprint(savestabs, ".stabs \"%s:p%s\",%d,0,%d,%d", sname, ostr,
- N_PSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
- break;
-
- case AUTO:
- cprint(savestabs, ".stabs \"%s:%s\",%d,0,%d,%d", sname, ostr,
- N_LSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
- break;
-
- case STATIC:
- if (blevel)
- cprint(savestabs, ".stabs \"%s:V%s\",%d,0,%d," LABFMT, sname, ostr,
- N_LCSYM, BIT2BYTE(s->ssue->suesize), s->soffset);
- else
- cprint(savestabs, ".stabs \"%s:S%s\",%d,0,%d,%s", sname, ostr,
- N_LCSYM, BIT2BYTE(s->ssue->suesize), exname(sname));
- break;
-
- case EXTERN:
- case EXTDEF:
- cprint(savestabs, ".stabs \"%s:G%s\",%d,0,%d,0", sname, ostr,
- N_GSYM, BIT2BYTE(s->ssue->suesize));
- break;
-
- case REGISTER:
- cprint(savestabs, ".stabs \"%s:r%s\",%d,0,%d,%d", sname, ostr,
- N_RSYM, 1, s->soffset);
- break;
-
- default:
- cerror("fix stab_newsym; class %d", s->sclass);
- }
-}
-
-void
-stabs_chgsym(struct symtab *s)
-{
-}
-
-/*
- * define a struct.
- */
-void
-stabs_struct(struct symtab *p, struct suedef *sue)
-{
-}
-
-void
-cprint(int p2, char *fmt, ...)
-{
- va_list ap;
- char *str;
-
- va_start(ap, fmt);
- if (p2) {
- str = tmpvsprintf(fmt, ap);
- str = newstring(str, strlen(str)); /* XXX - for inlines */
- send_passt(IP_ASM, str);
- } else {
- putchar('\t');
- vprintf(fmt, ap);
- putchar('\n');
- }
- va_end(ap);
-}
-
-#endif
--- usr.bin/pcc/cc/ccom/symtabs.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* $Id: symtabs.c,v 1.14 2006/06/16 09:30:32 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-#include "pass1.h"
-
-/*
- * These definitions are used in the patricia tree that stores
- * the strings.
- */
-#define LEFT_IS_LEAF 0x80000000
-#define RIGHT_IS_LEAF 0x40000000
-#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
-#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
-#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
-#define CHECKBITS 8
-
-struct tree {
- int bitno;
- struct tree *lr[2];
-};
-
-static struct tree *firstname;
-int nametabs, namestrlen;
-static struct tree *firststr;
-int strtabs, strstrlen;
-static char *symtab_add(char *key, struct tree **, int *, int *);
-
-#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
-#define getree() permalloc(sizeof(struct tree))
-
-char *
-addname(char *key)
-{
- return symtab_add(key, &firstname, &nametabs, &namestrlen);
-}
-
-char *
-addstring(char *key)
-{
- return symtab_add(key, &firststr, &strtabs, &strstrlen);
-}
-
-/*
- * Add a name to the name stack (if its non-existing),
- * return its address.
- * This is a simple patricia implementation.
- */
-char *
-symtab_add(char *key, struct tree **first, int *tabs, int *stlen)
-{
- struct tree *w, *new, *last;
- int cix, bit, fbit, svbit, ix, bitno, len;
- char *m, *k, *sm;
-
- /* Count full string length */
- for (k = key, len = 0; *k; k++, len++)
- ;
-
- switch (*tabs) {
- case 0:
- *first = (struct tree *)newstring(key, len);
- *stlen += (len + 1);
- (*tabs)++;
- return (char *)*first;
-
- case 1:
- m = (char *)*first;
- svbit = 0; /* XXX why? */
- break;
-
- default:
- w = *first;
- bitno = len * CHECKBITS;
- for (;;) {
- bit = BITNO(w->bitno);
- fbit = bit > bitno ? 0 : P_BIT(key, bit);
- svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
- IS_LEFT_LEAF(w->bitno);
- w = w->lr[fbit];
- if (svbit) {
- m = (char *)w;
- break;
- }
- }
- }
-
- sm = m;
- k = key;
-
- /* Check for correct string and return */
- for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS)
- ;
- if (*m == 0 && *k == 0)
- return sm;
-
- ix = *m ^ *k;
- while ((ix & 1) == 0)
- ix >>= 1, cix++;
-
- /* Create new node */
- new = getree();
- bit = P_BIT(key, cix);
- new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
- new->lr[bit] = (struct tree *)newstring(key, len);
- *stlen += (len + 1);
-
- if ((*tabs)++ == 1) {
- new->lr[!bit] = *first;
- new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
- *first = new;
- return (char *)new->lr[bit];
- }
-
-
- w = *first;
- last = NULL;
- for (;;) {
- fbit = w->bitno;
- bitno = BITNO(w->bitno);
- if (bitno == cix)
- cerror("bitno == cix");
- if (bitno > cix)
- break;
- svbit = P_BIT(key, bitno);
- last = w;
- w = w->lr[svbit];
- if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
- break;
- }
-
- new->lr[!bit] = w;
- if (last == NULL) {
- *first = new;
- } else {
- last->lr[svbit] = new;
- last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
- }
- if (bitno < cix)
- new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
- return (char *)new->lr[bit];
-}
-
-static struct tree *sympole[NSTYPES];
-static struct symtab *tmpsyms[NSTYPES];
-int numsyms[NSTYPES];
-
-/*
- * Inserts a symbol into the symbol tree.
- * Returns a struct symtab.
- */
-struct symtab *
-lookup(char *key, int ttype)
-{
- struct symtab *sym;
- struct tree *w, *new, *last;
- int cix, bit, fbit, svbit, ix, bitno, match;
- int type, uselvl;
-
- long code = (long)key;
- type = ttype & SMASK;
- uselvl = (blevel > 0 && type != SSTRING);
-
- /*
- * The local symbols are kept in a simple linked list.
- * Check this list first.
- */
- if (blevel > 0)
- for (sym = tmpsyms[type]; sym; sym = sym->snext)
- if (sym->sname == key)
- return sym;
-
- switch (numsyms[type]) {
- case 0:
- if (ttype & SNOCREAT)
- return NULL;
- if (uselvl) {
- sym = getsymtab(key, ttype|STEMP);
- sym->snext = tmpsyms[type];
- tmpsyms[type] = sym;
- return sym;
- }
- sympole[type] = (struct tree *)getsymtab(key, ttype);
- numsyms[type]++;
- return (struct symtab *)sympole[type];
-
- case 1:
- w = (struct tree *)sympole[type];
- svbit = 0; /* XXX why? */
- break;
-
- default:
- w = sympole[type];
- for (;;) {
- bit = BITNO(w->bitno);
- fbit = (code >> bit) & 1;
- svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
- IS_LEFT_LEAF(w->bitno);
- w = w->lr[fbit];
- if (svbit)
- break;
- }
- }
-
- sym = (struct symtab *)w;
- match = (long)sym->sname;
-
- ix = code ^ match;
- if (ix == 0)
- return sym;
- else if (ttype & SNOCREAT)
- return NULL;
-
-#ifdef PCC_DEBUG
- if (ddebug)
- printf(" adding %s as %s at level %d\n",
- key, uselvl ? "temp" : "perm", blevel);
-#endif
-
- /*
- * Insert into the linked list, if feasible.
- */
- if (uselvl) {
- sym = getsymtab(key, ttype|STEMP);
- sym->snext = tmpsyms[type];
- tmpsyms[type] = sym;
- return sym;
- }
-
- /*
- * Need a new node. If type is SNORMAL and inside a function
- * the node must be allocated as permanent anyway.
- * This could be optimized by adding a remove routine, but it
- * may be more trouble than it is worth.
- */
- if (ttype == (STEMP|SNORMAL))
- ttype = SNORMAL;
-
- for (cix = 0; (ix & 1) == 0; ix >>= 1, cix++)
- ;
-
- new = ttype & STEMP ? tmpalloc(sizeof(struct tree)) :
- permalloc(sizeof(struct tree));
- bit = (code >> cix) & 1;
- new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
- new->lr[bit] = (struct tree *)getsymtab(key, ttype);
- if (numsyms[type]++ == 1) {
- new->lr[!bit] = sympole[type];
- new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
- sympole[type] = new;
- return (struct symtab *)new->lr[bit];
- }
-
-
- w = sympole[type];
- last = NULL;
- for (;;) {
- fbit = w->bitno;
- bitno = BITNO(w->bitno);
- if (bitno == cix)
- cerror("bitno == cix");
- if (bitno > cix)
- break;
- svbit = (code >> bitno) & 1;
- last = w;
- w = w->lr[svbit];
- if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
- break;
- }
-
- new->lr[!bit] = w;
- if (last == NULL) {
- sympole[type] = new;
- } else {
- last->lr[svbit] = new;
- last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
- }
- if (bitno < cix)
- new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
- return (struct symtab *)new->lr[bit];
-}
-
-void
-symclear(int level)
-{
- struct symtab *s;
- int i;
-
-#ifdef PCC_DEBUG
- if (ddebug)
- printf("symclear(%d)\n", level);
-#endif
- if (level < 1) {
- for (i = 0; i < NSTYPES; i++) {
- s = tmpsyms[i];
- tmpsyms[i] = 0;
- if (i != SLBLNAME)
- continue;
- while (s != NULL) {
- if (s->soffset < 0)
- uerror("label '%s' undefined",s->sname);
- s = s->snext;
- }
- }
- } else {
- for (i = 0; i < NSTYPES; i++) {
- if (i == SLBLNAME)
- continue; /* function scope */
- while (tmpsyms[i] != NULL &&
- tmpsyms[i]->slevel > level) {
- tmpsyms[i] = tmpsyms[i]->snext;
- }
- }
- }
-}
-
-struct symtab *
-hide(struct symtab *sym)
-{
- struct symtab *new;
-
- new = getsymtab(sym->sname, SNORMAL|STEMP);
- new->snext = tmpsyms[SNORMAL];
- tmpsyms[SNORMAL] = new;
-#ifdef PCC_DEBUG
- if (ddebug)
- printf("\t%s hidden at level %d (%p -> %p)\n",
- sym->sname, blevel, sym, new);
-#endif
- return new;
-}
--- usr.bin/pcc/cc/ccom/optim.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* $Id: optim.c,v 1.28 2006/07/11 07:54:29 ragge Exp $ */
-/*
- * 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 conditionsand 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 "pass1.h"
-
-# define SWAP(p,q) {sp=p; p=q; q=sp;}
-# define RCON(p) (p->n_right->n_op==ICON)
-# define RO(p) p->n_right->n_op
-# define RV(p) p->n_right->n_lval
-# define LCON(p) (p->n_left->n_op==ICON)
-# define LO(p) p->n_left->n_op
-# define LV(p) p->n_left->n_lval
-
-static int nncon(NODE *);
-
-int oflag = 0;
-
-/* remove left node */
-static NODE *
-zapleft(NODE *p)
-{
- NODE *q;
-
- q = p->n_left;
- nfree(p->n_right);
- nfree(p);
- return q;
-}
-
-/*
- * fortran function arguments
- */
-static NODE *
-fortarg(NODE *p)
-{
- if( p->n_op == CM ){
- p->n_left = fortarg( p->n_left );
- p->n_right = fortarg( p->n_right );
- return(p);
- }
-
- while( ISPTR(p->n_type) ){
- p = buildtree( UMUL, p, NIL );
- }
- return( optim(p) );
-}
-
- /* mapping relationals when the sides are reversed */
-short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
-
-/*
- * local optimizations, most of which are probably
- * machine independent
- */
-NODE *
-optim(NODE *p)
-{
- int o, ty;
- NODE *sp, *q;
- int i;
- TWORD t;
-
- if( (t=BTYPE(p->n_type))==ENUMTY || t==MOETY ) econvert(p);
- if( oflag ) return(p);
-
- ty = coptype(p->n_op);
- if( ty == LTYPE ) return(p);
-
- if( ty == BITYPE ) p->n_right = optim(p->n_right);
- p->n_left = optim(p->n_left);
-
- /* collect constants */
-again: o = p->n_op;
- switch(o){
-
- case SCONV:
- case PCONV:
- return( clocal(p) );
-
- case FORTCALL:
- p->n_right = fortarg( p->n_right );
- break;
-
- case ADDROF:
- if (LO(p) == TEMP)
- return p;
- if( LO(p) != NAME ) cerror( "& error" );
-
- if( !andable(p->n_left) ) return(p);
-
- LO(p) = ICON;
-
- setuleft:
- /* paint over the type of the left hand side with the type of the top */
- p->n_left->n_type = p->n_type;
- p->n_left->n_df = p->n_df;
- p->n_left->n_sue = p->n_sue;
- q = p->n_left;
- nfree(p);
- return q;
-
- case UMUL:
- if( LO(p) != ICON ) break;
- LO(p) = NAME;
- goto setuleft;
-
- case RS:
- if (LO(p) == RS && RCON(p->n_left) && RCON(p)) {
- /* two right-shift by constants */
- RV(p) += RV(p->n_left);
- p->n_left = zapleft(p->n_left);
- }
-#if 0
- else if (LO(p) == LS && RCON(p->n_left) && RCON(p)) {
- RV(p) -= RV(p->n_left);
- if (RV(p) < 0)
- o = p->n_op = LS, RV(p) = -RV(p);
- p->n_left = zapleft(p->n_left);
- }
-#endif
- if (RO(p) == ICON) {
- if (RV(p) < 0) {
- RV(p) = -RV(p);
- p->n_op = LS;
- goto again;
- }
-#ifdef notyet /* must check for side effects, --a >> 32; */
- if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue) &&
- ISUNSIGNED(p->n_type)) { /* ignore signed shifts */
- /* too many shifts */
- tfree(p->n_left);
- nfree(p->n_right);
- p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL;
- } else
-#endif
- /* avoid larger shifts than type size */
- if (RV(p) >= p->n_sue->suesize) {
- RV(p) = RV(p) % p->n_sue->suesize;
- werror("shift larger than type");
- }
- if (RV(p) == 0)
- p = zapleft(p);
- }
- break;
-
- case LS:
- if (LO(p) == LS && RCON(p->n_left) && RCON(p)) {
- /* two left-shift by constants */
- RV(p) += RV(p->n_left);
- p->n_left = zapleft(p->n_left);
- }
-#if 0
- else if (LO(p) == RS && RCON(p->n_left) && RCON(p)) {
- RV(p) -= RV(p->n_left);
- p->n_left = zapleft(p->n_left);
- }
-#endif
- if (RO(p) == ICON) {
- if (RV(p) < 0) {
- RV(p) = -RV(p);
- p->n_op = RS;
- goto again;
- }
-#ifdef notyet /* must check for side effects */
- if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue)) {
- /* too many shifts */
- tfree(p->n_left);
- nfree(p->n_right);
- p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL;
- } else
-#endif
- /* avoid larger shifts than type size */
- if (RV(p) >= p->n_sue->suesize) {
- RV(p) = RV(p) % p->n_sue->suesize;
- werror("shift larger than type");
- }
- if (RV(p) == 0)
- p = zapleft(p);
- }
- break;
-
- case MINUS:
- if (LCON(p) && RCON(p) && p->n_left->n_sp == p->n_right->n_sp) {
- /* link-time constants, but both are the same */
- /* solve it now by forgetting the symbols */
- p->n_left->n_sp = p->n_right->n_sp = NULL;
- }
- if( !nncon(p->n_right) ) break;
- RV(p) = -RV(p);
- o = p->n_op = PLUS;
-
- case MUL:
- case PLUS:
- case AND:
- case OR:
- case ER:
- /* commutative ops; for now, just collect constants */
- /* someday, do it right */
- if( nncon(p->n_left) || ( LCON(p) && !RCON(p) ) )
- SWAP( p->n_left, p->n_right );
- /* make ops tower to the left, not the right */
- if( RO(p) == o ){
- NODE *t1, *t2, *t3;
- t1 = p->n_left;
- sp = p->n_right;
- t2 = sp->n_left;
- t3 = sp->n_right;
- /* now, put together again */
- p->n_left = sp;
- sp->n_left = t1;
- sp->n_right = t2;
- p->n_right = t3;
- }
- if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->n_left) &&
- conval(p->n_right, MINUS, p->n_left->n_right)){
- zapleft:
-
- q = p->n_left->n_left;
- nfree(p->n_left->n_right);
- nfree(p->n_left);
- p->n_left = q;
- }
- if( RCON(p) && LO(p)==o && RCON(p->n_left) &&
- conval( p->n_right, o, p->n_left->n_right ) ){
- goto zapleft;
- }
- else if( LCON(p) && RCON(p) && conval( p->n_left, o, p->n_right ) ){
- zapright:
- nfree(p->n_right);
- q = makety(p->n_left, p->n_type, p->n_qual,
- p->n_df, p->n_sue);
- nfree(p);
- return clocal(q);
- }
-
- /* change muls to shifts */
-
- if( o == MUL && nncon(p->n_right) && (i=ispow2(RV(p)))>=0){
- if( i == 0 ) { /* multiplication by 1 */
- goto zapright;
- }
- o = p->n_op = LS;
- p->n_right->n_type = INT;
- p->n_right->n_df = NULL;
- RV(p) = i;
- }
-
- /* change +'s of negative consts back to - */
- if( o==PLUS && nncon(p->n_right) && RV(p)<0 ){
- RV(p) = -RV(p);
- o = p->n_op = MINUS;
- }
-
- /* remove ops with RHS 0 */
- if ((o == PLUS || o == MINUS || o == OR || o == ER) &&
- nncon(p->n_right) && RV(p) == 0) {
- goto zapright;
- }
- break;
-
- case DIV:
- if( nncon( p->n_right ) && p->n_right->n_lval == 1 )
- goto zapright;
- if (LCON(p) && RCON(p) && conval(p->n_left, DIV, p->n_right))
- goto zapright;
- if (RCON(p) && ISUNSIGNED(p->n_type) && (i=ispow2(RV(p))) > 0) {
- p->n_op = RS;
- RV(p) = i;
- q = p->n_right;
- if(tsize(q->n_type, q->n_df, q->n_sue) > SZINT)
- p->n_right = makety(q, INT, 0, 0, MKSUE(INT));
-
- break;
- }
- break;
-
- case MOD:
- if (RCON(p) && ISUNSIGNED(p->n_type) && ispow2(RV(p)) > 0) {
- p->n_op = AND;
- RV(p) = RV(p) -1;
- break;
- }
- break;
-
- case EQ:
- case NE:
- case LT:
- case LE:
- case GT:
- case GE:
- case ULT:
- case ULE:
- case UGT:
- case UGE:
- if( !LCON(p) ) break;
-
- /* exchange operands */
-
- sp = p->n_left;
- p->n_left = p->n_right;
- p->n_right = sp;
- p->n_op = revrel[p->n_op - EQ ];
- break;
-
- }
-
- return(p);
- }
-
-int
-ispow2(CONSZ c)
-{
- int i;
- if( c <= 0 || (c&(c-1)) ) return(-1);
- for( i=0; c>1; ++i) c >>= 1;
- return(i);
-}
-
-int
-nncon( p ) NODE *p; {
- /* is p a constant without a name */
- return( p->n_op == ICON && p->n_sp == NULL );
- }
--- usr.bin/pcc/cc/ccom/Makefile
+++ /dev/null
@@ -1,114 +0,0 @@
-# $Id: Makefile.in,v 1.11 2007/09/26 14:48:49 ragge Exp $
-#
-# Makefile.in for ccom
-#
-XFL=-DPCC_DEBUG -DGCC_COMPAT \
- -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
-
-CC = gcc
-CFLAGS = -g $(XFL) -I. -I${MIPDIR} -I$(MDIR) -Dmach_${TARGMACH} \
- -I../../os/${TARGOS}
-CPPFLAGS =
-LIBS =
-LDFLAGS =
-LEX = flex
-YACC = yacc
-TARGOS = midnightbsd
-TARGMACH = x86
-prefix = /usr/local
-exec_prefix = ${prefix}
-libexecdir = ${exec_prefix}/libexec
-datarootdir = ${prefix}/share
-mandir = ${datarootdir}/man
-strip = yes
-INSTALL = /usr/bin/install -c
-INSTALL_PROGRAM = ${INSTALL}
-
-MDIR=../../arch/$(TARGMACH)
-MIPDIR=../../mip
-
-OBJS1=optim.o pftn.o scan.o trees.o cgram.o inline.o symtabs.o \
- gcc_compat.o init.o local.o code.o stabs.o
-
-OBJS2=match.o reader.o optim2.o regs.o local2.o order.o table.o
-
-OBJS=$(OBJS1) $(OBJS2) compat.o common.o main.o external.o
-
-DEST=ccom
-
-all: ${DEST}
-
-${DEST}: $(OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
-
-.c.o:
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
-
-local.o: $(MDIR)/local.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local.c
-
-local2.o: $(MDIR)/local2.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local2.c
-
-code.o: $(MDIR)/code.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/code.c
-
-order.o: $(MDIR)/order.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/order.c
-
-table.o: $(MDIR)/table.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/table.c
-
-match.o: $(MIPDIR)/match.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/match.c
-
-reader.o: $(MIPDIR)/reader.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/reader.c
-
-optim2.o: $(MIPDIR)/optim2.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/optim2.c
-
-regs.o: $(MIPDIR)/regs.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/regs.c
-
-common.o: $(MIPDIR)/common.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/common.c
-
-compat.o: $(MIPDIR)/compat.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c
-
-external.h external.c: ${MIPDIR}/mkext.c $(MDIR)/table.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -DMKEXT -o mkext ${MIPDIR}/mkext.c \
- $(MDIR)/table.c ${MIPDIR}/common.c
- ./mkext
-
-trees.c: pass2.h
-
-pass2.h: external.h
-
-cgram.c: cgram.y
- $(YACC) $(YFLAGS) -d $<
- mv y.tab.c cgram.c
- mv y.tab.h cgram.h
-
-scan.c: scan.l cgram.c
- $(LEX) $(LFLAGS) $<
- mv lex.yy.c scan.c
-
-optim2.o reader.o: external.h
-
-install:
- test -z "${DESTDIR}$(libexecdir)" || mkdir -p "${DESTDIR}$(libexecdir)"
- ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${libexecdir}
- @if [ ${strip} = yes ]; then \
- strip ${DESTDIR}${libexecdir}/${DEST} ; \
- echo strip ${DESTDIR}${libexecdir}/${DEST} ; \
- fi
- test -z "${DESTDIR}$(mandir)/man1" || mkdir -p "${DESTDIR}$(mandir)/man1"
- ${INSTALL} ${DEST}.1 ${DESTDIR}${mandir}/man1/
-
-clean:
- /bin/rm -f $(OBJS) ccom scan.c cgram.[ch] mkext external.[ch]
-
-distclean: clean
- /bin/rm -f Makefile
--- usr.bin/pcc/cc/cpp/scanner.l
+++ /dev/null
@@ -1,814 +0,0 @@
-%{
-/* $Id: scanner.l,v 1.20 2007/09/25 20:41:07 ragge Exp $ */
-
-/*
- * 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 "cpp.h"
-#include "y.tab.h"
-%}
-
-%{
-static long long cvtdig(int rad);
-static int charcon(void);
-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 linestmt(void);
-static void storepb(void);
-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 32768
-#define YY_INPUT(b,r,m) (r = yyinput(b, m))
-#define fprintf(x, ...) error(__VA_ARGS__)
-#define ECHO putstr((usch *)yytext)
-#undef fileno
-#define fileno(x) 0
-
-#if YY_FLEX_SUBMINOR_VERSION >= 31
-/* Hack to avoid unneccessary 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((usch *)yytext);
-%}
-
-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
-
-%%
-
-"\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>"==" { 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})* {
- if (gotdef) {
- yylval.val =
- lookup((usch *)yytext, FIND) != 0;
- gotdef = 0;
- return IDENT;
- }
- yylval.val = 0;
- return NUMBER;
- }
-
-[1-9][0-9]* { if (slow && !YYSTATE) return IDENT; scale = 10; goto num; }
-
-0[xX]{H}+{IS}? { scale = 16;
- num: if (YYSTATE)
- yylval.val = cvtdig(scale);
- PRTOUT(NUMBER);
- }
-0{D}+{IS}? { scale = 8; goto num; }
-{D}+{IS}? { scale = 10; goto num; }
-L?'(\\.|[^\\'])+' { if (YYSTATE)
- yylval.val = charcon();
- PRTOUT(NUMBER);
- }
-
-<IFR>. { return yytext[0]; }
-
-{D}+{E}{FS}? { PRTOUT(FPOINT); }
-{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); }
-{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); }
-
-^{WS}*#{WS}* { 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(); }
-<CONTR>"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; }
-
-
-
-"//".*$ { /* if (tflag) yyless(..) */
- if (Cflag)
- putstr((usch *)yytext);
- else if (!flslvl)
- putch(' ');
- }
-"/*" { int c, wrn;
- if (Cflag)
- putstr((usch *)yytext);
- wrn = 0;
- more: while ((c = input()) && c != '*') {
- if (c == '\n')
- putch(c), ifiles->lineno++;
- else if (c == 1) /* WARN */
- wrn = 1;
- else if (Cflag)
- putch(c);
- }
- if (c == 0)
- return 0;
- if (Cflag)
- putch(c);
- if ((c = input()) && c != '/') {
- if (Cflag)
- putch('*');
- unput(c);
- goto more;
- }
- if (Cflag)
- 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((usch *)yytext, FIND)) != 0) {
- usch *op = stringbuf;
- putstr(gotident(nl));
- stringbuf = op;
- } else
- putstr((usch *)yytext);
- xx: ;
- }
-
-. { PRTOUT(yytext[0]); }
-
-%%
-
-usch *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 */
- if ((c = inpch()) == '\n') {
- ifiles->lineno++;
- putch('\n');
- goto again;
- }
- 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 on failure to open file.
- */
-int
-pushfile(usch *file)
-{
- extern struct initar *initar;
- struct includ ibuf;
- struct includ *old;
- struct includ *ic;
- int c, otrulvl;
-
- ic = &ibuf;
- old = ifiles;
-
- slow = 0;
- if (file != NULL) {
- if ((ic->infil = open((char *)file, O_RDONLY)) < 0)
- return -1;
- ic->orgfn = ic->fname = file;
- } else {
- ic->infil = 0;
- ic->orgfn = ic->fname = (usch *)"<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 = old;
- close(ic->infil);
- return 0;
-}
-
-/*
- * Print current position to output file.
- */
-void
-prtline()
-{
- usch *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
- 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, 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 some string numbers to long long.
- * Do not care about UL trailers, should we?
- */
-static long long
-cvtdig(int rad)
-{
- long long rv = 0;
- char *y = yytext;
- int c;
-
- c = *y++;
- if (rad == 16)
- y++;
- while (isxdigit(c)) {
- rv = rv * rad + dig2num(c);
- c = *y++;
- }
- return rv;
-}
-
-static int
-charcon(void)
-{
- usch *p = (usch *)yytext;
- int val, c;
-
- if (*p == 'L')
- p++;
- p++; /* 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(void)
-{
- int t;
-
- while ((t = yylex()) == WSPACE)
- ;
- if (t != '\n')
- error("newline expected, got %d", t);
-}
-
-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();
-}
-
-static void
-ifdefstmt(void)
-{
- if (flslvl) {
- /* just ignore the rest of the line */
- while (input() != '\n')
- ;
- unput('\n');
- yylex();
- flslvl++;
- return;
- }
- slow = 1;
- if (yylex() != WSPACE || yylex() != IDENT)
- error("bad ifdef");
- slow = 0;
- if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0)
- trulvl++;
- else
- flslvl++;
- chknl();
-}
-
-static void
-ifndefstmt(void)
-{
- slow = 1;
- if (yylex() != WSPACE || yylex() != IDENT)
- error("bad ifndef");
- slow = 0;
- if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0)
- trulvl++;
- else
- flslvl++;
- chknl();
-}
-
-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();
-}
-
-/*
- * Note! Ugly!
- * Walk over the string s and search for defined, and replace it with
- * spaces and a 1 or 0.
- */
-static void
-fixdefined(usch *s)
-{
- usch *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)
-{
- usch *opb = stringbuf;
- int c;
-
- while ((c = input()) != '\n')
- 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 usch *
-svinp(void)
-{
- int c;
- usch *cp = stringbuf;
-
- while ((c = input()) && c != '\n')
- savch(c);
- savch('\n');
- savch(0);
- BEGIN 0;
- return cp;
-}
-
-static void
-cpperror(void)
-{
- usch *cp;
- int c;
-
- if (flslvl)
- return;
- c = yylex();
- if (c != WSPACE && c != '\n')
- error("bad error");
- cp = svinp();
- if (flslvl)
- stringbuf = cp;
- else
- error("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((usch *)yytext, FIND)))
- np->value = 0;
- slow = 0;
- chknl();
-}
-
-static void
-pragmastmt(void)
-{
- int c;
-
- slow = 1;
- if (yylex() != WSPACE)
- error("bad pragma");
- putstr((usch *)"#pragma ");
- do {
- putch(c = input()); /* Do arg expansion instead? */
- } while (c && c != '\n');
- ifiles->lineno++;
- prtline();
- slow = 0;
-}
--- usr.bin/pcc/cc/cpp/token.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/* $Id: token.c,v 1.11 2006/09/28 11:10:08 ragge Exp $ */
-
-/*
- * 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 "cpp.h"
-
-/* definition for include file info */
-struct includ {
- struct includ *next;
- char *fname;
- int lineno;
- int infil;
- usch *curptr;
- usch *maxread;
- usch *ostr;
- usch *buffer;
- usch bbuf[NAMEMAX+CPPBUF+1];
-} *ifiles;
-
-usch *yyp, *yystr, yybuf[CPPBUF];
-
-int yylex(void);
-int yywrap(void);
-
-static struct includ *
-getbuf(usch *file)
-{
- struct includ *ic;
- usch *ostr = stringbuf;
-
- stringbuf = (usch *)ROUND((int)stringbuf);
- ic = (struct includ *)stringbuf;
- stringbuf += sizeof(struct includ);
- ic->ostr = ostr;
-
- return ic;
-}
-
-static void
-putbuf(struct includ *ic)
-{
-if (stringbuf < (usch *)&ic[1])
-;
-else
- stringbuf = ic->ostr;
-}
-
-static int
-input(void)
-{
- struct includ *ic;
- int len;
-
- if (ifiles->curptr < ifiles->maxread)
- return *ifiles->curptr++;
-
- if (ifiles->infil < 0) {
- ic = ifiles;
- ifiles = ifiles->next;
- putbuf(ic);
- return input();
- }
- if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
- error("read error on file %s", ifiles->fname);
- if (len == 0)
- return -1;
- ifiles->curptr = ifiles->buffer;
- ifiles->maxread = ifiles->buffer + len;
- return input();
-}
-
-static void
-unput(int c)
-{
- struct includ *ic;
-
- if (ifiles->curptr > ifiles->bbuf) {
- *--ifiles->curptr = c;
- } else {
- ic = getbuf(NULL);
- ic->fname = ifiles->fname;
- ic->lineno = ifiles->lineno;
- ic->infil = -1;
- ic->curptr = &ic->bbuf[NAMEMAX+CPPBUF+1];
- ic->maxread = ic->curptr;
- ic->next = ifiles;
- ifiles = ic;
- *--ifiles->curptr = c;
- }
-}
-
-#define UNPUT(c) *--ifiles->curptr = c
-
-static int
-slofgetc(void)
-{
- int c;
-
-again: switch (c = input()) {
- case '\\': /* continued lines */
- if ((c = input()) == '\n') {
- ifiles->lineno++;
- putc('\n', obuf);
- goto again;
- }
- cunput(c);
- return '\\';
- case '?': /* trigraphs */
- if ((c = input()) != '?') {
- cunput(c);
- return '?';
- }
- switch (c = input()) {
- 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:
- cunput(c);
- cunput('?');
- return '?';
- }
- cunput(c);
- goto again;
- default:
- return c;
- }
-}
-
-int
-yylex()
-{
- static int wasnl = 1;
- int c, oc, rval;
-
-fast: yystr = yybuf;
- yyp = yystr;
- c = input();
- if (c != ' ' && c != '\t' && c != '#')
- wasnl = 0;
-#define ONEMORE() { *yyp++ = c; c = slofgetc(); }
-again: switch (c) {
- case -1:
- rval = 0;
- break;
-
- case '\'': /* charcon */
- case '"': /* string */
-chstr: oc = c;
- if (slow == 0) {
- do {
- putch(c);
- if (c == '\\')
- putch(slofgetc());
- } while ((c = slofgetc()) != EOF && c != oc);
- if (c == oc)
- putch(c);
- goto fast;
- } else {
- do {
- *yyp++ = c;
- if (c == '\\')
- *yyp++ = slofgetc();
- } while ((c = slofgetc()) != EOF && c != oc);
- *yyp++ = c; *yyp = 0;
- }
- rval = oc == '"' ? STRING : CHARCON;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- *yyp++ = c;
- c = slofgetc();
- if (yyp[-1] == '0' && (c == 'x' || c == 'X')) {
- do {
- ONEMORE();
- } while (isxdigit(c));
- } else {
- while (isdigit(c))
- ONEMORE();
- }
- if (c != '.' && c != 'e' && c != 'E') {
- /* not floating point number */
- while (c == 'l' || c == 'L' || c == 'u' || c == 'U') {
- ONEMORE();
- }
- cunput(c);
- *yyp = 0;
- rval = NUMBER;
- break;
- }
- /* it's a floating point number here */
- if (c == '.') { /* decimal point */
-F: do { /* may be followed by digits */
- ONEMORE();
- } while (isdigit(c));
- if (c == 'e' || c == 'E') {
-E: ONEMORE();
- if (c == '-' || c == '+') {
- ONEMORE();
- }
- while (isdigit(c))
- ONEMORE();
- }
- if (c == 'f' || c == 'F' || c == 'l' || c == 'L')
- ONEMORE();
- cunput(c);
- *yyp = 0;
- rval = FPOINT;
- break;
- } else
- goto E;
-
- case '.':
- ONEMORE();
- if (isdigit(c))
- goto F;
- if (!slow) {
- UNPUT(c);
- putch('.');
- goto fast;
- }
- if (c == '.') {
- ONEMORE();
- if (c == '.') {
- *yyp++ = '.'; *yyp = 0;
- rval = ELLIPS;
- break;
- }
- cunput(c);
- cunput('.');
- *--yyp = 0;
- rval = '.';
- break;
- }
- cunput(c);
- *yyp = 0;
- rval = '.';
- break;
-
- case '\\':
- c = input();
- if (c == '\n') {
- ifiles->lineno++;
- putch('\n');
- goto fast;
- }
- if (!slow) {
- putch('\\');
- goto again;
- }
- UNPUT(c);
- *yyp++ = '\\'; *yyp = 0;
- rval = '\\';
- break;
-
- case '\n':
- wasnl = 1;
- ifiles->lineno++;
- rval = NL;
- if (slow)
- break;
- if (flslvl == 0) {
- if (curline() == 1)
- prtline();
- else
- putch('\n');
- }
- goto fast;
-
- case '#':
- if (wasnl) {
- wasnl = 0;
- rval = CONTROL;
- break;
- }
- if (!slow) {
- putch('#');
- goto fast;
- }
- *yyp++ = c;
- c = input();
- if (c == '#') {
- *yyp++ = c;
- *yyp = 0;
- rval = CONCAT;
- } else {
- unput(c);
- *yyp = 0;
- rval = MKSTR;
- }
- break;
-
- case ' ':
- case '\t': /* whitespace */
- do {
- *yyp++ = c;
- c = input();
- } while (c == ' ' || c == '\t');
- if (wasnl && c == '#') {
- wasnl = 0;
- rval = CONTROL;
- } else {
- unput(c);
- *yyp = 0;
- rval = WSPACE;
- }
- break;
-
- case '/':
- if ((c = slofgetc()) == '/') {
- if (Cflag)
- fprintf(obuf, "//");
- while ((c = slofgetc()) && c != '\n')
- if (Cflag)
- putc(c, obuf);
- goto again;
- } else if (c == '*') {
- if (Cflag)
- fprintf(obuf, "/*");
- oc = 0;
- do {
- while ((c = slofgetc()) && c != '*') {
- if (c == '\n') {
- putc(c, obuf);
- ifiles->lineno++;
- } else if (Cflag)
- putc(c, obuf);
- }
- if (Cflag)
- putc(c, obuf);
- if ((c = slofgetc()) == '/')
- break;
- unput(c);
- } while (c);
- if (Cflag)
- putc(c, obuf);
- if (tflag) {
- rval = yylex();
- } else {
- *yyp++ = ' '; *yyp = 0;
- rval = WSPACE;
- }
- } else {
- unput(c);
- *yyp++ = '/'; *yyp = 0;
- rval = '/';
- }
- break;
-
- case 'L': /* may be STRING, CHARCON or identifier */
- *yyp++ = c;
- if ((c = slofgetc()) == '"' || c == '\'')
- goto chstr;
-gotid: while (isalnum(c) || c == '_') {
- *yyp++ = c;
- c = slofgetc();
- }
- *yyp = 0;
- unput(c);
- rval = IDENT;
- break;
-
- default:
- if (isalpha(c) || c == '_')
- goto gotid;
- if (!slow && c > 5) {
- putch(c);
- goto fast;
- }
- yystr[0] = c; yystr[1] = 0;
- rval = c;
- break;
- }
- return rval;
-}
-
-/*
- * A new file included.
- * If ifiles == NULL, this is the first file and already opened (stdin).
- * Return 0 on success, -1 on failure to open file.
- */
-int
-pushfile(char *file)
-{
- struct includ ibuf;
- struct includ *old;
- struct includ *ic;
-
- ic = &ibuf;
- old = ifiles;
-
- slow = 0;
- if (file != NULL) {
- if ((ic->infil = open(file, O_RDONLY)) < 0)
- return -1;
- ic->fname = file;
- } else {
- ic->infil = 0;
- ic->fname = "<stdin>";
- }
- ic->buffer = ic->bbuf+NAMEMAX;
- ic->curptr = ic->buffer;
- ifiles = ic;
- ic->lineno = 0;
- ic->maxread = ic->curptr;
- unput('\n');
-
- mainscan();
-
- if (trulvl || flslvl)
- error("unterminated conditional");
-
- ifiles = old;
- close(ic->infil);
- return 0;
-}
-
-/*
- * Print current position to output file.
- */
-void
-prtline()
-{
- fprintf(obuf, "# %d \"%s\"\n", ifiles->lineno, ifiles->fname);
-}
-
-void
-cunput(int c)
-{
-extern int dflag;
-if (dflag)printf(": '%c'(%d)", c, c);
- unput(c);
-}
-
-void
-setline(int line)
-{
- if (ifiles)
- ifiles->lineno = line-1;
-}
-
-void
-setfile(char *name)
-{
- if (ifiles)
- ifiles->fname = strdup(name);
-}
-
-int
-curline()
-{
- return ifiles ? ifiles->lineno : 0;
-}
-
-char *
-curfile()
-{
- return ifiles ? ifiles->fname : "";
-}
--- usr.bin/pcc/cc/cpp/cpp.c
+++ /dev/null
@@ -1,1482 +0,0 @@
-/* $Id: cpp.c,v 1.65 2007/09/25 20:41:08 ragge Exp $ */
-
-/*
- * Copyright (c) 2004 Anders Magnusson (ragge at 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.
- */
-/*
- * The C preprocessor.
- * This code originates from the V6 preprocessor with some additions
- * from V7 cpp, and at last ansi/c99 support.
- */
-
-#include "../../config.h"
-
-#include <sys/wait.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-#include "cpp.h"
-#include "y.tab.h"
-
-#define MAXARG 250 /* # of args to a macro, limited by char value */
-#define SBSIZE 600000
-
-static usch sbf[SBSIZE];
-/* C command */
-
-int tflag; /* traditional cpp syntax */
-#ifdef CPP_DEBUG
-int dflag; /* debug printouts */
-#define DPRINT(x) if (dflag) printf x
-#define DDPRINT(x) if (dflag > 1) printf x
-#else
-#define DPRINT(x)
-#define DDPRINT(x)
-#endif
-
-int ofd;
-usch outbuf[CPPBUF];
-int obufp, istty;
-int Cflag, Mflag, dMflag;
-usch *Mfile;
-struct initar *initar;
-
-/* avoid recursion */
-struct recur {
- struct recur *next;
- struct symtab *sp;
-};
-
-/* include dirs */
-struct incs {
- struct incs *next;
- usch *dir;
-} *incdir[2];
-#define INCINC 0
-#define SYSINC 1
-
-static struct symtab *filloc;
-static struct symtab *linloc;
-static struct symtab *pragloc;
-int trulvl;
-int flslvl;
-int elflvl;
-int elslvl;
-usch *stringbuf = sbf;
-
-/*
- * Macro replacement list syntax:
- * - For object-type macros, replacement strings are stored as-is.
- * - For function-type macros, macro args are substituted for the
- * character WARN followed by the argument number.
- * - The value element points to the end of the string, to simplify
- * pushback onto the input queue.
- *
- * The first character (from the end) in the replacement list is
- * the number of arguments:
- * VARG - ends with ellipsis, next char is argcount without ellips.
- * OBJCT - object-type macro
- * 0 - empty parenthesis, foo()
- * 1-> - number of args.
- */
-
-#define VARG 0xfe /* has varargs */
-#define OBJCT 0xff
-#define WARN 1 /* SOH, not legal char */
-#define CONC 2 /* STX, not legal char */
-#define SNUFF 3 /* ETX, not legal char */
-#define NOEXP 4 /* EOT, not legal char */
-#define EXPAND 5 /* ENQ, not legal char */
-
-/* args for lookup() */
-#define FIND 0
-#define ENTER 1
-
-static void expdef(usch *proto, struct recur *, int gotwarn);
-void define(void);
-static int canexpand(struct recur *, struct symtab *np);
-void include(void);
-void line(void);
-void flbuf(void);
-void usage(void);
-
-int
-main(int argc, char **argv)
-{
- struct initar *it;
- struct incs *w, *w2;
- struct symtab *nl;
- register int ch;
-
- while ((ch = getopt(argc, argv, "CD:I:MS:U:d:i:tvV?")) != -1)
- switch (ch) {
- case 'C': /* Do not discard comments */
- Cflag++;
- break;
-
- case 'i': /* include */
- case 'U': /* undef */
- case 'D': /* define something */
- /* XXX should not need malloc() here */
- if ((it = malloc(sizeof(struct initar))) == NULL)
- error("couldn't apply -%c %s", ch, optarg);
- it->type = ch;
- it->str = optarg;
- it->next = initar;
- initar = it;
- break;
-
- case 'M': /* Generate dependencies for make */
- Mflag++;
- break;
-
- case 'S':
- case 'I':
- if ((w = calloc(sizeof(struct incs), 1)) == NULL)
- error("couldn't apply -%c %s", ch, optarg);
- w->dir = (usch *)optarg;
- w2 = incdir[ch == 'I' ? INCINC : SYSINC];
- if (w2 != NULL) {
- while (w2->next)
- w2 = w2->next;
- w2->next = w;
- } else
- incdir[ch == 'I' ? INCINC : SYSINC] = w;
- break;
-
-#ifdef CPP_DEBUG
- case 'V':
- dflag++;
- break;
-#endif
- case 'v':
- printf("cpp: %s\n", VERSSTR);
- break;
- case 'd':
- if (optarg[0] == 'M') {
- dMflag = 1;
- Mflag = 1;
- }
- /* ignore others */
- break;
-
- case 't':
- tflag = 1;
- break;
-
- case '?':
- usage();
- default:
- error("bad arg %c\n", ch);
- }
- argc -= optind;
- argv += optind;
-
- filloc = lookup((usch *)"__FILE__", ENTER);
- linloc = lookup((usch *)"__LINE__", ENTER);
- pragloc = lookup((usch *)"_Pragma", ENTER);
- filloc->value = linloc->value = (usch *)""; /* Just something */
- pragloc->value = (usch *)"";
-
- if (tflag == 0) {
- time_t t = time(NULL);
- usch *n = (usch *)ctime(&t);
-
- /*
- * Manually move in the predefined macros.
- */
- nl = lookup((usch *)"__TIME__", ENTER);
- savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"');
- savch(OBJCT);
- nl->value = stringbuf-1;
-
- nl = lookup((usch *)"__DATE__", ENTER);
- savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]);
- savstr(&n[20]); savch('"'); savch(OBJCT);
- nl->value = stringbuf-1;
-
- nl = lookup((usch *)"__STDC__", ENTER);
- savch(0); savch('1'); savch(OBJCT);
- nl->value = stringbuf-1;
- }
-
- if (Mflag && !dMflag) {
- usch *c;
-
- if (argc < 1)
- error("-M and no infile");
- if ((c = (usch *)strrchr(argv[0], '/')) == NULL)
- c = (usch *)argv[0];
- else
- c++;
- Mfile = stringbuf;
- savstr(c); savch(0);
- if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL)
- error("-M and no extension: ");
- c[1] = 'o';
- c[2] = 0;
- }
-
- if (argc == 2) {
- if ((ofd = open(argv[1], O_WRONLY|O_CREAT, 0600)) < 0)
- error("Can't creat %s", argv[1]);
- } else
- ofd = 1; /* stdout */
- istty = isatty(ofd);
-
- if (pushfile((usch *)(argc && strcmp(argv[0], "-") ? argv[0] : NULL)))
- error("cannot open %s", argv[0]);
-
- flbuf();
- close(ofd);
- return 0;
-}
-
-/*
- * Expand the symbol nl read from input.
- * Return a pointer to the fully expanded result.
- * It is the responsibility of the caller to reset the heap usage.
- */
-usch *
-gotident(struct symtab *nl)
-{
- struct symtab *thisnl;
- usch *osp, *ss2, *base;
- int c;
-
- thisnl = NULL;
- slow = 1;
- base = osp = stringbuf;
- goto found;
-
- while ((c = yylex()) != 0) {
- switch (c) {
- case IDENT:
- if (flslvl)
- break;
- osp = stringbuf;
-
- DPRINT(("IDENT0: %s\n", yytext));
- nl = lookup((usch *)yytext, FIND);
- if (nl == 0 || thisnl == 0)
- goto found;
- if (thisnl == nl) {
- nl = 0;
- goto found;
- }
- ss2 = stringbuf;
- if ((c = yylex()) == WSPACE) {
- savstr((usch *)yytext);
- c = yylex();
- }
- if (c != EXPAND) {
- unpstr((usch *)yytext);
- if (ss2 != stringbuf)
- unpstr(ss2);
- unpstr(nl->namep);
- (void)yylex(); /* get yytext correct */
- nl = 0; /* ignore */
- } else {
- thisnl = NULL;
- if (nl->value[0] == OBJCT) {
- unpstr(nl->namep);
- (void)yylex(); /* get yytext correct */
- nl = 0;
- }
- }
- stringbuf = ss2;
-
-found: if (nl == 0 || subst(nl, NULL) == 0) {
- if (nl)
- savstr(nl->namep);
- else
- savstr((usch *)yytext);
- } else if (osp != stringbuf) {
- DPRINT(("IDENT1: unput osp %p stringbuf %p\n",
- osp, stringbuf));
- ss2 = stringbuf;
- cunput(EXPAND);
- while (ss2 > osp)
- cunput(*--ss2);
- thisnl = nl;
- stringbuf = osp; /* clean up heap */
- }
- break;
-
- case EXPAND:
- DPRINT(("EXPAND!\n"));
- thisnl = NULL;
- break;
-
- case STRING:
- case '\n':
- case NUMBER:
- case FPOINT:
- case WSPACE:
- savstr((usch *)yytext);
- break;
-
- default:
- if (c < 256)
- savch(c);
- else
- savstr((usch *)yytext);
- break;
- }
- if (thisnl == NULL) {
- slow = 0;
- savch(0);
- return base;
- }
- }
- error("preamture EOF");
- /* NOTREACHED */
- return NULL; /* XXX gcc */
-}
-
-void
-line()
-{
- static usch *lbuf;
- static int llen;
- int c;
-
- slow = 1;
- if (yylex() != WSPACE)
- goto bad;
- if ((c = yylex()) != IDENT || !isdigit((int)yytext[0]))
- goto bad;
- ifiles->lineno = atoi(yytext);
-
- if ((c = yylex()) != '\n' && c != WSPACE)
- goto bad;
- if (c == '\n') {
- slow = 0;
- return;
- }
- if (yylex() != STRING)
- goto bad;
- c = strlen((char *)yytext);
- if (llen < c) {
- /* XXX may loose heap space */
- lbuf = stringbuf;
- stringbuf += c;
- llen = c;
- }
- yytext[strlen(yytext)-1] = 0;
- if (strlcpy((char *)lbuf, &yytext[1], SBSIZE) >= SBSIZE)
- error("line exceeded buffer size");
-
- ifiles->fname = lbuf;
- if (yylex() != '\n')
- goto bad;
- slow = 0;
- return;
-
-bad: error("bad line directive");
-}
-
-/*
- * Include a file. Include order:
- * - For <...> files, first search -I directories, then system directories.
- * - For "..." files, first search "current" dir, then as <...> files.
- */
-void
-include()
-{
- struct incs *w;
- struct symtab *nl;
- usch *osp;
- usch *fn, *safefn;
- int i, c, it;
-
- if (flslvl)
- return;
- osp = stringbuf;
- slow = 1;
-again:
- if ((c = yylex()) == WSPACE)
- c = yylex();
- if (c != STRING && c != '<' && c != IDENT)
- goto bad;
-
- if (c == IDENT) {
- if ((nl = lookup((usch *)yytext, FIND)) == NULL)
- goto bad;
- if (subst(nl, NULL) == 0)
- goto bad;
- savch('\0');
- unpstr(osp);
- goto again;
- } else if (c == '<') {
- fn = stringbuf;
- while ((c = yylex()) != '>' && c != '\n') {
- if (c == '\n')
- goto bad;
- savstr((usch *)yytext);
- }
- savch('\0');
- while ((c = yylex()) == WSPACE)
- ;
- if (c != '\n')
- goto bad;
- it = SYSINC;
- safefn = fn;
- } else {
- usch *nm = stringbuf;
-
- yytext[strlen(yytext)-1] = 0;
- fn = (usch *)&yytext[1];
- /* first try to open file relative to previous file */
- /* but only if it is not an absolute path */
- if (*fn != '/') {
- savstr(ifiles->orgfn);
- if ((stringbuf =
- (usch *)strrchr((char *)nm, '/')) == NULL)
- stringbuf = nm;
- else
- stringbuf++;
- }
- safefn = stringbuf;
- savstr(fn); savch(0);
- while ((c = yylex()) == WSPACE)
- ;
- if (c != '\n')
- goto bad;
- slow = 0;
- if (pushfile(nm) == 0)
- return;
- /* XXX may loose stringbuf space */
- }
-
- /* create search path and try to open file */
- slow = 0;
- for (i = 0; i < 2; i++) {
- for (w = incdir[i]; w; w = w->next) {
- usch *nm = stringbuf;
-
- savstr(w->dir); savch('/');
- savstr(safefn); savch(0);
- if (pushfile(nm) == 0)
- return;
- stringbuf = nm;
- }
- }
- error("cannot find '%s'", safefn);
- /* error() do not return */
-
-bad: error("bad include");
- /* error() do not return */
-}
-
-static int
-definp(void)
-{
- int c;
-
- do
- c = yylex();
- while (c == WSPACE);
- return c;
-}
-
-void
-define()
-{
- struct symtab *np;
- usch *args[MAXARG], *ubuf, *sbeg;
- int c, i, redef;
- int mkstr = 0, narg = -1;
- int ellips = 0;
- int len;
-
- if (flslvl)
- return;
- slow = 1;
- if (yylex() != WSPACE || yylex() != IDENT)
- goto bad;
-
- if (isdigit((int)yytext[0]))
- goto bad;
-
- np = lookup((usch *)yytext, ENTER);
- redef = np->value != NULL;
-
- sbeg = stringbuf;
- if ((c = yylex()) == '(') {
- narg = 0;
- /* function-like macros, deal with identifiers */
- for (;;) {
- c = definp();
- if (c == ')')
- break;
- if (c == ELLIPS) {
- ellips = 1;
- if (definp() != ')')
- goto bad;
- break;
- }
- if (c == IDENT) {
- len = strlen(yytext);
- args[narg] = alloca(len+1);
- strlcpy((char *)args[narg], yytext, len+1);
- narg++;
- if ((c = definp()) == ',')
- continue;
- if (c == ')')
- break;
- goto bad;
- }
- goto bad;
- }
- c = yylex();
- } else if (c == '\n') {
- /* #define foo */
- ;
- } else if (c != WSPACE)
- goto bad;
-
- while (c == WSPACE)
- c = yylex();
-
- /* parse replacement-list, substituting arguments */
- savch('\0');
- while (c != '\n') {
- switch (c) {
- case WSPACE:
- /* remove spaces if it surrounds a ## directive */
- ubuf = stringbuf;
- savstr((usch *)yytext);
- c = yylex();
- if (c == CONCAT) {
- stringbuf = ubuf;
- savch(CONC);
- if ((c = yylex()) == WSPACE)
- c = yylex();
- }
- continue;
-
- case CONCAT:
- /* No spaces before concat op */
- savch(CONC);
- if ((c = yylex()) == WSPACE)
- c = yylex();
- continue;
-
- case MKSTR:
- if (narg < 0) {
- /* no meaning in object-type macro */
- savch('#');
- break;
- }
- /* remove spaces between # and arg */
- savch(SNUFF);
- if ((c = yylex()) == WSPACE)
- c = yylex(); /* whitespace, ignore */
- mkstr = 1;
- if (c == VA_ARGS)
- continue;
-
- /* FALLTHROUGH */
- case IDENT:
- if (narg < 0)
- goto id; /* just add it if object */
- /* check if its an argument */
- for (i = 0; i < narg; i++)
- if (strcmp(yytext, (char *)args[i]) == 0)
- break;
- if (i == narg) {
- if (mkstr)
- error("not argument");
- goto id;
- }
- savch(i);
- savch(WARN);
- if (mkstr)
- savch(SNUFF), mkstr = 0;
- break;
-
- case VA_ARGS:
- if (ellips == 0)
- error("unwanted %s", yytext);
- savch(VARG);
- savch(WARN);
- if (mkstr)
- savch(SNUFF), mkstr = 0;
- break;
-
- default:
-id: savstr((usch *)yytext);
- break;
- }
- c = yylex();
- }
- /* remove trailing whitespace */
- while (stringbuf > sbeg) {
- if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')
- stringbuf--;
- else
- break;
- }
- if (ellips) {
- savch(narg);
- savch(VARG);
- } else
- savch(narg < 0 ? OBJCT : narg);
- if (redef) {
- usch *o = np->value, *n = stringbuf-1;
-
- /* Redefinition to identical replacement-list is allowed */
- while (*o && *o == *n)
- o--, n--;
- if (*o || *o != *n)
- error("%s redefined\nprevious define: %s:%d",
- np->namep, np->file, np->line);
- stringbuf = sbeg; /* forget this space */
- } else
- np->value = stringbuf-1;
-
-#ifdef CPP_DEBUG
- if (dflag) {
- usch *w = np->value;
-
- printf("!define: ");
- if (*w == OBJCT)
- printf("[object]");
- else if (*w == VARG)
- printf("[VARG%d]", *--w);
- while (*--w) {
- switch (*w) {
- case WARN: printf("<%d>", *--w); break;
- case CONC: printf("<##>"); break;
- case SNUFF: printf("<\">"); break;
- default: putchar(*w); break;
- }
- }
- putchar('\n');
- }
-#endif
- slow = 0;
- return;
-
-bad: error("bad define");
-}
-
-void
-xerror(usch *s)
-{
- usch *t;
-
- flbuf();
- savch(0);
- if (ifiles != NULL) {
- t = sheap("%s:%d: ", ifiles->fname, ifiles->lineno);
- write (2, t, strlen((char *)t));
- }
- write (2, s, strlen((char *)s));
- write (2, "\n", 1);
- exit(1);
-}
-
-/*
- * store a character into the "define" buffer.
- */
-void
-savch(c)
-{
- if (stringbuf-sbf < SBSIZE) {
- *stringbuf++ = c;
- } else {
- stringbuf = sbf; /* need space to write error message */
- error("Too much defining");
- }
-}
-
-/*
- * convert _Pragma to #pragma for output.
- */
-static void
-pragoper(void)
-{
- usch *opb;
- int t;
-
- slow = 1;
- putstr((usch *)"\n#pragma ");
- if ((t = yylex()) == WSPACE)
- t = yylex();
- if (t != '(')
- goto bad;
- if ((t = yylex()) == WSPACE)
- t = yylex();
- opb = stringbuf;
- while (t != ')') {
- savstr((usch *)yytext);
- t = yylex();
- }
- savch(0);
- cunput(WARN);
- unpstr(opb);
- stringbuf = opb;
- expmac(NULL);
- while (stringbuf > opb)
- cunput(*--stringbuf);
- if ((t = yylex()) != STRING)
- goto bad;
- opb = (usch *)yytext;
- if (*opb++ == 'L')
- opb++;
- while ((t = *opb++) != '\"') {
- if (t == '\\' && (*opb == '\"' || *opb == '\\'))
- t = *opb++;
- putch(t);
- }
- putch('\n');
- prtline();
- return;
-bad: error("bad pragma operator");
-}
-
-/*
- * substitute namep for sp->value.
- */
-int
-subst(sp, rp)
-struct symtab *sp;
-struct recur *rp;
-{
- struct recur rp2;
- register usch *vp, *cp;
- int c, rv = 0, ws;
-
- DPRINT(("subst: %s\n", sp->namep));
- /*
- * First check for special macros.
- */
- if (sp == filloc) {
- (void)sheap("\"%s\"", ifiles->fname);
- return 1;
- } else if (sp == linloc) {
- (void)sheap("%d", ifiles->lineno);
- return 1;
- } else if (sp == pragloc) {
- pragoper();
- return 1;
- }
- vp = sp->value;
-
- rp2.next = rp;
- rp2.sp = sp;
-
- if (*vp-- != OBJCT) {
- int gotwarn = 0;
-
- /* should we be here at all? */
- /* check if identifier is followed by parentheses */
- rv = 1;
- ws = 0;
- do {
- c = yylex();
- if (c == WARN) {
- gotwarn++;
- if (rp == NULL)
- goto noid;
- } else if (c == WSPACE || c == '\n')
- ws = 1;
- } while (c == WSPACE || c == '\n' || c == WARN);
-
- cp = (usch *)yytext;
- while (*cp)
- cp++;
- while (cp > (usch *)yytext)
- cunput(*--cp);
- DPRINT(("c %d\n", c));
- if (c == '(' ) {
- expdef(vp, &rp2, gotwarn);
- return rv;
- } else {
- /* restore identifier */
-noid: while (gotwarn--)
- cunput(WARN);
- if (ws)
- cunput(' ');
- cp = sp->namep;
- while (*cp)
- cp++;
- while (cp > sp->namep)
- cunput(*--cp);
- if ((c = yylex()) != IDENT)
- error("internal sync error");
- return 0;
- }
- } else {
- cunput(WARN);
- cp = vp;
- while (*cp) {
- if (*cp != CONC)
- cunput(*cp);
- cp--;
- }
- expmac(&rp2);
- }
- return 1;
-}
-
-/*
- * do macro-expansion until WARN character read.
- * read from lex buffer and store result on heap.
- * will recurse into lookup() for recursive expansion.
- * when returning all expansions on the token list is done.
- */
-void
-expmac(struct recur *rp)
-{
- struct symtab *nl;
- int c, noexp = 0, orgexp;
- usch *och, *stksv;
- extern int yyleng;
-
-#ifdef CPP_DEBUG
- if (dflag) {
- struct recur *rp2 = rp;
- printf("\nexpmac\n");
- while (rp2) {
- printf("do not expand %s\n", rp->sp->namep);
- rp2 = rp2->next;
- }
- }
-#endif
- while ((c = yylex()) != WARN) {
- switch (c) {
- case NOEXP: noexp++; break;
- case EXPAND: noexp--; break;
-
- case IDENT:
- /*
- * Handle argument concatenation here.
- * If an identifier is found and directly
- * after EXPAND or NOEXP then push the
- * identifier back on the input stream and
- * call yylex() again.
- * Be careful to keep the noexp balance.
- */
- och = stringbuf;
- savstr((usch *)yytext);
- DDPRINT(("id: str %s\n", och));
-
- orgexp = 0;
- while ((c = yylex()) == EXPAND || c == NOEXP)
- if (c == EXPAND)
- orgexp--;
- else
- orgexp++;
-
- DDPRINT(("id1: noexp %d orgexp %d\n", noexp, orgexp));
- if (c == IDENT) { /* XXX numbers? */
- DDPRINT(("id2: str %s\n", yytext));
- /* OK to always expand here? */
- savstr((usch *)yytext);
- switch (orgexp) {
- case 0: /* been EXP+NOEXP */
- if (noexp == 0)
- break;
- if (noexp != 1)
- error("case 0");
- cunput(NOEXP);
- noexp = 0;
- break;
- case -1: /* been EXP */
- if (noexp != 1)
- error("case -1");
- noexp = 0;
- break;
- case 1:
- if (noexp != 0)
- error("case 1");
- cunput(NOEXP);
- break;
- default:
- error("orgexp = %d", orgexp);
- }
- unpstr(och);
- stringbuf = och;
- continue; /* New longer identifier */
- }
- unpstr((usch *)yytext);
- if (orgexp == -1)
- cunput(EXPAND);
- else if (orgexp == 1)
- cunput(NOEXP);
- unpstr(och);
- stringbuf = och;
-
-
- yylex(); /* XXX reget last identifier */
-
- if ((nl = lookup((usch *)yytext, FIND)) == NULL)
- goto def;
-
- if (canexpand(rp, nl) == 0)
- goto def;
- /*
- * If noexp == 0 then expansion of any macro is
- * allowed. If noexp == 1 then expansion of a
- * fun-like macro is allowed iff there is an
- * EXPAND between the identifier and the '('.
- */
- if (noexp == 0) {
- if ((c = subst(nl, rp)) == 0)
- goto def;
- break;
- }
-//printf("noexp1 %d nl->namep %s\n", noexp, nl->namep);
-//if (noexp > 1) goto def;
- if (noexp != 1)
- error("bad noexp %d", noexp);
- stksv = NULL;
- if ((c = yylex()) == WSPACE) {
- stksv = alloca(yyleng+1);
- strlcpy((char *)stksv, yytext, yyleng+1);
- c = yylex();
- }
- /* only valid for expansion if fun macro */
- if (c == EXPAND && *nl->value != OBJCT) {
- noexp--;
- if (subst(nl, rp))
- break;
- savstr(nl->namep);
- if (stksv)
- savstr(stksv);
- } else {
- unpstr((usch *)yytext);
- if (stksv)
- unpstr(stksv);
- savstr(nl->namep);
- }
- break;
-
- case STRING:
- /* remove EXPAND/NOEXP from strings */
- if (yytext[1] == NOEXP) {
- savch('"');
- och = (usch *)&yytext[2];
- while (*och != EXPAND)
- savch(*och++);
- savch('"');
- break;
- }
- /* FALLTHROUGH */
-
-def: default:
- savstr((usch *)yytext);
- break;
- }
- }
- if (noexp)
- error("expmac noexp=%d", noexp);
- DPRINT(("return from expmac\n"));
-}
-
-/*
- * expand a function-like macro.
- * vp points to end of replacement-list
- * reads function arguments from yylex()
- * result is written on top of heap
- */
-void
-expdef(vp, rp, gotwarn)
- usch *vp;
- struct recur *rp;
-{
- usch **args, *sptr, *ap, *bp, *sp;
- int narg, c, i, plev, snuff, instr;
- int ellips = 0;
-
- DPRINT(("expdef %s rp %s\n", vp, (rp ? (char *)rp->sp->namep : "")));
- if ((c = yylex()) != '(')
- error("got %c, expected )", c);
- if (vp[1] == VARG) {
- narg = *vp--;
- ellips = 1;
- } else
- narg = vp[1];
- args = alloca(sizeof(usch *) * (narg+ellips));
-
- /*
- * read arguments and store them on heap.
- * will be removed just before return from this function.
- */
- sptr = stringbuf;
- for (i = 0; i < narg && c != ')'; i++) {
- args[i] = stringbuf;
- plev = 0;
- while ((c = yylex()) == WSPACE || c == '\n')
- ;
- for (;;) {
- if (plev == 0 && (c == ')' || c == ','))
- break;
- if (c == '(')
- plev++;
- if (c == ')')
- plev--;
- savstr((usch *)yytext);
- while ((c = yylex()) == '\n')
- savch('\n');
- }
- while (args[i] < stringbuf &&
- (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
- stringbuf--;
- savch('\0');
- }
- if (ellips)
- args[i] = (usch *)"";
- if (ellips && c != ')') {
- args[i] = stringbuf;
- plev = 0;
- while ((c = yylex()) == WSPACE)
- ;
- for (;;) {
- if (plev == 0 && c == ')')
- break;
- if (c == '(')
- plev++;
- if (c == ')')
- plev--;
- savstr((usch *)yytext);
- while ((c = yylex()) == '\n')
- savch('\n');
- }
- while (args[i] < stringbuf &&
- (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
- stringbuf--;
- savch('\0');
-
- }
- if (narg == 0 && ellips == 0)
- c = yylex();
- if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1))
- error("wrong arg count");
-
- while (gotwarn--)
- cunput(WARN);
-
- sp = vp;
- instr = snuff = 0;
-
- /*
- * push-back replacement-list onto lex buffer while replacing
- * arguments.
- */
- cunput(WARN);
- while (*sp != 0) {
- if (*sp == SNUFF)
- cunput('\"'), snuff ^= 1;
- else if (*sp == CONC)
- ;
- else if (*sp == WARN) {
-
- if (sp[-1] == VARG) {
- bp = ap = args[narg];
- sp--;
- } else
- bp = ap = args[(int)*--sp];
- if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
- cunput(WARN);
- while (*bp)
- bp++;
- while (bp > ap)
- cunput(*--bp);
- DPRINT(("expand arg %d string %s\n", *sp, ap));
- bp = ap = stringbuf;
- savch(NOEXP);
- expmac(NULL);
- savch(EXPAND);
- savch('\0');
- }
- while (*bp)
- bp++;
- while (bp > ap) {
- bp--;
- if (snuff && !instr &&
- (*bp == ' ' || *bp == '\t' || *bp == '\n')){
- while (*bp == ' ' || *bp == '\t' ||
- *bp == '\n') {
- bp--;
- }
- cunput(' ');
- }
- cunput(*bp);
- if ((*bp == '\'' || *bp == '"')
- && bp[-1] != '\\' && snuff) {
- instr ^= 1;
- if (instr == 0 && *bp == '"')
- cunput('\\');
- }
- if (instr && (*bp == '\\' || *bp == '"'))
- cunput('\\');
- }
- } else
- cunput(*sp);
- sp--;
- }
- stringbuf = sptr;
-
- /* scan the input buffer (until WARN) and save result on heap */
- expmac(rp);
-}
-
-usch *
-savstr(usch *str)
-{
- usch *rv = stringbuf;
-
- do {
- if (stringbuf >= &sbf[SBSIZE]) {
- stringbuf = sbf; /* need space to write error message */
- error("out of macro space!");
- }
- } while ((*stringbuf++ = *str++));
- stringbuf--;
- return rv;
-}
-
-int
-canexpand(struct recur *rp, struct symtab *np)
-{
- struct recur *w;
-
- for (w = rp; w && w->sp != np; w = w->next)
- ;
- if (w != NULL)
- return 0;
- return 1;
-}
-
-void
-unpstr(usch *c)
-{
- usch *d = c;
-
- while (*d)
- d++;
- while (d > c) {
- cunput(*--d);
- }
-}
-
-void
-flbuf()
-{
- if (obufp == 0)
- return;
- if (Mflag == 0 && write(ofd, outbuf, obufp) < 0)
- error("obuf write error");
- obufp = 0;
-}
-
-void
-putch(int ch)
-{
- outbuf[obufp++] = ch;
- if (obufp == CPPBUF || (istty && ch == '\n'))
- flbuf();
-}
-
-void
-putstr(usch *s)
-{
- for (; *s; s++) {
- outbuf[obufp++] = *s;
- if (obufp == CPPBUF || (istty && *s == '\n'))
- flbuf();
- }
-}
-
-/*
- * convert a number to an ascii string. Store it on the heap.
- */
-static void
-num2str(int num)
-{
- static usch buf[12];
- usch *b = buf;
- int m = 0;
-
- if (num < 0)
- num = -num, m = 1;
- do {
- *b++ = num % 10 + '0', num /= 10;
- } while (num);
- if (m)
- *b++ = '-';
- while (b > buf)
- savch(*--b);
-}
-
-/*
- * similar to sprintf, but only handles %s and %d.
- * saves result on heap.
- */
-usch *
-sheap(char *fmt, ...)
-{
- va_list ap;
- usch *op = stringbuf;
-
- va_start(ap, fmt);
- for (; *fmt; fmt++) {
- if (*fmt == '%') {
- fmt++;
- switch (*fmt) {
- case 's':
- savstr(va_arg(ap, usch *));
- break;
- case 'd':
- num2str(va_arg(ap, int));
- break;
- case 'c':
- savch(va_arg(ap, int));
- break;
- default:
- break; /* cannot call error() here */
- }
- } else
- savch(*fmt);
- }
- va_end(ap);
- *stringbuf = 0;
- return op;
-}
-
-void
-usage()
-{
- error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]");
-}
-
-#ifdef notyet
-/*
- * Symbol table stuff.
- * The data structure used is a patricia tree implementation using only
- * bytes to store offsets.
- * The information stored is (lower address to higher):
- *
- * unsigned char bitno[2]; bit number in the string
- * unsigned char left[3]; offset from base to left element
- * unsigned char right[3]; offset from base to right element
- */
-#endif
-
-/*
- * This patricia implementation is more-or-less the same as
- * used in ccom for string matching.
- */
-struct tree {
- int bitno;
- struct tree *lr[2];
-};
-
-#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
-#define LEFT_IS_LEAF 0x80000000
-#define RIGHT_IS_LEAF 0x40000000
-#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
-#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
-#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
-#define CHECKBITS 8
-
-static struct tree *sympole;
-static int numsyms;
-
-/*
- * Allocate a symtab struct and store the string.
- */
-static struct symtab *
-getsymtab(usch *str)
-{
- struct symtab *sp = malloc(sizeof(struct symtab));
-
- if (sp == NULL)
- error("getsymtab: couldn't allocate symtab");
- sp->namep = savstr(str);
- savch('\0');
- sp->value = NULL;
- sp->file = ifiles ? ifiles->orgfn : (usch *)"<initial>";
- sp->line = ifiles ? ifiles->lineno : 0;
- return sp;
-}
-
-/*
- * Do symbol lookup in a patricia tree.
- * Only do full string matching, no pointer optimisations.
- */
-struct symtab *
-lookup(usch *key, int enterf)
-{
- struct symtab *sp;
- struct tree *w, *new, *last;
- int len, cix, bit, fbit, svbit, ix, bitno;
- usch *k, *m, *sm;
-
- /* Count full string length */
- for (k = key, len = 0; *k; k++, len++)
- ;
-
- switch (numsyms) {
- case 0: /* no symbols yet */
- if (enterf != ENTER)
- return NULL;
- sympole = (struct tree *)getsymtab(key);
- numsyms++;
- return (struct symtab *)sympole;
-
- case 1:
- w = sympole;
- svbit = 0; /* XXX gcc */
- break;
-
- default:
- w = sympole;
- bitno = len * CHECKBITS;
- for (;;) {
- bit = BITNO(w->bitno);
- fbit = bit > bitno ? 0 : P_BIT(key, bit);
- svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
- IS_LEFT_LEAF(w->bitno);
- w = w->lr[fbit];
- if (svbit)
- break;
- }
- }
-
- sp = (struct symtab *)w;
-
- sm = m = sp->namep;
- k = key;
-
- /* Check for correct string and return */
- for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS)
- ;
- if (*m == 0 && *k == 0) {
- if (enterf != ENTER && sp->value == NULL)
- return NULL;
- return sp;
- }
-
- if (enterf != ENTER)
- return NULL; /* no string found and do not enter */
-
- ix = *m ^ *k;
- while ((ix & 1) == 0)
- ix >>= 1, cix++;
-
- /* Create new node */
- if ((new = malloc(sizeof *new)) == NULL)
- error("getree: couldn't allocate tree");
- bit = P_BIT(key, cix);
- new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
- new->lr[bit] = (struct tree *)getsymtab(key);
-
- if (numsyms++ == 1) {
- new->lr[!bit] = sympole;
- new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
- sympole = new;
- return (struct symtab *)new->lr[bit];
- }
-
- w = sympole;
- last = NULL;
- for (;;) {
- fbit = w->bitno;
- bitno = BITNO(w->bitno);
- if (bitno == cix)
- error("bitno == cix");
- if (bitno > cix)
- break;
- svbit = P_BIT(key, bitno);
- last = w;
- w = w->lr[svbit];
- if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
- break;
- }
-
- new->lr[!bit] = w;
- if (last == NULL) {
- sympole = new;
- } else {
- last->lr[svbit] = new;
- last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
- }
- if (bitno < cix)
- new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
- return (struct symtab *)new->lr[bit];
-}
-
--- usr.bin/pcc/cc/cpp/cpy.y
+++ /dev/null
@@ -1,166 +0,0 @@
-/* $Id: cpy.y,v 1.12 2006/10/08 13:41:39 ragge Exp $ */
-
-/*
- * Copyright (c) 2004 Anders Magnusson (ragge at 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 <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-void yyerror(char *);
-int yylex(void);
-%}
-
-%term stop
-%term EQ NE LE GE LS RS
-%term ANDAND OROR IDENT NUMBER
-/*
- * The following terminals are not used in the yacc code.
- */
-%term STRING FPOINT WSPACE VA_ARGS CONCAT MKSTR ELLIPS
-
-%left ','
-%right '='
-%right '?' ':'
-%left OROR
-%left ANDAND
-%left '|' '^'
-%left '&'
-%binary EQ NE
-%binary '<' '>' LE GE
-%left LS RS
-%left '+' '-'
-%left '*' '/' '%'
-%right '!' '~' UMINUS
-%left '(' '.'
-
-%union {
- long long val;
-}
-
-%type <val> term NUMBER e
-
-%%
-S: e '\n' { return($1 != 0);}
-
-
-e: e '*' e
- {$$ = $1 * $3;}
- | e '/' e
- {$$ = $1 / $3;}
- | e '%' e
- {$$ = $1 % $3;}
- | e '+' e
- {$$ = $1 + $3;}
- | e '-' e
- {$$ = $1 - $3;}
- | e LS e
- {$$ = $1 << $3;}
- | e RS e
- {$$ = $1 >> $3;}
- | e '<' e
- {$$ = $1 < $3;}
- | e '>' e
- {$$ = $1 > $3;}
- | e LE e
- {$$ = $1 <= $3;}
- | e GE e
- {$$ = $1 >= $3;}
- | e EQ e
- {$$ = $1 == $3;}
- | e NE e
- {$$ = $1 != $3;}
- | e '&' e
- {$$ = $1 & $3;}
- | e '^' e
- {$$ = $1 ^ $3;}
- | e '|' e
- {$$ = $1 | $3;}
- | e ANDAND e
- {$$ = $1 && $3;}
- | e OROR e
- {$$ = $1 || $3;}
- | e '?' e ':' e
- {$$ = $1 ? $3 : $5;}
- | e ',' e
- {$$ = $3;}
- | term
- {$$ = $1;}
-term:
- '-' term %prec UMINUS
- {$$ = -$2;}
- | '!' term
- {$$ = !$2;}
- | '~' term
- {$$ = ~$2;}
- | '(' e ')'
- {$$ = $2;}
- | NUMBER
- {$$= $1;}
-%%
-
-#include "cpp.h"
-
-void
-yyerror(char *err)
-{
- error(err);
-}
--- usr.bin/pcc/cc/cpp/cpp.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* $Id: cpp.h,v 1.27 2007/09/17 18:16:14 ragge Exp $ */
-
-/*
- * Copyright (c) 2004 Anders Magnusson (ragge at 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.
- */
-
-#include <stdio.h> /* for obuf */
-
-#include "../../config.h"
-
-typedef unsigned char usch;
-#ifdef YYTEXT_POINTER
-extern char *yytext;
-#else
-extern char yytext[];
-#endif
-extern usch *stringbuf;
-
-extern int trulvl;
-extern int flslvl;
-extern int elflvl;
-extern int elslvl;
-extern int tflag, Cflag;
-extern int Mflag, dMflag;
-extern usch *Mfile;
-extern int ofd;
-
-/* args for lookup() */
-#define FIND 0
-#define ENTER 1
-
-/* buffer used internally */
-#ifndef CPPBUF
-#ifdef __pdp11__
-#define CPPBUF BUFSIZ
-#else
-#define CPPBUF 65536
-#endif
-#endif
-
-#define NAMEMAX 64 /* max len of identifier */
-
-/* definition for include file info */
-struct includ {
- struct includ *next;
- usch *fname; /* current fn, changed if #line found */
- usch *orgfn; /* current fn, not changed */
- int lineno;
- int infil;
- usch *curptr;
- usch *maxread;
- usch *buffer;
- usch bbuf[NAMEMAX+CPPBUF+1];
-} *ifiles;
-
-/* Symbol table entry */
-struct symtab {
- usch *namep;
- usch *value;
- usch *file;
- int line;
-};
-
-struct initar {
- struct initar *next;
- int type;
- char *str;
-};
-
-struct recur; /* not used outside cpp.c */
-int subst(struct symtab *, struct recur *);
-struct symtab *lookup(usch *namep, int enterf);
-usch *gotident(struct symtab *nl);
-int slow; /* scan slowly for new tokens */
-
-int pushfile(usch *fname);
-void popfile(void);
-void prtline(void);
-int yylex(void);
-void cunput(int);
-int curline(void);
-char *curfile(void);
-void setline(int);
-void setfile(char *);
-int yyparse(void);
-void yyerror(char *);
-void unpstr(usch *);
-usch *savstr(usch *str);
-void savch(int c);
-void mainscan(void);
-void putch(int);
-void putstr(usch *s);
-void line(void);
-usch *sheap(char *fmt, ...);
-void xerror(usch *);
-#define error(...) xerror(sheap(__VA_ARGS__))
-void expmac(struct recur *);
--- usr.bin/pcc/cc/cpp/Makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-# $Id: Makefile.in,v 1.14 2007/09/26 14:48:51 ragge Exp $
-#
-# Makefile.in for cpp
-#
-XFL=-DCPP_DEBUG -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
-
-prefix = /usr/local
-exec_prefix = ${prefix}
-bindir = ${exec_prefix}/bin
-libexecdir = ${exec_prefix}/libexec
-datarootdir = ${prefix}/share
-mandir = ${datarootdir}/man
-CC = gcc
-CFLAGS = -g $(XFL)
-CPPFLAGS = -I${MDIR}
-LIBS =
-LDFLAGS =
-LEX = flex
-YACC=yacc
-INSTALL = /usr/bin/install -c
-INSTALL_PROGRAM = ${INSTALL}
-TARGMACH = x86
-
-OBJS=cpp.o cpy.o scanner.o compat.o
-HEADERS=cpp.h
-DEST=cpp
-
-MIPDIR=../../mip
-MDIR=../../arch/$(TARGMACH)
-
-all: ${DEST}
-
-${DEST}: $(OBJS) $(HEADERS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
-
-.c.o:
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
-
-.l.o:
- $(LEX) $(LFLAGS) $<
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ lex.yy.c
-
-.y.o:
- $(YACC) -d $(YFLAGS) $<
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ y.tab.c
-
-compat.o: $(MIPDIR)/compat.c
- $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c
-
-$(OBJS): $(HEADERS)
-
-cpp.o: cpy.o
-
-test:
- ./cpp < tests/test1 > tests/run1
- cmp tests/run1 tests/res1
- ./cpp < tests/test2 > tests/run2
- cmp tests/run2 tests/res2
- ./cpp < tests/test3 > tests/run3
- cmp tests/run3 tests/res3
- ./cpp < tests/test4 > tests/run4
- cmp tests/run4 tests/res4
- ./cpp < tests/test5 > tests/run5
- cmp tests/run5 tests/res5
- ./cpp < tests/test6 > tests/run6
- cmp tests/run6 tests/res6
- ./cpp < tests/test7 > tests/run7
- cmp tests/run7 tests/res7
- ./cpp < tests/test8 > tests/run8
- cmp tests/run8 tests/res8
- ./cpp < tests/test9 > tests/run9
- cmp tests/run9 tests/res9
-
-
-install:
- test -z "${DESTDIR}$(libexecdir)" || mkdir -p "${DESTDIR}$(libexecdir)"
- ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${libexecdir}
- @if [ ${strip} = yes ]; then \
- strip ${DESTDIR}${libexecdir}/${DEST} ; \
- echo strip ${DESTDIR}${libexecdir}/${DEST} ; \
- fi
- test -z "${DESTDIR}$(mandir)/man1" || mkdir -p "${DESTDIR}$(mandir)/man1"
- ${INSTALL} ${DEST}.1 ${DESTDIR}${mandir}/man1/
-
-clean:
- /bin/rm -f $(OBJS) cpp lex.yy.c y.tab.[ch] tests/run*
-
-distclean: clean
- /bin/rm -f Makefile
--- usr.bin/pcc/cc/cpp/cpp.1
+++ /dev/null
@@ -1,191 +0,0 @@
-.\" $Id: cpp.1,v 1.4 2007/09/26 14:48:51 ragge Exp $
-.\" $NetBSD$
-.\" $OpenBSD$
-."\
-.\" Copyright (c) 2007 Jeremy C. Reed <reed at 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 Cdt
-.Op Fl D Ar var=val
-.Op Fl U Ar var
-.Op Fl I Ar path
-.Op Fl S Ar path
-.Op Ar infile | -
-.Op Ar outfile
-.Pp
-.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 C
-Do not discard comments.
-.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 outputted.
-.\" TODO this doesn't show predefined macros
-.\" other -d options are ignored
-.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 defines as 1.
-.\" TODO: show example
-.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 I Ar directory
-Add
-.Ar directory
-to the list of system 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 M
-Generate dependencies for
-.Xr make 1 .
-.\" TODO: explain and show example?
-.It Fl S Ar directory
-Add
-.Ar directory
-to the list of system directories containing needed header files.
-.Fl S
-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__ ,
-and
-.Dv __STDC__
-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 ?
-Show command line usage for
-.Nm .
-.El
-.Sh 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 Ao stdin Ac .
-.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 ISO Standard C.
-.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.
--- usr.bin/pcc/cc/cpp/tests/res9
+++ /dev/null
@@ -1,5 +0,0 @@
-# 1 "<stdin>"
-
-
-
-ao
--- usr.bin/pcc/cc/cpp/tests/res7
+++ /dev/null
@@ -1,5 +0,0 @@
-# 1 "<stdin>"
-
-
-
-a YES
--- usr.bin/pcc/cc/cpp/tests/test1
+++ /dev/null
@@ -1,6 +0,0 @@
-#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";
--- usr.bin/pcc/cc/cpp/tests/res6
+++ /dev/null
@@ -1,6 +0,0 @@
-# 1 "<stdin>"
-
-
-
-
-foo
--- usr.bin/pcc/cc/cpp/tests/test2
+++ /dev/null
@@ -1,25 +0,0 @@
-#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", "" };
- */
--- usr.bin/pcc/cc/cpp/tests/test8
+++ /dev/null
@@ -1,7 +0,0 @@
-// test macro expansion in arguments
-#define s_pos s_s.s_pos
-#define foo(x) (x)
-
-//hej.s_pos
-foo(hej.s_pos)
-
--- usr.bin/pcc/cc/cpp/tests/test5
+++ /dev/null
@@ -1,3 +0,0 @@
-#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(,,) };
--- usr.bin/pcc/cc/cpp/tests/test7
+++ /dev/null
@@ -1,4 +0,0 @@
-#define a() YES
-#define b() a
-b()
-b()()
--- usr.bin/pcc/cc/cpp/tests/res4
+++ /dev/null
@@ -1,5 +0,0 @@
-# 1 "<stdin>"
-
-
-
-(1)
--- usr.bin/pcc/cc/cpp/tests/res3
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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"
--- usr.bin/pcc/cc/cpp/tests/test6
+++ /dev/null
@@ -1,5 +0,0 @@
-#define X(a,b, \
- c,d) \
- foo
-
-X(1,2,3,4)
--- usr.bin/pcc/cc/cpp/tests/res8
+++ /dev/null
@@ -1,8 +0,0 @@
-# 1 "<stdin>"
-
-
-
-
-
-(hej.s_s.s_pos)
-
--- usr.bin/pcc/cc/cpp/tests/res5
+++ /dev/null
@@ -1,4 +0,0 @@
-# 1 "<stdin>"
-
-int j[] = { 123, 45, 67, 89,
- 10, 11, 12, };
--- usr.bin/pcc/cc/cpp/tests/res1
+++ /dev/null
@@ -1,7 +0,0 @@
-# 1 "<stdin>"
-
-
-
-
-char p[] = "x ## y";
-
--- usr.bin/pcc/cc/cpp/tests/res2
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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", "" };
-
-
-
-
-
-
--- usr.bin/pcc/cc/cpp/tests/test4
+++ /dev/null
@@ -1,4 +0,0 @@
-#define foobar 1
-#define C(x,y) x##y
-#define D(x) (C(x,bar))
-D(foo)
--- usr.bin/pcc/cc/cpp/tests/test9
+++ /dev/null
@@ -1,4 +0,0 @@
-#define C(a,b,c) a##b##c
-#define N(x,y) C(x,_,y)
-#define A_O ao
-N(A,O)
--- usr.bin/pcc/cc/cpp/tests/test3
+++ /dev/null
@@ -1,15 +0,0 @@
-#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)
--- /dev/null
+++ usr.bin/pcc/ccom/inline.c
@@ -0,0 +1,209 @@
+/* $Id: inline.c,v 1.17 2007/09/09 10:01:01 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+#include "pass1.h"
+
+#include <stdarg.h>
+
+/*
+ * ilink from ipole points to the next struct in the list of functions.
+ */
+static struct istat {
+ struct istat *ilink;
+ char *name;
+ int type;
+#define NOTYETR 0 /* saved but not yet referenced */
+#define NOTYETW 1 /* saved and referenced but not yet written out */
+#define WRITTEN 2 /* is written out */
+#define NOTYETD 3 /* referenced but not yet saved */
+ struct interpass shead;
+} *ipole, *cifun;
+
+#define IP_REF (MAXIP+1)
+
+int isinlining, recovernodes;
+int inlnodecnt, inlstatcnt;
+
+#define ialloc() permalloc(sizeof(struct istat)); inlstatcnt++
+#define nalloc() permalloc(sizeof(NODE))
+
+static void
+tcnt(NODE *p)
+{
+ inlnodecnt++;
+}
+
+static struct istat *
+findfun(char *name)
+{
+ struct istat *is = ipole;
+ while (is) {
+ if (is->name == name)
+ return is;
+ is = is->ilink;
+ }
+ return NULL;
+}
+
+static void
+refnode(char *str)
+{
+ struct interpass *ip;
+
+ if (sdebug)
+ printf("refnode(%s)\n", str);
+
+ ip = permalloc(sizeof(*ip));
+ ip->type = IP_REF;
+ ip->ip_name = str;
+ inline_addarg(ip);
+}
+
+void
+inline_addarg(struct interpass *ip)
+{
+ DLIST_INSERT_BEFORE(&cifun->shead, ip, qelem);
+ if (ip->type == IP_NODE)
+ walkf(ip->ip_node, tcnt); /* Count as saved */
+}
+
+/*
+ * Called to setup for inlining of a new function.
+ */
+void
+inline_start(char *name)
+{
+ struct istat *is;
+
+ if (sdebug)
+ printf("inline_start(\"%s\")\n", name);
+
+ if (isinlining)
+ cerror("already inlining function");
+
+ if ((is = findfun(name)) == 0) {
+ is = ialloc();
+ is->ilink = ipole;
+ ipole = is;
+ is->name = name;
+ is->type = NOTYETR;
+ } else {
+ if (is->type != NOTYETD)
+ cerror("inline function already defined");
+ is->type = NOTYETW;
+ }
+ DLIST_INIT(&is->shead, qelem);
+ cifun = is;
+ isinlining++;
+}
+
+void
+inline_end()
+{
+ if (sdebug)
+ printf("inline_end()\n");
+
+ isinlining = 0;
+}
+
+/*
+ * Called when an inline function is found, to be sure that it will
+ * be written out.
+ * The function may not be defined when inline_ref() is called.
+ */
+void
+inline_ref(char *name)
+{
+ struct istat *w = ipole;
+
+ if (sdebug)
+ printf("inline_ref(\"%s\")\n", name);
+ if (isinlining) {
+ refnode(name);
+ } else {
+ while (w != NULL) {
+ if (w->name == name) {
+ if (w->type == NOTYETR)
+ w->type = NOTYETW;
+ return; /* setup for writeout */
+ }
+ w = w->ilink;
+ }
+ /* function not yet defined, print out when found */
+ w = ialloc();
+ w->ilink = ipole;
+ ipole = w;
+ w->name = name;
+ w->type = NOTYETD;
+ }
+}
+
+static void
+puto(struct istat *w)
+{
+ struct interpass *ip, *nip;
+
+ /* if -O, list will be saved again so foreach cannot be used */
+ ip = DLIST_NEXT(&w->shead, qelem);
+ while (ip != (&w->shead)) {
+ nip = DLIST_NEXT(ip, qelem);
+ DLIST_REMOVE(ip, qelem);
+ if (ip->type == IP_REF)
+ inline_ref(ip->ip_name);
+ else
+ pass2_compile(ip);
+ ip = nip;
+ }
+ DLIST_INIT(&w->shead, qelem);
+}
+
+/*
+ * printout functions that are referenced.
+ */
+void
+inline_prtout()
+{
+ struct istat *w = ipole;
+ int gotone = 0;
+
+ if (w == NULL)
+ return;
+ recovernodes++;
+ while (w != NULL) {
+ if (w->type == NOTYETW) {
+ puto(w);
+ w->type = WRITTEN;
+ gotone++;
+ }
+ w = w->ilink;
+ }
+ if (gotone)
+ inline_prtout();
+ recovernodes--;
+}
--- /dev/null
+++ usr.bin/pcc/ccom/scan.l
@@ -0,0 +1,467 @@
+%{
+/* $Id: scan.l,v 1.61 2007/09/19 17:20:26 ragge Exp $ */
+
+/*
+ * Copyright (c) 2002 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.
+ */
+%}
+
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+P [Pp][+-]?{D}+
+FS (f|F|l|L)
+IS (u|U|l|L)*
+
+%{
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "pass1.h"
+#include "cgram.h"
+
+static NODE *cvtdig(int radix);
+static NODE *charcon(void);
+static void control(int);
+static NODE *floatcon(void);
+static NODE *fhexcon(void);
+int notype, parbal;
+
+#define CPP_PRAGMA 1
+#define CPP_IDENT 2
+#define CPP_LINE 3
+#define CPP_HASH 4
+
+#ifdef STABS
+#define STABS_LINE(x) if (gflag && blevel) stabs_line(x)
+#else
+#define STABS_LINE(x)
+#endif
+#if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION >= 31
+/* Hack to avoid unneccessary 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);
+extern int yyget_lineno (void);
+extern void yyset_lineno (int);
+#endif
+
+%}
+
+%%
+
+"__func__" {
+ if (cftnsp == NULL)
+ uerror("__func__ outside function");
+ yylval.strp = cftnsp->sname; /* XXX - not C99 */
+ return(C_STRING);
+ }
+"asm" { return(C_ASM); }
+"auto" { yylval.intval = AUTO; return(C_CLASS); }
+"_Bool" { yylval.nodep = mkty((TWORD)BOOL, 0, MKSUE(BOOL));
+ return(C_TYPE); }
+"break" { return(C_BREAK); }
+"case" { return(C_CASE); }
+"char" { yylval.nodep = mkty((TWORD)CHAR, 0, MKSUE(CHAR));
+ notype=1; return(C_TYPE); }
+"const" { yylval.nodep =
+ block(QUALIFIER, NIL, NIL, CON, 0, 0);
+ return(C_QUALIFIER); }
+"continue" { return(C_CONTINUE); }
+"default" { return(C_DEFAULT); }
+"do" { return(C_DO); }
+"double" { yylval.nodep = mkty((TWORD)DOUBLE, 0, MKSUE(DOUBLE));
+ notype=1; return(C_TYPE); }
+"else" { return(C_ELSE); }
+"enum" { notype=1; return(C_ENUM); }
+"extern" { yylval.intval = EXTERN; return(C_CLASS); }
+"float" { yylval.nodep = mkty((TWORD)FLOAT, 0, MKSUE(FLOAT));
+ notype=1; return(C_TYPE); }
+"for" { return(C_FOR); }
+"goto" { return(C_GOTO); }
+"if" { return(C_IF); }
+"inline" { return(C_FUNSPEC); }
+"int" { yylval.nodep = mkty((TWORD)INT, 0, MKSUE(INT));
+ notype=1; return(C_TYPE); }
+"long" { yylval.nodep = mkty((TWORD)LONG, 0, MKSUE(LONG));
+ notype=1; return(C_TYPE); }
+"register" { yylval.intval = REGISTER; return(C_CLASS); }
+"restrict" { ; /* just ignore */ }
+"return" { return(C_RETURN); }
+"short" { yylval.nodep = mkty((TWORD)SHORT, 0, MKSUE(SHORT));
+ notype=1; return(C_TYPE); }
+"signed" { yylval.nodep = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
+ notype=1; return(C_TYPE); }
+"sizeof" { return(C_SIZEOF); }
+"static" { yylval.intval = STATIC; return(C_CLASS); }
+"struct" { yylval.intval = INSTRUCT; notype=1; return(C_STRUCT); }
+"switch" { return(C_SWITCH); }
+"typedef" { yylval.intval = TYPEDEF; return(C_CLASS); }
+"union" { yylval.intval = INUNION; notype=1; return(C_STRUCT); }
+"unsigned" { yylval.nodep = mkty((TWORD)UNSIGNED, 0, MKSUE(UNSIGNED));
+ notype=1; return(C_TYPE); }
+"void" { yylval.nodep = mkty((TWORD)VOID, 0, MKSUE(VOID));
+ notype=1; return(C_TYPE); }
+"volatile" { yylval.nodep =
+ block(QUALIFIER, NIL, NIL, VOL, 0, 0);
+ return(C_QUALIFIER); }
+"while" { return(C_WHILE); }
+
+{L}({L}|{D})* { struct symtab *s;
+ int i;
+
+ yylval.strp = addname(yytext);
+ if ((i = gcc_keyword(yylval.strp,
+ &yylval.nodep)) != 0)
+ return i;
+// printf("str: %s notype %d parbal %d\n", yytext, notype, parbal);
+ if (!notype) {
+ s = lookup(yylval.strp, SNOCREAT);
+ if (s && s->sclass == TYPEDEF)
+ return notype=1, C_TYPENAME;
+ }
+ return(C_NAME);
+ }
+
+0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); }
+0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); }
+{D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); }
+L?'(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); }
+
+{D}+{E}{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
+{D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
+{D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(); return(C_FCON); }
+0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
+0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
+0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(); return(C_FCON); }
+
+L?\"(\\.|[^\\"])*\" {
+ char *c = yytext;
+ int i = yyleng-2, rv;
+
+ if (*c++ == 'L') {
+ c++, i--;
+ rv = C_WSTRING;
+ } else
+ rv = C_STRING;
+ c[i] = 0; /* last " */
+ yylval.strp = c;
+ return rv;
+ }
+"..." { return(C_ELLIPSIS); }
+">>=" { yylval.intval = RSEQ; return(C_ASOP); }
+"<<=" { yylval.intval = LSEQ; return(C_ASOP); }
+"+=" { yylval.intval = PLUSEQ; return(C_ASOP); }
+"-=" { yylval.intval = MINUSEQ; return(C_ASOP); }
+"*=" { yylval.intval = MULEQ; return(C_ASOP); }
+"/=" { yylval.intval = DIVEQ; return(C_ASOP); }
+"%=" { yylval.intval = MODEQ; return(C_ASOP); }
+"&=" { yylval.intval = ANDEQ; return(C_ASOP); }
+"^=" { yylval.intval = EREQ; return(C_ASOP); }
+"|=" { yylval.intval = OREQ; return(C_ASOP); }
+">>" { yylval.intval = RS; return(C_SHIFTOP); }
+"<<" { yylval.intval = LS; return(C_SHIFTOP); }
+"++" { yylval.intval = INCR; return(C_INCOP); }
+"--" { yylval.intval = DECR; return(C_INCOP); }
+"->" { yylval.intval = STREF; return(C_STROP); }
+"&&" { yylval.intval = ANDAND; return(C_ANDAND); }
+"||" { yylval.intval = OROR; return(C_OROR); }
+"<=" { yylval.intval = LE; return(C_RELOP); }
+">=" { yylval.intval = GE; return(C_RELOP); }
+"==" { yylval.intval = EQ; return(C_EQUOP); }
+"!=" { yylval.intval = NE; return(C_EQUOP); }
+";" { notype = 0; return(';'); }
+("{"|"<%") { notype = 0; return('{'); }
+("}"|"%>") { return('}'); }
+"," { if (parbal) notype = 0; return(','); }
+":" { return(':'); }
+"=" { return('='); }
+"(" { parbal++; notype = 0; return('('); }
+")" { parbal--; if (parbal==0) { notype = 0; } return(')'); }
+("["|"<:") { return('['); }
+("]"|":>") { return(']'); }
+"." { yylval.intval = DOT; return(C_STROP); }
+"&" { return('&'); }
+"!" { yylval.intval = NOT; return(C_UNOP); }
+"~" { yylval.intval = COMPL; return(C_UNOP); }
+"-" { return('-'); }
+"+" { return('+'); }
+"*" { if (parbal && notype == 0) notype = 1; return('*'); }
+"/" { yylval.intval = DIV; return(C_DIVOP); }
+"%" { yylval.intval = MOD; return(C_DIVOP); }
+"<" { yylval.intval = LT; return(C_RELOP); }
+">" { yylval.intval = GT; return(C_RELOP); }
+"^" { return('^'); }
+"|" { return('|'); }
+"?" { return('?'); }
+^#pragma[ \t].* { control(CPP_PRAGMA); }
+^#ident[ \t].* { control(CPP_IDENT); }
+^#line[ \t].* { control(CPP_LINE); }
+^#.* { control(CPP_HASH); }
+
+[ \t\v\f] { }
+"\n" { ++lineno; STABS_LINE(lineno); }
+. { /* ignore bad characters */ }
+
+%%
+
+int lineno;
+char *ftitle = "<stdin>";
+
+int
+yywrap(void)
+{
+ if (0) unput(0); /* quiet gcc */
+ return(1);
+}
+
+/*
+ * XXX floatcon() and fhexcon() should be in support libraries for
+ * the target floating point.
+ */
+static NODE *
+f2(char *str)
+{
+ TWORD tw;
+ NODE *p;
+ double dc;
+ char *eptr;
+
+ dc = strtod(str, &eptr); /* XXX - avoid strtod() */
+ tw = (*eptr == 'f' || *eptr == 'F' ? FLOAT : DOUBLE);
+ p = block(FCON, NIL, NIL, tw, 0, MKSUE(tw));
+ p->n_dcon = dc;
+ return p;
+}
+
+NODE *
+floatcon(void)
+{
+ return f2(yytext);
+}
+
+static int
+h2n(int ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ return ch - 'A' + 10;
+
+}
+
+NODE *
+fhexcon(void)
+{
+ char buf[500];
+ char *c = yytext;
+ unsigned long long num1, num2;
+
+ /* XXX - convert it to a decimal float number and use strtod */
+ c+= 2; /* skip 0x */
+ for (num1 = 0; *c != '.' && *c != 'p' && *c != 'P'; c++)
+ num1 = (num1 << 4) | h2n(*c);
+ if (*c != '.' && *c != 'p' && *c != 'P')
+ cerror("fhexcon");
+ num2 = 0;
+ if (*c == '.') {
+ c++;
+ for (; *c != 'p' && *c != 'P'; c++)
+ num2 = (num2 << 4) | h2n(*c);
+ }
+ if (*c != 'P' && *c != 'p')
+ cerror("fhexcon2");
+ c++;
+ snprintf(buf, sizeof(buf), "%llu.%lluE%s", num1, num2, c);
+ return f2(buf);
+}
+
+unsigned int
+esccon(char **sptr)
+{
+ char *wr = *sptr;
+ unsigned int val;
+
+ switch (*wr++) {
+ 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 'x': val = strtoul(wr, &wr, 16); break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ wr--;
+ val = strtoul(wr, &wr, 8);
+ break;
+ default: val = wr[-1];
+ }
+ *sptr = wr;
+ return val;
+}
+
+NODE *
+cvtdig(int radix)
+{
+ NODE *p;
+ TWORD ntype;
+ unsigned long long v;
+ char *ch = yytext;
+ int n, numl, numu;
+
+ if (radix == 16)
+ ch += 2; /* Skip 0x */
+
+ v = 0;
+ while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') ||
+ (*ch >= 'A' && *ch <= 'F')) {
+ v *= radix;
+ n = *ch;
+ n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10);
+ ch++;
+ v += n;
+ }
+ /* Parse trailing chars */
+ ntype = INT;
+ numl = numu = 0;
+ for (n = 0; n < 3; n++) {
+ if (*ch == 0)
+ break;
+ if ((*ch == 'l' || *ch == 'L') && numl < 2)
+ ntype+=2, numl++;
+ else if ((*ch == 'u' || *ch == 'U') && numu < 1)
+ ntype = ENUNSIGN(ntype), numu++;
+ else
+ break;
+ ch++;
+ }
+ if (*ch)
+ uerror("constant has too many '%c'", *ch);
+
+ if (ntype == INT) {
+ /* v contains a number. Get type correct */
+ if (v > MAX_LONGLONG && radix != 10)
+ ntype = ULONGLONG;
+ else if (v > MAX_ULONG)
+ ntype = LONGLONG;
+ else if (v > MAX_LONG && radix != 10)
+ ntype = ULONG;
+ else if (v > MAX_UNSIGNED)
+ ntype = LONG;
+ else if (v > MAX_INT && radix != 10)
+ ntype = UNSIGNED;
+ }
+ ntype = ctype(ntype);
+ p = block(ICON, NIL, NIL, ntype, 0, MKSUE(ntype));
+ p->n_lval = v;
+ ASGLVAL(p->n_slval, v);
+
+ return p;
+}
+
+/*
+ * Convert a character constant to an integer.
+ */
+NODE *
+charcon(void)
+{
+ int lastcon = 0;
+ int val, i = 0;
+ char *pp = yytext;
+
+ if (*pp == 'L')
+ pp++;
+ pp++;
+ while (*pp != '\'') {
+ if (*pp++ == '\\') {
+ val = esccon(&pp);
+ } else
+ val = pp[-1];
+ makecc(val, i);
+ i++;
+ }
+
+ if (i == 0)
+ uerror("empty character constant");
+ if (i > (SZINT/SZCHAR) || (i>1))
+ werror("too many characters in character constant");
+ return bcon(lastcon);
+}
+
+void
+control(int t)
+{
+ char *wr = yytext;
+ char *eptr;
+ int val;
+
+ wr++; /* Skip initial '#' */
+ switch (t) {
+ case CPP_PRAGMA:
+ case CPP_IDENT:
+ return; /* Just skip these for now. */
+
+ case CPP_LINE:
+ wr += 4;
+ /* FALLTHROUGH */
+ case CPP_HASH:
+ val = strtol(wr, &eptr, 10);
+ if (wr == eptr) /* Illegal string */
+ goto bad;
+ wr = eptr;
+ lineno = val - 1;
+ while (*wr && *wr != '\"')
+ wr++;
+ if (*wr++ != '\"')
+ goto bad;
+ eptr = wr;
+ while (*wr && *wr != '\"')
+ wr++;
+ if (*wr != '\"')
+ goto bad;
+ *wr = 0;
+ ftitle = addstring(eptr);
+#ifdef STABS
+ if (gflag)
+ stabs_file(ftitle);
+#endif
+ }
+ return;
+bad:
+ werror("%s: illegal control", yytext);
+}
--- /dev/null
+++ usr.bin/pcc/ccom/pftn.c
@@ -0,0 +1,2553 @@
+/* $Id: pftn.c,v 1.171 2007/09/23 20:00:22 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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 conditionsand 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.
+ */
+
+/*
+ * Many changes from the 32V sources, among them:
+ * - New symbol table manager (moved to another file).
+ * - Prototype saving/checks.
+ */
+
+# include "pass1.h"
+
+#include <string.h> /* XXX - for strcmp */
+
+struct symtab *spname;
+struct symtab *cftnsp;
+static int strunem; /* currently parsed member type */
+int arglistcnt, dimfuncnt; /* statistics */
+int symtabcnt, suedefcnt; /* statistics */
+int autooff, /* the next unused automatic offset */
+ maxautooff, /* highest used automatic offset in function */
+ argoff, /* the next unused argument offset */
+ strucoff; /* the next structure offset position */
+int retlab = NOLAB; /* return label for subroutine */
+int brklab;
+int contlab;
+int flostat;
+int instruct, blevel;
+int reached, prolab;
+
+struct params;
+
+#define ISSTR(ty) (ty == STRTY || ty == UNIONTY || ty == ENUMTY)
+#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
+#define MKTY(p, t, d, s) r = talloc(); *r = *p; \
+ r = argcast(r, t, d, s); *p = *r; nfree(r);
+
+/*
+ * Info stored for delaying string printouts.
+ */
+struct strsched {
+ struct strsched *next;
+ int locctr;
+ struct symtab *sym;
+} *strpole;
+
+/*
+ * Linked list stack while reading in structs.
+ */
+struct rstack {
+ struct rstack *rnext;
+ int rinstruct;
+ int rclass;
+ int rstrucoff;
+ struct params *rlparam;
+ struct symtab *rsym;
+};
+
+/*
+ * Linked list for parameter (and struct elements) declaration.
+ */
+static struct params {
+ struct params *next, *prev;
+ struct symtab *sym;
+} *lpole, *lparam;
+static int nparams;
+
+/* defines used for getting things off of the initialization stack */
+
+static NODE *arrstk[10];
+static int arrstkp;
+static int intcompare;
+
+void fixtype(NODE *p, int class);
+int fixclass(int class, TWORD type);
+int falloc(struct symtab *p, int w, int new, NODE *pty);
+static void dynalloc(struct symtab *p, int *poff);
+void inforce(OFFSZ n);
+void vfdalign(int n);
+static void ssave(struct symtab *);
+static void strprint(void);
+static void alprint(union arglist *al, int in);
+static void lcommadd(struct symtab *sp);
+
+int ddebug = 0;
+
+/*
+ * Declaration of an identifier. Handles redeclarations, hiding,
+ * incomplete types and forward declarations.
+ */
+
+void
+defid(NODE *q, int class)
+{
+ struct symtab *p;
+ TWORD type, qual;
+ TWORD stp, stq;
+ int scl;
+ union dimfun *dsym, *ddef;
+ int slev, temp, changed;
+
+ if (q == NIL)
+ return; /* an error was detected */
+
+ p = q->n_sp;
+
+#ifdef PCC_DEBUG
+ if (ddebug) {
+ printf("defid(%s (%p), ", p->sname, p);
+ tprint(stdout, q->n_type, q->n_qual);
+ printf(", %s, (%p,%p)), level %d\n", scnames(class),
+ q->n_df, q->n_sue, blevel);
+ }
+#endif
+
+ fixtype(q, class);
+
+ type = q->n_type;
+ qual = q->n_qual;
+ class = fixclass(class, type);
+
+ stp = p->stype;
+ stq = p->squal;
+ slev = p->slevel;
+
+#ifdef PCC_DEBUG
+ if (ddebug) {
+ printf(" modified to ");
+ tprint(stdout, type, qual);
+ printf(", %s\n", scnames(class));
+ printf(" previous def'n: ");
+ tprint(stdout, stp, stq);
+ printf(", %s, (%p,%p)), level %d\n",
+ scnames(p->sclass), p->sdf, p->ssue, slev);
+ }
+#endif
+
+ if (blevel == 1) {
+ switch (class) {
+ default:
+ if (!(class&FIELD))
+ uerror("declared argument %s missing",
+ p->sname );
+ case MOS:
+ case STNAME:
+ case MOU:
+ case UNAME:
+ case MOE:
+ case ENAME:
+ case TYPEDEF:
+ ;
+ }
+ }
+
+ if (stp == UNDEF)
+ goto enter; /* New symbol */
+
+ if (type != stp)
+ goto mismatch;
+
+ if (blevel > slev && (class == AUTO || class == REGISTER))
+ /* new scope */
+ goto mismatch;
+
+ /*
+ * test (and possibly adjust) dimensions.
+ * also check that prototypes are correct.
+ */
+ dsym = p->sdf;
+ ddef = q->n_df;
+ changed = 0;
+ for (temp = type; temp & TMASK; temp = DECREF(temp)) {
+ if (ISARY(temp)) {
+ if (dsym->ddim == 0) {
+ dsym->ddim = ddef->ddim;
+ changed = 1;
+ } else if (ddef->ddim != 0 && dsym->ddim!=ddef->ddim) {
+ goto mismatch;
+ }
+ ++dsym;
+ ++ddef;
+ } else if (ISFTN(temp)) {
+ /* add a late-defined prototype here */
+ if (cftnsp == NULL && dsym->dfun == NULL)
+ dsym->dfun = ddef->dfun;
+ if (!oldstyle && ddef->dfun != NULL &&
+ chkftn(dsym->dfun, ddef->dfun))
+ uerror("declaration doesn't match prototype");
+ dsym++, ddef++;
+ }
+ }
+#ifdef STABS
+ if (changed && gflag)
+ stabs_chgsym(p); /* symbol changed */
+#endif
+
+ /* check that redeclarations are to the same structure */
+ if ((temp == STRTY || temp == UNIONTY || temp == ENUMTY) &&
+ p->ssue != q->n_sue &&
+ class != STNAME && class != UNAME && class != ENAME) {
+ goto mismatch;
+ }
+
+ scl = p->sclass;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf(" previous class: %s\n", scnames(scl));
+#endif
+
+ if (class&FIELD) {
+ /* redefinition */
+ if (!falloc(p, class&FLDSIZ, 1, NIL)) {
+ /* successful allocation */
+ ssave(p);
+ return;
+ }
+ /* blew it: resume at end of switch... */
+ } else switch(class) {
+
+ case EXTERN:
+ switch( scl ){
+ case STATIC:
+ case USTATIC:
+ if( slev==0 ) return;
+ break;
+ case EXTDEF:
+ case EXTERN:
+ case FORTRAN:
+ case UFORTRAN:
+ return;
+ }
+ break;
+
+ case STATIC:
+ if (scl==USTATIC || (scl==EXTERN && blevel==0)) {
+ p->sclass = STATIC;
+ return;
+ }
+ if (changed || (scl == STATIC && blevel == slev))
+ return; /* identical redeclaration */
+ break;
+
+ case USTATIC:
+ if (scl==STATIC || scl==USTATIC)
+ return;
+ break;
+
+ case TYPEDEF:
+ if (scl == class)
+ return;
+ break;
+
+ case UFORTRAN:
+ if (scl == UFORTRAN || scl == FORTRAN)
+ return;
+ break;
+
+ case FORTRAN:
+ if (scl == UFORTRAN) {
+ p->sclass = FORTRAN;
+ return;
+ }
+ break;
+
+ case MOU:
+ case MOS:
+ if (scl == class) {
+ if (oalloc(p, &strucoff))
+ break;
+ if (class == MOU)
+ strucoff = 0;
+ ssave(p);
+ return;
+ }
+ break;
+
+ case MOE:
+ break;
+
+ case EXTDEF:
+ switch (scl) {
+ case EXTERN:
+ p->sclass = EXTDEF;
+ return;
+ case USTATIC:
+ p->sclass = STATIC;
+ return;
+ }
+ break;
+
+ case STNAME:
+ case UNAME:
+ case ENAME:
+ if (scl != class)
+ break;
+ if (p->ssue->suesize == 0)
+ return; /* previous entry just a mention */
+ break;
+
+ case AUTO:
+ case REGISTER:
+ ; /* mismatch.. */
+ }
+
+ mismatch:
+
+ /*
+ * Only allowed for automatic variables.
+ */
+ if (blevel == slev || class == EXTERN || class == FORTRAN ||
+ class == UFORTRAN) {
+ if (ISSTR(class) && !ISSTR(p->sclass)) {
+ uerror("redeclaration of %s", p->sname);
+ return;
+ }
+ }
+ if (blevel == 0)
+ uerror("redeclaration of %s", p->sname);
+ q->n_sp = p = hide(p);
+
+ enter: /* make a new entry */
+
+#ifdef PCC_DEBUG
+ if(ddebug)
+ printf(" new entry made\n");
+#endif
+ p->stype = type;
+ p->squal = qual;
+ p->sclass = class;
+ p->slevel = blevel;
+ p->soffset = NOOFFSET;
+ p->suse = lineno;
+ if (class == STNAME || class == UNAME || class == ENAME) {
+ p->ssue = permalloc(sizeof(struct suedef));
+ suedefcnt++;
+ p->ssue->suesize = 0;
+ p->ssue->suelem = NULL;
+ p->ssue->suealign = ALSTRUCT;
+ } else {
+ switch (BTYPE(type)) {
+ case STRTY:
+ case UNIONTY:
+ case ENUMTY:
+ p->ssue = q->n_sue;
+ break;
+ default:
+ p->ssue = MKSUE(BTYPE(type));
+ }
+ }
+
+ /* copy dimensions */
+ p->sdf = q->n_df;
+ /* Do not save param info for old-style functions */
+ if (ISFTN(type) && oldstyle)
+ p->sdf->dfun = NULL;
+
+ /* allocate offsets */
+ if (class&FIELD) {
+ (void) falloc(p, class&FLDSIZ, 0, NIL); /* new entry */
+ ssave(p);
+ } else switch (class) {
+
+ case REGISTER:
+ cerror("register var");
+
+ case AUTO:
+ if (arrstkp)
+ dynalloc(p, &autooff);
+ else
+ oalloc(p, &autooff);
+ break;
+ case STATIC:
+ case EXTDEF:
+ p->soffset = getlab();
+#ifdef GCC_COMPAT
+ { extern char *renname;
+ if (renname)
+ gcc_rename(p, renname);
+ renname = NULL;
+ }
+#endif
+ break;
+
+ case EXTERN:
+ case UFORTRAN:
+ case FORTRAN:
+ p->soffset = getlab();
+#ifdef notdef
+ /* Cannot reset level here. What does the standard say??? */
+ p->slevel = 0;
+#endif
+#ifdef GCC_COMPAT
+ { extern char *renname;
+ if (renname)
+ gcc_rename(p, renname);
+ renname = NULL;
+ }
+#endif
+ break;
+ case MOU:
+ case MOS:
+ oalloc(p, &strucoff);
+ if (class == MOU)
+ strucoff = 0;
+ ssave(p);
+ break;
+
+ case MOE:
+ p->soffset = strucoff++;
+ ssave(p);
+ break;
+
+ }
+
+#ifdef STABS
+ if (gflag)
+ stabs_newsym(p);
+#endif
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf( " sdf, ssue, offset: %p, %p, %d\n",
+ p->sdf, p->ssue, p->soffset);
+#endif
+
+}
+
+void
+ssave(struct symtab *sym)
+{
+ struct params *p;
+
+ p = tmpalloc(sizeof(struct params));
+ p->next = NULL;
+ p->sym = sym;
+
+ if (lparam == NULL) {
+ p->prev = (struct params *)&lpole;
+ lpole = p;
+ } else {
+ lparam->next = p;
+ p->prev = lparam;
+ }
+ lparam = p;
+}
+
+/*
+ * end of function
+ */
+void
+ftnend()
+{
+ extern struct savbc *savbc;
+ extern struct swdef *swpole;
+ char *c;
+
+ if (retlab != NOLAB && nerrors == 0) { /* inside a real function */
+ plabel(retlab);
+ efcode(); /* struct return handled here */
+ c = cftnsp->sname;
+#ifdef GCC_COMPAT
+ c = gcc_findname(cftnsp);
+#endif
+ SETOFF(maxautooff, ALCHAR);
+ send_passt(IP_EPILOG, 0, maxautooff/SZCHAR, c,
+ cftnsp->stype, cftnsp->sclass == EXTDEF, retlab);
+ }
+
+ tcheck();
+ brklab = contlab = retlab = NOLAB;
+ flostat = 0;
+ if (nerrors == 0) {
+ if (savbc != NULL)
+ cerror("bcsave error");
+ if (lparam != NULL)
+ cerror("parameter reset error");
+ if (swpole != NULL)
+ cerror("switch error");
+ }
+ savbc = NULL;
+ lparam = NULL;
+ maxautooff = autooff = AUTOINIT;
+ reached = 1;
+
+ if (isinlining)
+ inline_end();
+ inline_prtout();
+
+ strprint();
+
+ tmpfree(); /* Release memory resources */
+}
+
+void
+dclargs()
+{
+ union dimfun *df;
+ union arglist *al, *al2, *alb;
+ struct params *a;
+ struct symtab *p, **parr = NULL; /* XXX gcc */
+ char *c;
+ int i;
+
+ argoff = ARGINIT;
+
+ /*
+ * Deal with fun(void) properly.
+ */
+ if (nparams == 1 && lparam->sym->stype == VOID)
+ goto done;
+
+ /*
+ * Generate a list for bfcode().
+ * Parameters were pushed in reverse order.
+ */
+ if (nparams != 0)
+ parr = tmpalloc(sizeof(struct symtab *) * nparams);
+
+ if (nparams)
+ for (a = lparam, i = 0; a != NULL && a != (struct params *)&lpole;
+ a = a->prev) {
+
+ p = a->sym;
+ parr[i++] = p;
+ if (p->stype == FARG) {
+ p->stype = INT;
+ p->ssue = MKSUE(INT);
+ }
+ if (ISARY(p->stype)) {
+ p->stype += (PTR-ARY);
+ p->sdf++;
+ } else if (ISFTN(p->stype)) {
+ werror("function declared as argument");
+ p->stype = INCREF(p->stype);
+ }
+ /* always set aside space, even for register arguments */
+ oalloc(p, &argoff);
+#ifdef STABS
+ if (gflag)
+ stabs_newsym(p);
+#endif
+ }
+ if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) {
+ /*
+ * Check against prototype of oldstyle function.
+ */
+ alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1);
+ for (i = 0; i < nparams; i++) {
+ TWORD type = parr[i]->stype;
+ (al2++)->type = type;
+ if (ISSTR(BTYPE(type)))
+ (al2++)->sue = parr[i]->ssue;
+ while (!ISFTN(type) && !ISARY(type) && type > BTMASK)
+ type = DECREF(type);
+ if (type > BTMASK)
+ (al2++)->df = parr[i]->sdf;
+ }
+ al2->type = TNULL;
+ intcompare = 1;
+ if (chkftn(al, alb))
+ uerror("function doesn't match prototype");
+ intcompare = 0;
+ }
+done: cendarg();
+ c = cftnsp->sname;
+#ifdef GCC_COMPAT
+ c = gcc_findname(cftnsp);
+#endif
+#if 0
+ prolab = getlab();
+ send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
+ cftnsp->sclass == EXTDEF, prolab);
+#endif
+ plabel(prolab); /* after prolog, used in optimization */
+ retlab = getlab();
+ bfcode(parr, nparams);
+ if (xtemps) {
+ /* put arguments in temporaries */
+ for (i = 0; i < nparams; i++) {
+ NODE *q, *r, *s;
+
+ p = parr[i];
+ if (p->stype == STRTY || p->stype == UNIONTY ||
+ cisreg(p->stype) == 0)
+ continue;
+ spname = p;
+ q = buildtree(NAME, 0, 0);
+ r = tempnode(0, p->stype, p->sdf, p->ssue);
+ s = buildtree(ASSIGN, r, q);
+ p->soffset = r->n_lval;
+ p->sflags |= STNODE;
+ ecomp(s);
+ }
+ plabel(getlab()); /* used when spilling */
+ }
+ lparam = NULL;
+ nparams = 0;
+}
+
+/*
+ * reference to a structure or union, with no definition
+ */
+NODE *
+rstruct(char *tag, int soru)
+{
+ struct symtab *p;
+ NODE *q;
+
+ p = (struct symtab *)lookup(tag, STAGNAME);
+ switch (p->stype) {
+
+ case UNDEF:
+ def:
+ q = block(NAME, NIL, NIL, 0, 0, 0);
+ q->n_sp = p;
+ q->n_type = (soru&INSTRUCT) ? STRTY :
+ ((soru&INUNION) ? UNIONTY : ENUMTY);
+ defid(q, (soru&INSTRUCT) ? STNAME :
+ ((soru&INUNION) ? UNAME : ENAME));
+ nfree(q);
+ break;
+
+ case STRTY:
+ if (soru & INSTRUCT)
+ break;
+ goto def;
+
+ case UNIONTY:
+ if (soru & INUNION)
+ break;
+ goto def;
+
+ case ENUMTY:
+ if (!(soru&(INUNION|INSTRUCT)))
+ break;
+ goto def;
+
+ }
+ q = mkty(p->stype, 0, p->ssue);
+ q->n_sue = p->ssue;
+ return q;
+}
+
+void
+moedef(char *name)
+{
+ NODE *q;
+
+ q = block(NAME, NIL, NIL, MOETY, 0, 0);
+ q->n_sp = lookup(name, 0);
+ defid(q, MOE);
+ nfree(q);
+}
+
+/*
+ * begining of structure or union declaration
+ */
+struct rstack *
+bstruct(char *name, int soru)
+{
+ struct rstack *r;
+ struct symtab *s;
+ NODE *q;
+
+ if (name != NULL)
+ s = lookup(name, STAGNAME);
+ else
+ s = NULL;
+
+ r = tmpalloc(sizeof(struct rstack));
+ r->rinstruct = instruct;
+ r->rclass = strunem;
+ r->rstrucoff = strucoff;
+
+ strucoff = 0;
+ instruct = soru;
+ q = block(NAME, NIL, NIL, 0, 0, 0);
+ q->n_sp = s;
+ if (instruct==INSTRUCT) {
+ strunem = MOS;
+ q->n_type = STRTY;
+ if (s != NULL)
+ defid(q, STNAME);
+ } else if(instruct == INUNION) {
+ strunem = MOU;
+ q->n_type = UNIONTY;
+ if (s != NULL)
+ defid(q, UNAME);
+ } else { /* enum */
+ strunem = MOE;
+ q->n_type = ENUMTY;
+ if (s != NULL)
+ defid(q, ENAME);
+ }
+ r->rsym = q->n_sp;
+ r->rlparam = lparam;
+ nfree(q);
+
+ return r;
+}
+
+/*
+ * Called after a struct is declared to restore the environment.
+ */
+NODE *
+dclstruct(struct rstack *r)
+{
+ NODE *n;
+ struct params *l, *m;
+ struct suedef *sue;
+ struct symtab *p;
+ int al, sa, sz;
+ TWORD temp;
+ int i, high, low;
+
+ if (r->rsym == NULL) {
+ sue = permalloc(sizeof(struct suedef));
+ suedefcnt++;
+ sue->suesize = 0;
+ sue->suealign = ALSTRUCT;
+ } else
+ sue = r->rsym->ssue;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf("dclstruct(%s)\n", r->rsym ? r->rsym->sname : "??");
+#endif
+ temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
+ instruct = r->rinstruct;
+ strunem = r->rclass;
+ al = ALSTRUCT;
+
+ high = low = 0;
+
+ if ((l = r->rlparam) == NULL)
+ l = lpole;
+ else
+ l = l->next;
+
+ /* memory for the element array must be allocated first */
+ for (m = l, i = 1; m != NULL; m = m->next)
+ i++;
+ sue->suelem = permalloc(sizeof(struct symtab *) * i);
+
+ for (i = 0; l != NULL; l = l->next) {
+ sue->suelem[i++] = p = l->sym;
+
+ if (p == NULL)
+ cerror("gummy structure member");
+ if (temp == ENUMTY) {
+ if (p->soffset < low)
+ low = p->soffset;
+ if (p->soffset > high)
+ high = p->soffset;
+ p->ssue = sue;
+ continue;
+ }
+ sa = talign(p->stype, p->ssue);
+ if (p->sclass & FIELD) {
+ sz = p->sclass&FLDSIZ;
+ } else {
+ sz = tsize(p->stype, p->sdf, p->ssue);
+ }
+ if (sz > strucoff)
+ strucoff = sz; /* for use with unions */
+ /*
+ * set al, the alignment, to the lcm of the alignments
+ * of the members.
+ */
+ SETOFF(al, sa);
+ }
+ sue->suelem[i] = NULL;
+ SETOFF(strucoff, al);
+
+ if (temp == ENUMTY) {
+ TWORD ty;
+
+#ifdef ENUMSIZE
+ ty = ENUMSIZE(high,low);
+#else
+ if ((char)high == high && (char)low == low)
+ ty = ctype(CHAR);
+ else if ((short)high == high && (short)low == low)
+ ty = ctype(SHORT);
+ else
+ ty = ctype(INT);
+#endif
+ strucoff = tsize(ty, 0, MKSUE(ty));
+ sue->suealign = al = talign(ty, MKSUE(ty));
+ }
+
+ sue->suesize = strucoff;
+ sue->suealign = al;
+
+#ifdef STABS
+ if (gflag)
+ stabs_struct(r->rsym, sue);
+#endif
+
+#ifdef PCC_DEBUG
+ if (ddebug>1) {
+ int i;
+
+ printf("\tsize %d align %d elem %p\n",
+ sue->suesize, sue->suealign, sue->suelem);
+ for (i = 0; sue->suelem[i] != NULL; ++i) {
+ printf("\tmember %s(%p)\n",
+ sue->suelem[i]->sname, sue->suelem[i]);
+ }
+ }
+#endif
+
+ strucoff = r->rstrucoff;
+ if ((lparam = r->rlparam) != NULL)
+ lparam->next = NULL;
+ n = mkty(temp, 0, sue);
+ return n;
+}
+
+/*
+ * error printing routine in parser
+ */
+void yyerror(char *s);
+void
+yyerror(char *s)
+{
+ uerror(s);
+}
+
+void yyaccpt(void);
+void
+yyaccpt(void)
+{
+ ftnend();
+}
+
+/*
+ * p is top of type list given to tymerge later.
+ * Find correct CALL node and declare parameters from there.
+ */
+void
+ftnarg(NODE *p)
+{
+ NODE *q;
+ struct symtab *s;
+
+#ifdef PCC_DEBUG
+ if (ddebug > 2)
+ printf("ftnarg(%p)\n", p);
+#endif
+ /*
+ * Enter argument onto param stack.
+ * Do not declare parameters until later (in dclargs);
+ * the function must be declared first.
+ * put it on the param stack in reverse order, due to the
+ * nature of the stack it will be reclaimed correct.
+ */
+ for (; p->n_op != NAME; p = p->n_left) {
+ if (p->n_op == (UCALL) && p->n_left->n_op == NAME)
+ return; /* Nothing to enter */
+ if (p->n_op == CALL && p->n_left->n_op == NAME)
+ break;
+ }
+
+ p = p->n_right;
+ blevel = 1;
+
+ while (p->n_op == CM) {
+ q = p->n_right;
+ if (q->n_op != ELLIPSIS) {
+ s = lookup((char *)q->n_sp, 0);
+ if (s->stype != UNDEF) {
+ if (s->slevel > 0)
+ uerror("parameter '%s' redefined",
+ s->sname);
+ s = hide(s);
+ }
+ s->soffset = NOOFFSET;
+ s->sclass = PARAM;
+ s->stype = q->n_type;
+ s->sdf = q->n_df;
+ s->ssue = q->n_sue;
+ ssave(s);
+ nparams++;
+#ifdef PCC_DEBUG
+ if (ddebug > 2)
+ printf(" saving sym %s (%p) from (%p)\n",
+ s->sname, s, q);
+#endif
+ }
+ p = p->n_left;
+ }
+ s = lookup((char *)p->n_sp, 0);
+ if (s->stype != UNDEF) {
+ if (s->slevel > 0)
+ uerror("parameter '%s' redefined", s->sname);
+ s = hide(s);
+ }
+ s->soffset = NOOFFSET;
+ s->sclass = PARAM;
+ s->stype = p->n_type;
+ s->sdf = p->n_df;
+ s->ssue = p->n_sue;
+ ssave(s);
+ if (p->n_type != VOID)
+ nparams++;
+ blevel = 0;
+
+#ifdef PCC_DEBUG
+ if (ddebug > 2)
+ printf(" saving sym %s (%p) from (%p)\n",
+ s->sname, s, p);
+#endif
+}
+
+/*
+ * compute the alignment of an object with type ty, sizeoff index s
+ */
+int
+talign(unsigned int ty, struct suedef *sue)
+{
+ int i;
+
+ if (ISPTR(ty))
+ return(ALPOINT); /* shortcut */
+
+ if(sue == NULL && ty!=INT && ty!=CHAR && ty!=SHORT &&
+ ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT) {
+ return(fldal(ty));
+ }
+
+ for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+ switch( (ty>>i)&TMASK ){
+
+ case FTN:
+ cerror("compiler takes alignment of function");
+ case PTR:
+ return(ALPOINT);
+ case ARY:
+ continue;
+ case 0:
+ break;
+ }
+ }
+
+ switch( BTYPE(ty) ){
+
+ case UNIONTY:
+ case ENUMTY:
+ case STRTY:
+ return((unsigned int)sue->suealign);
+ case BOOL:
+ return (ALBOOL);
+ case CHAR:
+ case UCHAR:
+ return (ALCHAR);
+ case FLOAT:
+ return (ALFLOAT);
+ case LDOUBLE:
+ return (ALLDOUBLE);
+ case DOUBLE:
+ return (ALDOUBLE);
+ case LONGLONG:
+ case ULONGLONG:
+ return (ALLONGLONG);
+ case LONG:
+ case ULONG:
+ return (ALLONG);
+ case SHORT:
+ case USHORT:
+ return (ALSHORT);
+ default:
+ return (ALINT);
+ }
+}
+
+/* compute the size associated with type ty,
+ * dimoff d, and sizoff s */
+/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
+OFFSZ
+tsize(TWORD ty, union dimfun *d, struct suedef *sue)
+{
+
+ int i;
+ OFFSZ mult, sz;
+
+ mult = 1;
+
+ for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+ switch( (ty>>i)&TMASK ){
+
+ case FTN:
+ uerror( "cannot take size of function");
+ case PTR:
+ return( SZPOINT(ty) * mult );
+ case ARY:
+ mult *= d->ddim;
+ d++;
+ continue;
+ case 0:
+ break;
+
+ }
+ }
+
+ if (sue == NULL)
+ cerror("bad tsize sue");
+ sz = sue->suesize;
+#ifdef GCC_COMPAT
+ if (ty == VOID)
+ sz = SZCHAR;
+#endif
+ if (ty != STRTY && ty != UNIONTY) {
+ if (sz == 0) {
+ uerror("unknown size");
+ return(SZINT);
+ }
+ } else {
+ if (sue->suelem == NULL)
+ uerror("unknown structure/union/enum");
+ }
+
+ return((unsigned int)sz * mult);
+}
+
+/*
+ * Write last part of wide string.
+ * Do not bother to save wide strings.
+ */
+NODE *
+wstrend(char *str)
+{
+ struct symtab *sp = getsymtab(str, SSTRING|STEMP);
+ struct strsched *sc = tmpalloc(sizeof(struct strsched));
+ NODE *p = block(NAME, NIL, NIL, WCHAR_TYPE+ARY,
+ tmpalloc(sizeof(union dimfun)), MKSUE(WCHAR_TYPE));
+ int i;
+ char *c;
+
+ sp->sclass = ILABEL;
+ sp->soffset = getlab();
+ sp->stype = WCHAR_TYPE+ARY;
+
+ sc = tmpalloc(sizeof(struct strsched));
+ sc->locctr = STRNG;
+ sc->sym = sp;
+ sc->next = strpole;
+ strpole = sc;
+
+ /* length calculation, used only for sizeof */
+ for (i = 0, c = str; *c; ) {
+ if (*c++ == '\\')
+ (void)esccon(&c);
+ i++;
+ }
+ p->n_df->ddim = (i+1) * ((MKSUE(WCHAR_TYPE))->suesize/SZCHAR);
+ p->n_sp = sp;
+ return(p);
+}
+
+/*
+ * Write last part of string.
+ */
+NODE *
+strend(char *str)
+{
+// extern int maystr;
+ struct symtab *s;
+ NODE *p;
+ int i;
+ char *c;
+
+ /* If an identical string is already emitted, just forget this one */
+ str = addstring(str); /* enter string in string table */
+ s = lookup(str, SSTRING); /* check for existance */
+
+ if (s->soffset == 0 /* && maystr == 0 */) { /* No string */
+ struct strsched *sc;
+ s->sclass = ILABEL;
+
+ /*
+ * Delay printout of this string until after the current
+ * function, or the end of the statement.
+ */
+ sc = tmpalloc(sizeof(struct strsched));
+ sc->locctr = STRNG;
+ sc->sym = s;
+ sc->next = strpole;
+ strpole = sc;
+ s->soffset = getlab();
+ }
+
+ p = block(NAME, NIL, NIL, CHAR+ARY,
+ tmpalloc(sizeof(union dimfun)), MKSUE(CHAR));
+#ifdef CHAR_UNSIGNED
+ p->n_type = UCHAR+ARY;
+#endif
+ /* length calculation, used only for sizeof */
+ for (i = 0, c = str; *c; ) {
+ if (*c++ == '\\')
+ (void)esccon(&c);
+ i++;
+ }
+ p->n_df->ddim = i+1;
+ p->n_sp = s;
+ return(p);
+}
+
+/*
+ * Print out new strings, before temp memory is cleared.
+ */
+void
+strprint()
+{
+ char *wr;
+ int i, val, isw;
+ NODE *p = bcon(0);
+
+ while (strpole != NULL) {
+ setloc1(STRNG);
+ deflab1(strpole->sym->soffset);
+ isw = strpole->sym->stype == WCHAR_TYPE+ARY;
+
+ i = 0;
+ wr = strpole->sym->sname;
+ while (*wr != 0) {
+ if (*wr++ == '\\')
+ val = esccon(&wr);
+ else
+ val = (unsigned char)wr[-1];
+ if (isw) {
+ p->n_lval = val;
+ p->n_type = WCHAR_TYPE;
+ ninval(i*(WCHAR_TYPE/SZCHAR),
+ (MKSUE(WCHAR_TYPE))->suesize, p);
+ } else
+ bycode(val, i);
+ i++;
+ }
+ if (isw) {
+ p->n_lval = 0;
+ ninval(i*(WCHAR_TYPE/SZCHAR),
+ (MKSUE(WCHAR_TYPE))->suesize, p);
+ } else {
+ bycode(0, i++);
+ bycode(-1, i);
+ }
+ strpole = strpole->next;
+ }
+ nfree(p);
+}
+
+#if 0
+/*
+ * simulate byte v appearing in a list of integer values
+ */
+void
+putbyte(int v)
+{
+ NODE *p;
+ p = bcon(v);
+ incode( p, SZCHAR );
+ tfree( p );
+// gotscal();
+}
+#endif
+
+/*
+ * update the offset pointed to by poff; return the
+ * offset of a value of size `size', alignment `alignment',
+ * given that off is increasing
+ */
+int
+upoff(int size, int alignment, int *poff)
+{
+ int off;
+
+ off = *poff;
+ SETOFF(off, alignment);
+ if (off < 0)
+ cerror("structure or stack overgrown"); /* wrapped */
+ *poff = off+size;
+ return (off);
+}
+
+/*
+ * allocate p with offset *poff, and update *poff
+ */
+int
+oalloc(struct symtab *p, int *poff )
+{
+ int al, off, tsz;
+ int noff;
+
+ /*
+ * Only generate tempnodes if we are optimizing,
+ * and only for integers, floats or pointers,
+ * and not if the basic type is volatile.
+ */
+/* XXX OLDSTYLE */
+ if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) &&
+ (p->stype < STRTY || ISPTR(p->stype)) &&
+ !ISVOL((p->squal << TSHIFT)) && cisreg(p->stype)) {
+ NODE *tn = tempnode(0, p->stype, p->sdf, p->ssue);
+ p->soffset = tn->n_lval;
+ p->sflags |= STNODE;
+ nfree(tn);
+ return 0;
+ }
+
+ al = talign(p->stype, p->ssue);
+ noff = off = *poff;
+ tsz = tsize(p->stype, p->sdf, p->ssue);
+#ifdef BACKAUTO
+ if (p->sclass == AUTO) {
+ noff = off + tsz;
+ if (noff < 0)
+ cerror("stack overflow");
+ SETOFF(noff, al);
+ off = -noff;
+ } else
+#endif
+ if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR ||
+ p->stype == SHORT || p->stype == USHORT)) {
+ off = upoff(SZINT, ALINT, &noff);
+#ifndef RTOLBYTES
+ off = noff - tsz;
+#endif
+ } else {
+ off = upoff(tsz, al, &noff);
+ }
+
+ if (p->sclass != REGISTER) {
+ /* in case we are allocating stack space for register arguments */
+ if (p->soffset == NOOFFSET)
+ p->soffset = off;
+ else if(off != p->soffset)
+ return(1);
+ }
+
+ *poff = noff;
+ return(0);
+}
+
+/*
+ * Allocate space on the stack for dynamic arrays.
+ * Strategy is as follows:
+ * - first entry is a pointer to the dynamic datatype.
+ * - if it's a one-dimensional array this will be the only entry used.
+ * - if it's a multi-dimensional array the following (numdim-1) integers
+ * will contain the sizes to multiply the indexes with.
+ * - code to write the dimension sizes this will be generated here.
+ * - code to allocate space on the stack will be generated here.
+ */
+static void
+dynalloc(struct symtab *p, int *poff)
+{
+ union dimfun *df;
+ NODE *n, *nn, *tn, *pol;
+ TWORD t;
+ int i, no;
+
+ /*
+ * The pointer to the array is stored in a TEMP node, which number
+ * is in the soffset field;
+ */
+ t = p->stype;
+ p->sflags |= (STNODE|SDYNARRAY);
+ p->stype = INCREF(p->stype); /* Make this an indirect pointer */
+ tn = tempnode(0, p->stype, p->sdf, p->ssue);
+ p->soffset = tn->n_lval;
+
+ df = p->sdf;
+
+ pol = NIL;
+ for (i = 0; ISARY(t); t = DECREF(t), df++) {
+ if (df->ddim >= 0)
+ continue;
+ n = arrstk[i++];
+ nn = tempnode(0, INT, 0, MKSUE(INT));
+ no = nn->n_lval;
+ ecomp(buildtree(ASSIGN, nn, n)); /* Save size */
+
+ df->ddim = -no;
+ n = tempnode(no, INT, 0, MKSUE(INT));
+ if (pol == NIL)
+ pol = n;
+ else
+ pol = buildtree(MUL, pol, n);
+ }
+ /* Create stack gap */
+ if (pol == NIL)
+ uerror("aggregate dynamic array not allowed");
+ else
+ spalloc(tn, pol, tsize(t, 0, p->ssue));
+ arrstkp = 0;
+}
+
+/*
+ * allocate a field of width w
+ * new is 0 if new entry, 1 if redefinition, -1 if alignment
+ */
+int
+falloc(struct symtab *p, int w, int new, NODE *pty)
+{
+ int al,sz,type;
+
+ type = (new<0)? pty->n_type : p->stype;
+
+ /* this must be fixed to use the current type in alignments */
+ switch( new<0?pty->n_type:p->stype ){
+
+ case ENUMTY: {
+ struct suedef *sue;
+ sue = new < 0 ? pty->n_sue : p->ssue;
+ al = sue->suealign;
+ sz = sue->suesize;
+ break;
+ }
+
+ case CHAR:
+ case UCHAR:
+ al = ALCHAR;
+ sz = SZCHAR;
+ break;
+
+ case SHORT:
+ case USHORT:
+ al = ALSHORT;
+ sz = SZSHORT;
+ break;
+
+ case INT:
+ case UNSIGNED:
+ al = ALINT;
+ sz = SZINT;
+ break;
+
+ default:
+ if( new < 0 ) {
+ uerror( "illegal field type" );
+ al = ALINT;
+ } else
+ al = fldal( p->stype );
+ sz =SZINT;
+ }
+
+ if( w > sz ) {
+ uerror( "field too big");
+ w = sz;
+ }
+
+ if( w == 0 ){ /* align only */
+ SETOFF( strucoff, al );
+ if( new >= 0 ) uerror( "zero size field");
+ return(0);
+ }
+
+ if( strucoff%al + w > sz ) SETOFF( strucoff, al );
+ if( new < 0 ) {
+ strucoff += w; /* we know it will fit */
+ return(0);
+ }
+
+ /* establish the field */
+
+ if( new == 1 ) { /* previous definition */
+ if( p->soffset != strucoff || p->sclass != (FIELD|w) ) return(1);
+ }
+ p->soffset = strucoff;
+ strucoff += w;
+ p->stype = type;
+ fldty( p );
+ return(0);
+}
+
+/*
+ * handle unitialized declarations assumed to be not functions:
+ * int a;
+ * extern int a;
+ * static int a;
+ */
+void
+nidcl(NODE *p, int class)
+{
+ struct symtab *sp;
+ int commflag = 0;
+
+ /* compute class */
+ if (class == SNULL) {
+ if (blevel > 1)
+ class = AUTO;
+ else if (blevel != 0 || instruct)
+ cerror( "nidcl error" );
+ else /* blevel = 0 */
+ commflag = 1, class = EXTERN;
+ }
+
+ defid(p, class);
+
+ sp = p->n_sp;
+ /* check if forward decl */
+ if (ISARY(sp->stype) && sp->sdf->ddim == 0)
+ return;
+
+ if (sp->sflags & SASG)
+ return; /* already initialized */
+
+ switch (class) {
+ case EXTDEF:
+ /* simulate initialization by 0 */
+ simpleinit(p->n_sp, bcon(0));
+ break;
+ case EXTERN:
+ if (commflag)
+ lcommadd(p->n_sp);
+ else
+ extdec(p->n_sp);
+ break;
+ case STATIC:
+ if (blevel == 0)
+ lcommadd(p->n_sp);
+ else
+ lcommdec(p->n_sp);
+ break;
+ }
+}
+
+struct lcd {
+ SLIST_ENTRY(lcd) next;
+ struct symtab *sp;
+};
+
+static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw};
+
+/*
+ * Add a local common statement to the printout list.
+ */
+void
+lcommadd(struct symtab *sp)
+{
+ struct lcd *lc, *lcp;
+
+ lcp = NULL;
+ SLIST_FOREACH(lc, &lhead, next) {
+ if (lc->sp == sp)
+ return; /* already exists */
+ if (lc->sp == NULL && lcp == NULL)
+ lcp = lc;
+ }
+ if (lcp == NULL) {
+ lc = permalloc(sizeof(struct lcd));
+ lc->sp = sp;
+ SLIST_INSERT_LAST(&lhead, lc, next);
+ } else
+ lcp->sp = sp;
+}
+
+/*
+ * Delete a local common statement.
+ */
+void
+lcommdel(struct symtab *sp)
+{
+ struct lcd *lc;
+
+ SLIST_FOREACH(lc, &lhead, next) {
+ if (lc->sp == sp) {
+ lc->sp = NULL;
+ return;
+ }
+ }
+}
+
+/*
+ * Print out the remaining common statements.
+ */
+void
+lcommprint(void)
+{
+ struct lcd *lc;
+
+ SLIST_FOREACH(lc, &lhead, next) {
+ if (lc->sp != NULL) {
+ if (lc->sp->sclass == STATIC)
+ lcommdec(lc->sp);
+ else
+ commdec(lc->sp);
+ }
+ }
+}
+
+/*
+ * Merges a type tree into one type. Returns one type node with merged types
+ * and class stored in the su field. Frees all other nodes.
+ * XXX - classes in typedefs?
+ */
+NODE *
+typenode(NODE *p)
+{
+ NODE *l, *sp = NULL;
+ int class = 0, adj, noun, sign;
+ TWORD qual = 0;
+
+ adj = INT; /* INT, LONG or SHORT */
+ noun = UNDEF; /* INT, CHAR or FLOAT */
+ sign = 0; /* 0, SIGNED or UNSIGNED */
+
+ /* Remove initial QUALIFIERs */
+ if (p && p->n_op == QUALIFIER) {
+ qual = p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ /* Handle initial classes special */
+ if (p && p->n_op == CLASS) {
+ class = p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ /* Remove more QUALIFIERs */
+ if (p && p->n_op == QUALIFIER) {
+ qual |= p->n_type;
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ag: if (p && p->n_op == TYPE) {
+ if (p->n_left == NIL) {
+#ifdef CHAR_UNSIGNED
+ if (p->n_type == CHAR)
+ p->n_type = UCHAR;
+#endif
+ if (p->n_type == SIGNED)
+ p->n_type = INT;
+uni: p->n_lval = class;
+ p->n_qual = qual >> TSHIFT;
+ return p;
+ } else if (p->n_left->n_op == QUALIFIER) {
+ qual |= p->n_left->n_type;
+ l = p->n_left;
+ p->n_left = l->n_left;
+ nfree(l);
+ goto ag;
+ } else if (ISSTR(p->n_type)) {
+ /* Save node; needed for return */
+ sp = p;
+ p = p->n_left;
+ }
+ }
+
+ while (p != NIL) {
+ if (p->n_op == QUALIFIER) {
+ qual |= p->n_type;
+ goto next;
+ }
+ if (p->n_op == CLASS) {
+ if (class != 0)
+ uerror("too many storage classes");
+ class = p->n_type;
+ goto next;
+ }
+ if (p->n_op != TYPE)
+ cerror("typenode got notype %d", p->n_op);
+ switch (p->n_type) {
+ case UCHAR:
+ case USHORT: /* may come from typedef */
+ if (sign != 0 || adj != INT)
+ goto bad;
+ noun = p->n_type;
+ break;
+ case SIGNED:
+ case UNSIGNED:
+ if (sign != 0)
+ goto bad;
+ sign = p->n_type;
+ break;
+ case LONG:
+ if (adj == LONG) {
+ adj = LONGLONG;
+ break;
+ }
+ /* FALLTHROUGH */
+ case SHORT:
+ if (adj != INT)
+ goto bad;
+ adj = p->n_type;
+ break;
+ case INT:
+ case CHAR:
+ case FLOAT:
+ case DOUBLE:
+ if (noun != UNDEF)
+ goto bad;
+ noun = p->n_type;
+ break;
+ case VOID:
+ if (noun != UNDEF || adj != INT)
+ goto bad;
+ adj = noun = VOID;
+ break;
+ case STRTY:
+ case UNIONTY:
+ break;
+ default:
+ goto bad;
+ }
+ next:
+ l = p->n_left;
+ nfree(p);
+ p = l;
+ }
+
+ if (sp) {
+ p = sp;
+ goto uni;
+ }
+
+#ifdef CHAR_UNSIGNED
+ if (noun == CHAR && sign == 0)
+ sign = UNSIGNED;
+#endif
+ if (noun == UNDEF) {
+ noun = INT;
+ } else if (noun == FLOAT) {
+ if (sign != 0 || adj == SHORT)
+ goto bad;
+ noun = (adj == LONG ? DOUBLE : FLOAT);
+ } else if (noun == DOUBLE) {
+ if (sign != 0 || adj == SHORT)
+ goto bad;
+ noun = (adj == LONG ? LDOUBLE : DOUBLE);
+ } else if (noun == CHAR && adj != INT)
+ goto bad;
+
+ if (adj != INT && (noun != DOUBLE && noun != LDOUBLE))
+ noun = adj;
+ if (sign == UNSIGNED)
+ noun += (UNSIGNED-INT);
+
+ p = block(TYPE, NIL, NIL, noun, 0, 0);
+ p->n_qual = qual >> TSHIFT;
+ if (strunem != 0)
+ class = strunem;
+ p->n_lval = class;
+ return p;
+
+bad: uerror("illegal type combination");
+ return mkty(INT, 0, 0);
+}
+
+struct tylnk {
+ struct tylnk *next;
+ union dimfun df;
+};
+
+static void tyreduce(NODE *p, struct tylnk **, int *);
+
+static void
+tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim)
+{
+ (*tylkp)->next = tmpalloc(sizeof(struct tylnk));
+ *tylkp = (*tylkp)->next;
+ (*tylkp)->next = NULL;
+ (*tylkp)->df = dim;
+ (*ntdim)++;
+}
+
+/* merge type typ with identifier idp */
+NODE *
+tymerge(NODE *typ, NODE *idp)
+{
+ NODE *p;
+ union dimfun *j;
+ struct tylnk *base, tylnk, *tylkp;
+ unsigned int t;
+ int ntdim, i;
+
+ if (typ->n_op != TYPE)
+ cerror("tymerge: arg 1");
+
+#ifdef PCC_DEBUG
+ if (ddebug > 2) {
+ printf("tymerge(%p,%p)\n", typ, idp);
+ fwalk(typ, eprint, 0);
+ fwalk(idp, eprint, 0);
+ }
+#endif
+
+ idp->n_type = typ->n_type;
+ idp->n_qual = (typ->n_qual << TSHIFT) | idp->n_qual; /* XXX ??? */
+
+ tylkp = &tylnk;
+ tylkp->next = NULL;
+ ntdim = 0;
+
+ tyreduce(idp, &tylkp, &ntdim);
+ idp->n_sue = typ->n_sue;
+
+ for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t))
+ if (ISARY(t) || ISFTN(t))
+ tylkadd(*j++, &tylkp, &ntdim);
+
+ if (ntdim) {
+ union dimfun *a = permalloc(sizeof(union dimfun) * ntdim);
+ dimfuncnt += ntdim;
+ for (i = 0, base = tylnk.next; base; base = base->next, i++)
+ a[i] = base->df;
+ idp->n_df = a;
+ } else
+ idp->n_df = NULL;
+
+ /* now idp is a single node: fix up type */
+
+ idp->n_type = ctype(idp->n_type);
+ idp->n_qual = DECQAL(idp->n_qual);
+
+ /* in case ctype has rewritten things */
+ if ((t = BTYPE(idp->n_type)) != STRTY && t != UNIONTY && t != ENUMTY)
+ idp->n_sue = MKSUE(t);
+
+ if (idp->n_op != NAME) {
+ for (p = idp->n_left; p->n_op != NAME; p = p->n_left)
+ nfree(p);
+ nfree(p);
+ idp->n_op = NAME;
+ }
+
+ return(idp);
+}
+
+/*
+ * Retrieve all CM-separated argument types, sizes and dimensions and
+ * put them in an array.
+ * XXX - can only check first type level, side effects?
+ */
+static union arglist *
+arglist(NODE *n)
+{
+ union arglist *al;
+ NODE *w = n, **ap;
+ int num, cnt, i, j, k;
+ TWORD ty;
+
+#ifdef PCC_DEBUG
+ if (pdebug) {
+ printf("arglist %p\n", n);
+ fwalk(n, eprint, 0);
+ }
+#endif
+ /* First: how much to allocate */
+ for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) {
+ cnt++; /* Number of levels */
+ num++; /* At least one per step */
+ if (w->n_right->n_op == ELLIPSIS)
+ continue;
+ ty = w->n_right->n_type;
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
+ BTYPE(ty) == ENUMTY)
+ num++;
+ while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
+ ty = DECREF(ty);
+ if (ty > BTMASK)
+ num++;
+ }
+ cnt++;
+ ty = w->n_type;
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
+ BTYPE(ty) == ENUMTY)
+ num++;
+ while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
+ ty = DECREF(ty);
+ if (ty > BTMASK)
+ num++;
+ num += 2; /* TEND + last arg type */
+
+ /* Second: Create list to work on */
+ ap = tmpalloc(sizeof(NODE *) * cnt);
+ al = permalloc(sizeof(union arglist) * num);
+ arglistcnt += num;
+
+ for (w = n, i = 0; w->n_op == CM; w = w->n_left)
+ ap[i++] = w->n_right;
+ ap[i] = w;
+
+ /* Third: Create actual arg list */
+ for (k = 0, j = i; j >= 0; j--) {
+ if (ap[j]->n_op == ELLIPSIS) {
+ al[k++].type = TELLIPSIS;
+ ap[j]->n_op = ICON; /* for tfree() */
+ continue;
+ }
+ /* Convert arrays to pointers */
+ if (ISARY(ap[j]->n_type)) {
+ ap[j]->n_type += (PTR-ARY);
+ ap[j]->n_df++;
+ }
+ /* Convert (silently) functions to pointers */
+ if (ISFTN(ap[j]->n_type))
+ ap[j]->n_type = INCREF(ap[j]->n_type);
+ ty = ap[j]->n_type;
+ al[k++].type = ty;
+ if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY ||
+ BTYPE(ty) == ENUMTY)
+ al[k++].sue = ap[j]->n_sue;
+ while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK)
+ ty = DECREF(ty);
+ if (ty > BTMASK)
+ al[k++].df = ap[j]->n_df;
+ }
+ al[k++].type = TNULL;
+ if (k > num)
+ cerror("arglist: k%d > num%d", k, num);
+ tfree(n);
+ if (pdebug)
+ alprint(al, 0);
+ return al;
+}
+
+/*
+ * build a type, and stash away dimensions,
+ * from a parse tree of the declaration
+ * the type is build top down, the dimensions bottom up
+ */
+void
+tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim)
+{
+ union dimfun dim;
+ NODE *r = NULL;
+ int o;
+ TWORD t, q;
+
+ o = p->n_op;
+ if (o == NAME)
+ return;
+
+ t = INCREF(p->n_type);
+ q = p->n_qual;
+ switch (o) {
+ case CALL:
+ t += (FTN-PTR);
+ dim.dfun = arglist(p->n_right);
+ break;
+ case UCALL:
+ t += (FTN-PTR);
+ dim.dfun = NULL;
+ break;
+ case LB:
+ t += (ARY-PTR);
+ if (p->n_right->n_op != ICON) {
+ r = p->n_right;
+ o = RB;
+ } else {
+ dim.ddim = p->n_right->n_lval;
+ nfree(p->n_right);
+#ifdef notdef
+ /* XXX - check dimensions at usage time */
+ if (dim.ddim == 0 && p->n_left->n_op == LB)
+ uerror("null dimension");
+#endif
+ }
+ break;
+ }
+
+ p->n_left->n_type = t;
+ p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual;
+ tyreduce(p->n_left, tylkp, ntdim);
+
+ if (o == LB || o == (UCALL) || o == CALL)
+ tylkadd(dim, tylkp, ntdim);
+ if (o == RB) {
+ dim.ddim = -1;
+ tylkadd(dim, tylkp, ntdim);
+ arrstk[arrstkp++] = r;
+ }
+
+ p->n_sp = p->n_left->n_sp;
+ p->n_type = p->n_left->n_type;
+ p->n_qual = p->n_left->n_qual;
+}
+
+static NODE *
+argcast(NODE *p, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ NODE *u, *r = talloc();
+
+ r->n_op = NAME;
+ r->n_type = t;
+ r->n_qual = 0; /* XXX */
+ r->n_df = d;
+ r->n_sue = sue;
+
+ u = buildtree(CAST, r, p);
+ nfree(u->n_left);
+ r = u->n_right;
+ nfree(u);
+ return r;
+}
+
+#ifndef NO_C_BUILTINS
+/*
+ * replace an alloca function with direct allocation on stack.
+ * return a destination temp node.
+ */
+static NODE *
+builtin_alloca(NODE *f, NODE *a)
+{
+ struct symtab *sp;
+ NODE *t, *u;
+
+#ifdef notyet
+ if (xnobuiltins)
+ return NULL;
+#endif
+
+ if (f->n_op != NAME)
+ return NULL; /* not direct call */
+ sp = f->n_sp;
+
+ /* XXX - strcmp is bad, use pointer comparision, redo someday */
+ if (strcmp(sp->sname, "__builtin_alloca")) /* use GCC name */
+ return NULL; /* not alloca */
+
+ if (a == NULL || a->n_op == CM) {
+ uerror("wrong arg count for alloca");
+ return NULL;
+ }
+ t = tempnode(0, VOID|PTR, 0, MKSUE(INT) /* XXX */);
+ u = tempnode(t->n_lval, VOID|PTR, 0, MKSUE(INT) /* XXX */);
+ spalloc(t, a, SZCHAR);
+ tfree(f);
+ return u;
+}
+#endif
+
+#ifdef PCC_DEBUG
+/*
+ * Print a prototype.
+ */
+static void
+alprint(union arglist *al, int in)
+{
+ int i = 0, j;
+
+ for (; al->type != TNULL; al++) {
+ for (j = in; j > 0; j--)
+ printf(" ");
+ printf("arg %d: ", i++);
+ tprint(stdout, al->type, 0);
+ if (BTYPE(al->type) == STRTY ||
+ BTYPE(al->type) == UNIONTY || BTYPE(al->type) == ENUMTY) {
+ al++;
+ printf("dim %d\n", al->df->ddim);
+ }
+ printf("\n");
+ if (ISFTN(DECREF(al->type))) {
+ al++;
+ alprint(al->df->dfun, in+1);
+ }
+ }
+ if (in == 0)
+ printf("end arglist\n");
+}
+#endif
+/*
+ * Do prototype checking and add conversions before calling a function.
+ * Argument f is function and a is a CM-separated list of arguments.
+ * Returns a merged node (via buildtree() of function and arguments.
+ */
+NODE *
+doacall(NODE *f, NODE *a)
+{
+ NODE *w, *r;
+ union arglist *al;
+ struct ap {
+ struct ap *next;
+ NODE *node;
+ } *at, *apole = NULL;
+ int argidx/* , hasarray = 0*/;
+ TWORD type, arrt;
+
+#ifdef PCC_DEBUG
+ if (ddebug) {
+ printf("doacall.\n");
+ fwalk(f, eprint, 0);
+ if (a)
+ fwalk(a, eprint, 0);
+ }
+#endif
+
+ /* First let MD code do something */
+ calldec(f, a);
+/* XXX XXX hack */
+ if ((f->n_op == CALL || f->n_op == CALL) &&
+ f->n_left->n_op == ADDROF &&
+ f->n_left->n_left->n_op == NAME &&
+ (f->n_left->n_left->n_type & 0x7e0) == 0x4c0)
+ goto build;
+/* XXX XXX hack */
+
+#ifndef NO_C_BUILTINS
+ /* check for alloca */
+ if ((w = builtin_alloca(f, a)))
+ return w;
+#endif
+ /*
+ * Do some basic checks.
+ */
+ if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) {
+ if (Wimplicit_function_declaration) {
+ if (f->n_sp != NULL)
+ werror("no prototype for function '%s()'",
+ f->n_sp->sname);
+ else
+ werror("no prototype for function pointer");
+ }
+ /* floats must be cast to double */
+ if (a == NULL)
+ goto build;
+ for (w = a; w->n_op == CM; w = w->n_left) {
+ if (w->n_right->n_type != FLOAT)
+ continue;
+ w->n_right = argcast(w->n_right, DOUBLE,
+ NULL, MKSUE(DOUBLE));
+ }
+ if (a->n_type == FLOAT) {
+ MKTY(a, DOUBLE, 0, 0);
+ }
+ goto build;
+ }
+ if (al->type == VOID) {
+ if (a != NULL)
+ uerror("function takes no arguments");
+ goto build; /* void function */
+ } else {
+ if (a == NULL) {
+ uerror("function needs arguments");
+ goto build;
+ }
+ }
+#ifdef PCC_DEBUG
+ if (pdebug) {
+ printf("arglist for %p\n",
+ f->n_sp != NULL ? f->n_sp->sname : "function pointer");
+ alprint(al, 0);
+ }
+#endif
+
+ /*
+ * Create a list of pointers to the nodes given as arg.
+ */
+ for (w = a; w->n_op == CM; w = w->n_left) {
+ at = tmpalloc(sizeof(struct ap));
+ at->node = w->n_right;
+ at->next = apole;
+ apole = at;
+ }
+ at = tmpalloc(sizeof(struct ap));
+ at->node = w;
+ at->next = apole;
+ apole = at;
+
+ /*
+ * Do the typechecking by walking up the list.
+ */
+ argidx = 1;
+ while (al->type != TNULL) {
+ if (al->type == TELLIPSIS) {
+ /* convert the rest of float to double */
+ for (; apole; apole = apole->next) {
+ if (apole->node->n_type != FLOAT)
+ continue;
+ MKTY(apole->node, DOUBLE, 0, 0);
+ }
+ goto build;
+ }
+ if (apole == NULL) {
+ uerror("too few arguments to function");
+ goto build;
+ }
+/* al = prototyp, apole = argument till ftn */
+/* type = argumentets typ, arrt = prototypens typ */
+ type = apole->node->n_type;
+ arrt = al->type;
+#if 0
+ if ((hasarray = ISARY(arrt)))
+ arrt += (PTR-ARY);
+#endif
+ if (ISARY(type))
+ type += (PTR-ARY);
+
+ /* Check structs */
+ if (type <= BTMASK && arrt <= BTMASK) {
+ if (type != arrt) {
+ if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) {
+incomp: uerror("incompatible types for arg %d",
+ argidx);
+ } else {
+ MKTY(apole->node, arrt, 0, 0)
+ }
+ } else if (ISSOU(BTYPE(type))) {
+ if (apole->node->n_sue != al[1].sue)
+ goto incomp;
+ }
+ goto out;
+ }
+
+ /* Hereafter its only pointers (or arrays) left */
+ /* Check for struct/union intermixing with other types */
+ if (((type <= BTMASK) && ISSOU(BTYPE(type))) ||
+ ((arrt <= BTMASK) && ISSOU(BTYPE(arrt))))
+ goto incomp;
+
+ /* Check for struct/union compatibility */
+ if (type == arrt) {
+ if (ISSOU(BTYPE(type))) {
+ if (apole->node->n_sue == al[1].sue)
+ goto out;
+ } else
+ goto out;
+ }
+ if (BTYPE(arrt) == ENUMTY && BTYPE(type) == INT &&
+ (arrt & ~BTMASK) == (type & ~BTMASK))
+ goto skip; /* XXX enumty destroyed in optim() */
+ if (BTYPE(arrt) == VOID && type > BTMASK)
+ goto skip; /* void *f = some pointer */
+ if (arrt > BTMASK && BTYPE(type) == VOID)
+ goto skip; /* some *f = void pointer */
+ if (apole->node->n_op == ICON && apole->node->n_lval == 0)
+ goto skip; /* Anything assigned a zero */
+
+ if ((type & ~BTMASK) == (arrt & ~BTMASK)) {
+ /* do not complain for intermixed char/uchar */
+ if ((BTYPE(type) == CHAR || BTYPE(type) == UCHAR) &&
+ (BTYPE(arrt) == CHAR || BTYPE(arrt) == UCHAR))
+ goto skip;
+ }
+
+ werror("implicit conversion of argument %d due to prototype",
+ argidx);
+
+skip: if (ISSTR(BTYPE(arrt))) {
+ MKTY(apole->node, arrt, 0, al[1].sue)
+ } else {
+ MKTY(apole->node, arrt, 0, 0)
+ }
+
+out: al++;
+ if (ISSTR(BTYPE(arrt)))
+ al++;
+#if 0
+ while (arrt > BTMASK && !ISFTN(arrt))
+ arrt = DECREF(arrt);
+ if (ISFTN(arrt) || hasarray)
+ al++;
+#else
+ while (arrt > BTMASK) {
+ if (ISARY(arrt) || ISFTN(arrt)) {
+ al++;
+ break;
+ }
+ arrt = DECREF(arrt);
+ }
+#endif
+ apole = apole->next;
+ argidx++;
+ }
+ if (apole != NULL)
+ uerror("too many arguments to function");
+
+build: return buildtree(a == NIL ? UCALL : CALL, f, a);
+}
+
+static int
+chk2(TWORD type, union dimfun *dsym, union dimfun *ddef)
+{
+ while (type > BTMASK) {
+ switch (type & TMASK) {
+ case ARY:
+ /* may be declared without dimension */
+ if (dsym->ddim == 0)
+ dsym->ddim = ddef->ddim;
+ if (ddef->ddim && dsym->ddim != ddef->ddim)
+ return 1;
+ dsym++, ddef++;
+ break;
+ case FTN:
+ /* old-style function headers with function pointers
+ * will most likely not have a prototype.
+ * This is not considered an error. */
+ if (ddef->dfun == NULL) {
+#ifdef notyet
+ werror("declaration not a prototype");
+#endif
+ } else if (chkftn(dsym->dfun, ddef->dfun))
+ return 1;
+ dsym++, ddef++;
+ break;
+ }
+ type = DECREF(type);
+ }
+ return 0;
+}
+
+/*
+ * Compare two function argument lists to see if they match.
+ */
+int
+chkftn(union arglist *usym, union arglist *udef)
+{
+ TWORD t2;
+ int ty, tyn;
+
+ if (usym == NULL)
+ return 0;
+ if (cftnsp != NULL && udef == NULL && usym->type == VOID)
+ return 0; /* foo() { function with foo(void); prototype */
+ if (udef == NULL && usym->type != TNULL)
+ return 1;
+ while (usym->type != TNULL) {
+ if (usym->type == udef->type)
+ goto done;
+ /*
+ * If an old-style declaration, then all types smaller than
+ * int are given as int parameters.
+ */
+ if (intcompare) {
+ ty = BTYPE(usym->type);
+ tyn = BTYPE(udef->type);
+ if (ty == tyn || ty != INT)
+ return 1;
+ if (tyn == CHAR || tyn == UCHAR ||
+ tyn == SHORT || tyn == USHORT)
+ goto done;
+ return 1;
+ } else
+ return 1;
+
+done: ty = BTYPE(usym->type);
+ t2 = usym->type;
+ if (ISSTR(ty)) {
+ usym++, udef++;
+ if (usym->sue != udef->sue)
+ return 1;
+ }
+
+ while (ISFTN(t2) == 0 && ISARY(t2) == 0 && t2 > BTMASK)
+ t2 = DECREF(t2);
+ if (t2 > BTMASK) {
+ usym++, udef++;
+ if (chk2(t2, usym->df, udef->df))
+ return 1;
+ }
+ usym++, udef++;
+ }
+ if (usym->type != udef->type)
+ return 1;
+ return 0;
+}
+
+void
+fixtype(NODE *p, int class)
+{
+ unsigned int t, type;
+ int mod1, mod2;
+ /* fix up the types, and check for legality */
+
+ if( (type = p->n_type) == UNDEF ) return;
+ if ((mod2 = (type&TMASK))) {
+ t = DECREF(type);
+ while( mod1=mod2, mod2 = (t&TMASK) ){
+ if( mod1 == ARY && mod2 == FTN ){
+ uerror( "array of functions is illegal" );
+ type = 0;
+ }
+ else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
+ uerror( "function returns illegal type" );
+ type = 0;
+ }
+ t = DECREF(t);
+ }
+ }
+
+ /* detect function arguments, watching out for structure declarations */
+ if (instruct && ISFTN(type)) {
+ uerror("function illegal in structure or union");
+ type = INCREF(type);
+ }
+ p->n_type = type;
+}
+
+/*
+ * give undefined version of class
+ */
+int
+uclass(int class)
+{
+ if (class == SNULL)
+ return(EXTERN);
+ else if (class == STATIC)
+ return(USTATIC);
+ else if (class == FORTRAN)
+ return(UFORTRAN);
+ else
+ return(class);
+}
+
+int
+fixclass(int class, TWORD type)
+{
+ /* first, fix null class */
+ if (class == SNULL) {
+ if (instruct&INSTRUCT)
+ class = MOS;
+ else if (instruct&INUNION)
+ class = MOU;
+ else if (blevel == 0)
+ class = EXTDEF;
+ else
+ class = AUTO;
+ }
+
+ /* now, do general checking */
+
+ if( ISFTN( type ) ){
+ switch( class ) {
+ default:
+ uerror( "function has illegal storage class" );
+ case AUTO:
+ class = EXTERN;
+ case EXTERN:
+ case EXTDEF:
+ case FORTRAN:
+ case TYPEDEF:
+ case STATIC:
+ case UFORTRAN:
+ case USTATIC:
+ ;
+ }
+ }
+
+ if( class&FIELD ){
+ if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
+ return( class );
+ }
+
+ switch( class ){
+
+ case MOU:
+ if( !(instruct&INUNION) ) uerror( "illegal MOU class" );
+ return( class );
+
+ case MOS:
+ if( !(instruct&INSTRUCT) ) uerror( "illegal MOS class" );
+ return( class );
+
+ case MOE:
+ if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal MOE class" );
+ return( class );
+
+ case REGISTER:
+ if (blevel == 0)
+ uerror( "illegal register declaration" );
+ if (blevel == 1)
+ return(PARAM);
+ else
+ return(AUTO);
+
+ case AUTO:
+ if( blevel < 2 ) uerror( "illegal ULABEL class" );
+ return( class );
+
+ case UFORTRAN:
+ case FORTRAN:
+# ifdef NOFORTRAN
+ NOFORTRAN; /* a condition which can regulate the FORTRAN usage */
+# endif
+ if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
+ else {
+ type = DECREF(type);
+ if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
+ uerror( "fortran function has wrong type" );
+ }
+ }
+ case STNAME:
+ case UNAME:
+ case ENAME:
+ case EXTERN:
+ case STATIC:
+ case EXTDEF:
+ case TYPEDEF:
+ case USTATIC:
+ return( class );
+
+ default:
+ cerror( "illegal class: %d", class );
+ /* NOTREACHED */
+
+ }
+ return 0; /* XXX */
+}
+
+/*
+ * Generates a goto statement; sets up label number etc.
+ */
+void
+gotolabel(char *name)
+{
+ struct symtab *s = lookup(name, SLBLNAME);
+
+ if (s->soffset == 0)
+ s->soffset = -getlab();
+ branch(s->soffset < 0 ? -s->soffset : s->soffset);
+}
+
+/*
+ * Sets a label for gotos.
+ */
+void
+deflabel(char *name)
+{
+ struct symtab *s = lookup(name, SLBLNAME);
+
+ if (s->soffset > 0)
+ uerror("label '%s' redefined", name);
+ if (s->soffset == 0)
+ s->soffset = getlab();
+ if (s->soffset < 0)
+ s->soffset = -s->soffset;
+ plabel( s->soffset);
+}
+
+struct symtab *
+getsymtab(char *name, int flags)
+{
+ struct symtab *s;
+
+ if (flags & STEMP) {
+ s = tmpalloc(sizeof(struct symtab));
+ } else {
+ s = permalloc(sizeof(struct symtab));
+ symtabcnt++;
+ }
+ s->sname = name;
+ s->snext = NULL;
+ s->stype = UNDEF;
+ s->squal = 0;
+ s->sclass = SNULL;
+ s->sflags = flags & SMASK;
+ s->soffset = 0;
+ s->slevel = blevel;
+ return s;
+}
+
+#ifdef PCC_DEBUG
+static char *
+ccnames[] = { /* names of storage classes */
+ "SNULL",
+ "AUTO",
+ "EXTERN",
+ "STATIC",
+ "REGISTER",
+ "EXTDEF",
+ "LABEL",
+ "ULABEL",
+ "MOS",
+ "PARAM",
+ "STNAME",
+ "MOU",
+ "UNAME",
+ "TYPEDEF",
+ "FORTRAN",
+ "ENAME",
+ "MOE",
+ "UFORTRAN",
+ "USTATIC",
+ };
+
+char *
+scnames(int c)
+{
+ /* return the name for storage class c */
+ static char buf[12];
+ if( c&FIELD ){
+ snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ );
+ return( buf );
+ }
+ return( ccnames[c] );
+ }
+#endif
--- /dev/null
+++ usr.bin/pcc/ccom/init.c
@@ -0,0 +1,961 @@
+/* $Id: init.c,v 1.30 2007/09/24 20:34:03 ragge Exp $ */
+
+/*
+ * Copyright (c) 2004, 2007 Anders Magnusson (ragge at ludd.ltu.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 "pass1.h"
+#include <string.h>
+
+/*
+ * Four machine-dependent routines may be called during initialization:
+ *
+ * instring(char *str) - Print out a string.
+ * zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ.
+ * infld(CONSZ off, int fsz, CONSZ val)
+ * - sets the bitfield val starting at off and size fsz.
+ * inval(CONSZ off, int fsz, NODE *)
+ * - prints an integer constant which may have
+ * a label associated with it, located at off and
+ * size fsz.
+ *
+ * Initialization may be of different kind:
+ * - Initialization at compile-time, all values are constants and laid
+ * out in memory. Static or extern variables outside functions.
+ * - Initialization at run-time, written to their values as code.
+ *
+ * Currently run-time-initialized variables are only initialized by using
+ * move instructions. An optimization might be to detect that it is
+ * initialized with constants and therefore copied from readonly memory.
+ */
+
+/*
+ * The base element(s) of an initialized variable is kept in a linked
+ * list, allocated while initialized.
+ *
+ * When a scalar is found, entries are popped of the instk until it's
+ * possible to find an entry for a new scalar; then onstk() is called
+ * to get the correct type and size of that scalar.
+ *
+ * If a right brace is found, pop the stack until a matching left brace
+ * were found while filling the elements with zeros. This left brace is
+ * also marking where the current level is for designated initializations.
+ *
+ * Position entries are increased when traversing back down into the stack.
+ */
+
+/*
+ * Good-to-know entries from symtab:
+ * soffset - # of bits from beginning of this structure.
+ */
+
+/*
+ * TO FIX:
+ * - Alignment of structs on like i386 char members.
+ */
+
+int idebug;
+
+/*
+ * Struct used in array initialisation.
+ */
+static struct instk {
+ struct instk *in_prev; /* linked list */
+ struct symtab **in_xp; /* member in structure initializations */
+ struct symtab *in_sym; /* stab index */
+ union dimfun *in_df; /* dimenston of array */
+ TWORD in_t; /* type for this level */
+ int in_n; /* number of arrays seen so far */
+ int in_fl; /* flag which says if this level is controlled by {} */
+} *pstk, pbase;
+
+static struct symtab *csym;
+
+#define ISSOU(ty) (ty == STRTY || ty == UNIONTY)
+
+#ifdef PCC_DEBUG
+static void prtstk(struct instk *in);
+#endif
+
+/*
+ * Linked lists for initializations.
+ */
+struct ilist {
+ struct ilist *next;
+ CONSZ off; /* bit offset of this entry */
+ int fsz; /* bit size of this entry */
+ NODE *n; /* node containing this data info */
+};
+
+struct llist {
+ SLIST_ENTRY(llist) next;
+ CONSZ begsz; /* bit offset of this entry */
+ struct ilist *il;
+} *curll;
+static SLIST_HEAD(, llist) lpole;
+static CONSZ basesz;
+static int numents; /* # of array entries allocated */
+
+static struct ilist *
+getil(struct ilist *next, CONSZ b, int sz, NODE *n)
+{
+ struct ilist *il = tmpalloc(sizeof(struct ilist));
+
+ il->off = b;
+ il->fsz = sz;
+ il->n = n;
+ il->next = next;
+ return il;
+}
+
+/*
+ * Allocate a new struct defining a block of initializers appended to the
+ * end of the llist. Return that entry.
+ */
+static struct llist *
+getll(void)
+{
+ struct llist *ll;
+
+ ll = tmpalloc(sizeof(struct llist));
+ ll->begsz = numents * basesz;
+ ll->il = NULL;
+ SLIST_INSERT_LAST(&lpole, ll, next);
+ numents++;
+ return ll;
+}
+
+/*
+ * Return structure containing off bitnumber.
+ * Allocate more entries, if needed.
+ * This is not bright implemented.
+ */
+static struct llist *
+setll(OFFSZ off)
+{
+ struct llist *ll;
+
+ /* Ensure that we have enough entries */
+ while (off >= basesz * numents)
+ (void)getll();
+ SLIST_FOREACH(ll, &lpole, next)
+ if (ll->begsz <= off && ll->begsz + basesz > off)
+ break;
+ return ll; /* ``cannot fail'' */
+}
+
+/*
+ * beginning of initialization; allocate space to store initialized data.
+ * remember storage class for writeout in endinit().
+ * p is the newly declarated type.
+ */
+void
+beginit(struct symtab *sp)
+{
+ struct instk *is = &pbase;
+ struct llist *ll;
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("beginit(), sclass %s\n", scnames(sp->sclass));
+#endif
+
+ csym = sp;
+
+ numents = 0; /* no entries in array list */
+ if (ISARY(sp->stype))
+ basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->ssue);
+ else
+ basesz = tsize(DECREF(sp->stype), sp->sdf, sp->ssue);
+ SLIST_INIT(&lpole);
+ curll = ll = getll(); /* at least first entry in list */
+
+ /* first element */
+ is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_n = 0;
+ is->in_t = sp->stype;
+ is->in_sym = sp;
+ is->in_df = sp->sdf;
+ is->in_fl = 0;
+ is->in_prev = NULL;
+ pstk = is;
+}
+
+/*
+ * Push a new entry on the initializer stack.
+ * The new entry will be "decremented" to the new sub-type of the previous
+ * entry when called.
+ * Popping of entries is done elsewhere.
+ */
+static void
+stkpush(void)
+{
+ struct instk *is;
+ struct symtab *sq, *sp;
+ TWORD t;
+
+ if (pstk == NULL) {
+ sp = csym;
+ t = 0;
+ } else {
+ t = pstk->in_t;
+ sp = pstk->in_sym;
+ }
+
+#ifdef PCC_DEBUG
+ if (idebug) {
+ printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass));
+ tprint(stdout, t, 0);
+ }
+#endif
+
+ /*
+ * Figure out what the next initializer will be, and push it on
+ * the stack. If this is an array, just decrement type, if it
+ * is a struct or union, extract the next element.
+ */
+ is = tmpalloc(sizeof(struct instk));
+ is->in_fl = 0;
+ is->in_n = 0;
+ if (pstk == NULL) {
+ /* stack empty */
+ is->in_xp = ISSOU(sp->stype) ? sp->ssue->suelem : NULL;
+ is->in_t = sp->stype;
+ is->in_sym = sp;
+ is->in_df = sp->sdf;
+ } else if (ISSOU(t)) {
+ sq = *pstk->in_xp;
+ if (sq == NULL) {
+ uerror("excess of initializing elements");
+ } else {
+ is->in_xp = ISSOU(sq->stype) ? sq->ssue->suelem : 0;
+ is->in_t = sq->stype;
+ is->in_sym = sq;
+ is->in_df = sq->sdf;
+ }
+ } else if (ISARY(t)) {
+ is->in_xp = ISSOU(DECREF(t)) ? pstk->in_sym->ssue->suelem : 0;
+ is->in_t = DECREF(t);
+ is->in_sym = sp;
+ if (pstk->in_df->ddim && pstk->in_n >= pstk->in_df->ddim) {
+ werror("excess of initializing elements");
+ pstk->in_n--;
+ }
+ if (ISARY(is->in_t))
+ is->in_df = pstk->in_df+1;
+ } else
+ uerror("too many left braces");
+ is->in_prev = pstk;
+ pstk = is;
+
+#ifdef PCC_DEBUG
+ if (idebug) {
+ printf(" newtype ");
+ tprint(stdout, is->in_t, 0);
+ printf("\n");
+ }
+#endif
+}
+
+/*
+ * pop down to either next level that can handle a new initializer or
+ * to the next braced level.
+ */
+static void
+stkpop(void)
+{
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("stkpop\n");
+#endif
+ for (; pstk; pstk = pstk->in_prev) {
+ if (pstk->in_t == STRTY) {
+ pstk->in_xp++;
+ if (*pstk->in_xp != NULL)
+ break;
+ }
+ if (ISSOU(pstk->in_t) && pstk->in_fl)
+ break; /* need } */
+ if (ISARY(pstk->in_t)) {
+ pstk->in_n++;
+ if (pstk->in_fl)
+ break;
+ if (pstk->in_df->ddim == 0 ||
+ pstk->in_n < pstk->in_df->ddim)
+ break; /* ger more elements */
+ }
+ }
+#ifdef PCC_DEBUG
+ if (idebug > 1)
+ prtstk(pstk);
+#endif
+}
+
+/*
+ * Count how many elements an array may consist of.
+ */
+static int
+acalc(struct instk *is, int n)
+{
+ if (is == NULL || !ISARY(is->in_t))
+ return 0;
+ return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n;
+}
+
+/*
+ * Find current bit offset of the top element on the stack from
+ * the beginning of the aggregate.
+ */
+static CONSZ
+findoff(void)
+{
+ struct instk *is;
+ OFFSZ off;
+
+#ifdef PCC_DEBUG
+ if (ISARY(pstk->in_t) || ISSOU(pstk->in_t))
+ cerror("findoff on bad type");
+#endif
+
+ /*
+ * Offset calculations. If:
+ * - previous type is STRTY, soffset has in-struct offset.
+ * - this type is ARY, offset is ninit*stsize.
+ */
+ for (off = 0, is = pstk; is; is = is->in_prev) {
+ if (is->in_prev && is->in_prev->in_t == STRTY)
+ off += is->in_sym->soffset;
+ if (ISARY(is->in_t)) {
+ /* suesize is the basic type, so adjust */
+ TWORD t = is->in_t;
+ OFFSZ o;
+ while (ISARY(t))
+ t = DECREF(t);
+ o = ISPTR(t) ? SZPOINT(t) : is->in_sym->ssue->suesize;
+ off += o * acalc(is, 1);
+ while (is->in_prev && ISARY(is->in_prev->in_t)) {
+ if (is->in_prev->in_prev &&
+ is->in_prev->in_prev->in_t == STRTY)
+ off += is->in_sym->soffset;
+ is = is->in_prev;
+ }
+ }
+ }
+ if (idebug>1) {
+ printf("findoff: off %lld\n", off);
+ prtstk(pstk);
+ }
+ return off;
+}
+
+/*
+ * Insert the node p with size fsz at position off.
+ * Bit fields are already dealt with, so a node of correct type
+ * with correct alignment and correct bit offset is given.
+ */
+static void
+nsetval(CONSZ off, int fsz, NODE *p)
+{
+ struct llist *ll;
+ struct ilist *il;
+
+ if (idebug>1)
+ printf("setval: off %lld fsz %d p %p\n", off, fsz, p);
+
+ if (fsz == 0)
+ return;
+
+ ll = setll(off);
+ off -= ll->begsz;
+ if (ll->il == NULL) {
+ ll->il = getil(NULL, off, fsz, p);
+ } else {
+ il = ll->il;
+ if (il->off > off) {
+ ll->il = getil(ll->il, off, fsz, p);
+ } else {
+ for (il = ll->il; il->next; il = il->next)
+ if (il->off <= off && il->next->off > off)
+ break;
+ if (il->off == off) {
+ /* replace */
+ nfree(il->n);
+ il->n = p;
+ } else
+ il->next = getil(il->next, off, fsz, p);
+ }
+ }
+}
+
+/*
+ * Align data and set correct location.
+ */
+static void
+setscl(struct symtab *sp)
+{
+ setloc1((sp->squal << TSHIFT) & CON ? RDATA : DATA);
+ defalign(talign(sp->stype, sp->ssue));
+ if (sp->sclass == EXTDEF ||
+ (sp->sclass == STATIC && sp->slevel == 0)) {
+ defnam(sp);
+ } else {
+ if (sp->soffset == NOOFFSET)
+ cerror("setscl");
+ deflab1(sp->soffset);
+ }
+}
+
+/*
+ * take care of generating a value for the initializer p
+ * inoff has the current offset (last bit written)
+ * in the current word being generated
+ */
+void
+scalinit(NODE *p)
+{
+ CONSZ woff;
+ NODE *q;
+ int fsz;
+
+#ifdef PCC_DEBUG
+ if (idebug > 2) {
+ printf("scalinit(%p)\n", p);
+ fwalk(p, eprint, 0);
+ prtstk(pstk);
+ }
+#endif
+
+ if (nerrors)
+ return;
+
+ p = optim(p);
+
+ if (csym->sclass != AUTO && p->n_op != ICON &&
+ p->n_op != FCON && p->n_op != NAME)
+ cerror("scalinit not leaf");
+
+ /* Out of elements? */
+ if (pstk == NULL) {
+ uerror("excess of initializing elements");
+ return;
+ }
+
+ /*
+ * Get to the simple type if needed.
+ */
+ while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
+ stkpush();
+
+ /* let buildtree do typechecking (and casting) */
+ q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_sym->sdf,
+ pstk->in_sym->ssue);
+ p = buildtree(ASSIGN, q, p);
+ nfree(p->n_left);
+ q = optim(p->n_right);
+ nfree(p);
+
+ /* bitfield sizes are special */
+ if (pstk->in_sym->sclass & FIELD)
+ fsz = -(pstk->in_sym->sclass & FLDSIZ);
+ else
+ fsz = tsize(pstk->in_t, pstk->in_sym->sdf, pstk->in_sym->ssue);
+ woff = findoff();
+
+ nsetval(woff, fsz, q);
+
+ stkpop();
+#ifdef PCC_DEBUG
+ if (idebug > 2) {
+ printf("scalinit e(%p)\n", p);
+ }
+#endif
+}
+
+/*
+ * Generate code to insert a value into a bitfield.
+ */
+static void
+insbf(OFFSZ off, int fsz, int val)
+{
+ struct symtab sym;
+ NODE *p, *r;
+ TWORD typ;
+
+#ifdef PCC_DEBUG
+ if (idebug > 1)
+ printf("insbf: off %lld fsz %d val %d\n", off, fsz, val);
+#endif
+
+ if (fsz == 0)
+ return;
+
+ /* small opt: do char instead of bf asg */
+ if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR)
+ typ = CHAR;
+ else
+ typ = INT;
+ /* Fake a struct reference */
+ spname = csym;
+ p = buildtree(ADDROF,
+ buildtree(NAME, NIL, NIL), NIL);
+ r = block(ICON, NIL, NIL, typ, 0, MKSUE(typ));
+ sym.stype = typ;
+ sym.squal = 0;
+ sym.sdf = 0;
+ sym.ssue = MKSUE(typ);
+ sym.soffset = off;
+ sym.sclass = typ == INT ? FIELD | fsz : MOU;
+ r->n_sp = &sym;
+ p = block(STREF, p, r, INT, 0, MKSUE(INT));
+ ecode(buildtree(ASSIGN, stref(p), bcon(val)));
+}
+
+/*
+ * Clear a bitfield, starting at off and size fsz.
+ */
+static void
+clearbf(OFFSZ off, OFFSZ fsz)
+{
+ /* Pad up to the next even initializer */
+ if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) {
+ int ba = ((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off;
+ if (ba > fsz)
+ ba = fsz;
+ insbf(off, ba, 0);
+ off += ba;
+ fsz -= ba;
+ }
+ while (fsz >= SZCHAR) {
+ insbf(off, SZCHAR, 0);
+ off += SZCHAR;
+ fsz -= SZCHAR;
+ }
+ if (fsz)
+ insbf(off, fsz, 0);
+}
+
+/*
+ * final step of initialization.
+ * print out init nodes and generate copy code (if needed).
+ */
+void
+endinit(void)
+{
+ struct llist *ll;
+ struct ilist *il;
+ int fsz;
+ OFFSZ lastoff, tbit;
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("endinit()\n");
+#endif
+
+ if (csym->sclass != AUTO)
+ setscl(csym);
+
+ /* Calculate total block size */
+ if (ISARY(csym->stype) && csym->sdf->ddim == 0) {
+ tbit = numents*basesz; /* open-ended arrays */
+ csym->sdf->ddim = numents;
+ if (csym->sclass == AUTO) { /* Get stack space */
+ csym->soffset = NOOFFSET;
+ oalloc(csym, &autooff);
+ }
+ } else
+ tbit = tsize(csym->stype, csym->sdf, csym->ssue);
+
+ /* Traverse all entries and print'em out */
+ lastoff = 0;
+ SLIST_FOREACH(ll, &lpole, next) {
+ for (il = ll->il; il; il = il->next) {
+#ifdef PCC_DEBUG
+ if (idebug > 1) {
+ printf("off %lld size %d val %lld type ",
+ ll->begsz+il->off, il->fsz, il->n->n_lval);
+ tprint(stdout, il->n->n_type, 0);
+ printf("\n");
+ }
+#endif
+ fsz = il->fsz;
+ if (csym->sclass == AUTO) {
+ struct symtab sym;
+ NODE *p, *r, *n;
+
+ if (ll->begsz + il->off > lastoff)
+ clearbf(lastoff,
+ (ll->begsz + il->off) - lastoff);
+
+ /* Fake a struct reference */
+ spname = csym;
+ p = buildtree(ADDROF,
+ buildtree(NAME, NIL, NIL), NIL);
+ n = il->n;
+ r = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
+ sym.stype = n->n_type;
+ sym.squal = n->n_qual;
+ sym.sdf = n->n_df;
+ sym.ssue = n->n_sue;
+ sym.soffset = ll->begsz + il->off;
+ sym.sclass = fsz < 0 ? FIELD | -fsz : 0;
+ r->n_sp = &sym;
+ p = block(STREF, p, r, INT, 0, MKSUE(INT));
+ ecode(buildtree(ASSIGN, stref(p), il->n));
+ if (fsz < 0)
+ fsz = -fsz;
+
+ } else {
+ if (ll->begsz + il->off > lastoff)
+ zbits(lastoff,
+ (ll->begsz + il->off) - lastoff);
+ if (fsz < 0) {
+ fsz = -fsz;
+ infld(il->off, fsz, il->n->n_lval);
+ } else
+ ninval(il->off, fsz, il->n);
+ nfree(il->n);
+ }
+ lastoff = ll->begsz + il->off + fsz;
+ }
+ }
+ if (csym->sclass == AUTO) {
+ clearbf(lastoff, tbit-lastoff);
+ } else
+ zbits(lastoff, tbit-lastoff);
+}
+
+/*
+ * process an initializer's left brace
+ */
+void
+ilbrace()
+{
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("ilbrace()\n");
+#endif
+
+ if (pstk == NULL)
+ return;
+
+ stkpush();
+ pstk->in_fl = 1; /* mark lbrace */
+#ifdef PCC_DEBUG
+ if (idebug > 1)
+ prtstk(pstk);
+#endif
+}
+
+/*
+ * called when a '}' is seen
+ */
+void
+irbrace()
+{
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("irbrace()\n");
+ if (idebug > 2)
+ prtstk(pstk);
+#endif
+
+ if (pstk == NULL)
+ return;
+
+ /* Got right brace, search for corresponding in the stack */
+ for (; pstk->in_prev != NULL; pstk = pstk->in_prev) {
+ if(!pstk->in_fl)
+ continue;
+
+ /* we have one now */
+
+ pstk->in_fl = 0; /* cancel { */
+ if (ISARY(pstk->in_t))
+ pstk->in_n = pstk->in_df->ddim;
+ else if (pstk->in_t == STRTY) {
+ while (pstk->in_xp[1] != NULL)
+ pstk->in_xp++;
+ }
+ stkpop();
+ return;
+ }
+}
+
+/*
+ * Create a new init stack based on given elements.
+ */
+static void
+mkstack(NODE *p)
+{
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("mkstack: %p\n", p);
+#endif
+
+ if (p == NULL)
+ return;
+ mkstack(p->n_left);
+
+ switch (p->n_op) {
+ case LB: /* Array index */
+ if (p->n_right->n_op != ICON)
+ cerror("mkstack");
+ if (!ISARY(pstk->in_t))
+ uerror("array indexing non-array");
+ pstk->in_n = p->n_right->n_lval;
+ nfree(p->n_right);
+ break;
+
+ case NAME:
+ if (pstk->in_xp) {
+ for (; pstk->in_xp[0]; pstk->in_xp++)
+ if (pstk->in_xp[0]->sname == (char *)p->n_sp)
+ break;
+ if (pstk->in_xp[0] == NULL)
+ uerror("member missing");
+ } else {
+ uerror("not a struct/union");
+ }
+ break;
+ default:
+ cerror("mkstack2");
+ }
+ nfree(p);
+ stkpush();
+
+}
+
+/*
+ * Initialize a specific element, as per C99.
+ */
+void
+desinit(NODE *p)
+{
+ int op = p->n_op;
+
+ if (pstk == NULL)
+ stkpush(); /* passed end of array */
+ while (pstk->in_prev && pstk->in_fl == 0)
+ pstk = pstk->in_prev; /* Empty stack */
+
+ if (ISSOU(pstk->in_t))
+ pstk->in_xp = pstk->in_sym->ssue->suelem;
+
+ mkstack(p); /* Setup for assignment */
+
+ /* pop one step if SOU, ilbrace will push */
+ if (op == NAME)
+ pstk = pstk->in_prev;
+
+#ifdef PCC_DEBUG
+ if (idebug > 1) {
+ printf("desinit e\n");
+ prtstk(pstk);
+ }
+#endif
+}
+
+/*
+ * Convert a string to an array of char/wchar for asginit.
+ */
+static void
+strcvt(NODE *p)
+{
+ char *s;
+ int i;
+
+ for (s = p->n_sp->sname; *s != 0; ) {
+ if (*s++ == '\\') {
+ i = esccon(&s);
+ } else
+ i = (unsigned char)s[-1];
+ asginit(bcon(i));
+ }
+ nfree(p);
+}
+
+/*
+ * Do an assignment to a struct element.
+ */
+void
+asginit(NODE *p)
+{
+ int g;
+
+#ifdef PCC_DEBUG
+ if (idebug)
+ printf("asginit %p\n", p);
+ if (idebug > 1 && p)
+ fwalk(p, eprint, 0);
+#endif
+
+ /* convert string to array of char */
+ if (p && DEUNSIGN(p->n_type) == ARY+CHAR) {
+ /*
+ * ...but only if next element is ARY+CHAR, otherwise
+ * just fall through.
+ */
+
+ /* HACKHACKHACK */
+ struct instk *is = pstk;
+
+ if (pstk == NULL)
+ stkpush();
+ while (ISSOU(pstk->in_t) || ISARY(pstk->in_t))
+ stkpush();
+ if (pstk->in_prev &&
+ DEUNSIGN(pstk->in_prev->in_t) == ARY+CHAR) {
+ pstk = pstk->in_prev;
+ if ((g = pstk->in_fl) == 0)
+ pstk->in_fl = 1; /* simulate ilbrace */
+
+ strcvt(p);
+ if (g == 0)
+ irbrace();
+ return;
+ } else
+ pstk = is; /* no array of char */
+ /* END HACKHACKHACK */
+ }
+
+ if (p == NULL) { /* only end of compound stmt */
+ irbrace();
+ } else /* assign next element */
+ scalinit(p);
+}
+
+#ifdef PCC_DEBUG
+void
+prtstk(struct instk *in)
+{
+ int i, o = 0;
+
+ printf("init stack:\n");
+ for (; in != NULL; in = in->in_prev) {
+ for (i = 0; i < o; i++)
+ printf(" ");
+ printf("%p) '%s' ", in, in->in_sym->sname);
+ tprint(stdout, in->in_t, 0);
+ printf(" %s ", scnames(in->in_sym->sclass));
+ if (in->in_df && in->in_df->ddim)
+ printf("arydim=%d ", in->in_df->ddim);
+ printf("ninit=%d ", in->in_n);
+ if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t))
+ printf("stsize=%d ", in->in_sym->ssue->suesize);
+ if (in->in_fl) printf("{ ");
+ printf("soff=%d ", in->in_sym->soffset);
+ if (in->in_t == STRTY) {
+ if (in->in_xp && in->in_xp[0])
+ printf("curel %s ", in->in_xp[0]->sname);
+ else
+ printf("END struct");
+ }
+ printf("\n");
+ o++;
+ }
+}
+#endif
+
+/*
+ * Do a simple initialization.
+ * At block 0, just print out the value, at higher levels generate
+ * appropriate code.
+ */
+void
+simpleinit(struct symtab *sp, NODE *p)
+{
+ /* May be an initialization of an array of char by a string */
+ if ((DEUNSIGN(p->n_type) == ARY+CHAR &&
+ DEUNSIGN(sp->stype) == ARY+CHAR) ||
+ (DEUNSIGN(p->n_type) == ARY+WCHAR_TYPE &&
+ DEUNSIGN(sp->stype) == ARY+WCHAR_TYPE)) {
+ /* Handle "aaa" as { 'a', 'a', 'a' } */
+ beginit(sp);
+ strcvt(p);
+ if (csym->sdf->ddim == 0)
+ scalinit(bcon(0)); /* Null-term arrays */
+ endinit();
+ return;
+ }
+
+ switch (sp->sclass) {
+ case STATIC:
+ case EXTDEF:
+ spname = sp;
+ p = optim(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
+ setscl(sp);
+ ninval(0, p->n_right->n_sue->suesize, p->n_right);
+ tfree(p);
+ break;
+
+ case AUTO:
+ case REGISTER:
+ if (ISARY(sp->stype))
+ cerror("no array init");
+ spname = sp;
+ ecomp(buildtree(ASSIGN, buildtree(NAME, NIL, NIL), p));
+ break;
+
+ default:
+ uerror("illegal initialization");
+ }
+}
--- /dev/null
+++ usr.bin/pcc/ccom/gcc_compat.c
@@ -0,0 +1,126 @@
+/* $Id: gcc_compat.c,v 1.7 2006/05/13 06:35:36 ragge Exp $ */
+/*
+ * Copyright (c) 2004 Anders Magnusson (ragge at 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.
+ */
+
+/*
+ * Routines to support some of the gcc extensions to C.
+ */
+#ifdef GCC_COMPAT
+
+#include "pass1.h"
+#include "cgram.h"
+
+#include <string.h>
+
+static struct kw {
+ char *name, *ptr;
+ int rv;
+} kw[] = {
+ { "__asm", NULL, C_ASM },
+ { "__signed", NULL, 0 },
+ { "__inline", NULL, C_FUNSPEC },
+ { "__const", NULL, 0 },
+ { "__asm__", NULL, C_ASM },
+ { NULL, NULL, 0 },
+};
+
+void
+gcc_init()
+{
+ struct kw *kwp;
+
+ for (kwp = kw; kwp->name; kwp++)
+ kwp->ptr = addname(kwp->name);
+
+}
+
+/*
+ * See if a string matches a gcc keyword.
+ */
+int
+gcc_keyword(char *str, NODE **n)
+{
+ struct kw *kwp;
+ int i;
+
+ for (i = 0, kwp = kw; kwp->name; kwp++, i++)
+ if (str == kwp->ptr)
+ break;
+ if (kwp->name == NULL)
+ return 0;
+ if (kwp->rv)
+ return kwp->rv;
+ switch (i) {
+ case 1: /* __signed */
+ *n = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED));
+ return C_TYPE;
+ case 3: /* __const */
+ *n = block(QUALIFIER, NIL, NIL, CON, 0, 0);
+ return C_QUALIFIER;
+ }
+ cerror("gcc_keyword");
+ return 0;
+}
+
+static struct ren {
+ struct ren *next;
+ char *old, *new;
+} *renp;
+/*
+ * Save a name for later renaming of a variable.
+ */
+void
+gcc_rename(struct symtab *sp, char *newname)
+{
+ struct ren *ren = permalloc(sizeof(struct ren));
+
+ sp->sflags |= SRENAME;
+ ren->old = sp->sname;
+ ren->new = newstring(newname, strlen(newname)+1);
+ ren->next = renp;
+ renp = ren;
+}
+
+/*
+ * Get a renamed variable.
+ */
+char *
+gcc_findname(struct symtab *sp)
+{
+ struct ren *w;
+
+ if ((sp->sflags & SRENAME) == 0)
+ return exname(sp->sname);
+
+ for (w = renp; w; w = w->next) {
+ if (w->old == sp->sname)
+ return exname(w->new);
+ }
+ cerror("gcc_findname %s", sp->sname);
+ return NULL;
+}
+#endif
--- /dev/null
+++ usr.bin/pcc/ccom/pass1.h
@@ -0,0 +1,394 @@
+/* $Id: pass1.h,v 1.125 2007/09/09 10:01:01 ragge Exp $ */
+/*
+ * 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 conditionsand 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 <sys/types.h>
+#include <stdarg.h>
+
+#include "manifest.h"
+
+#include "protos.h"
+#include "ccconfig.h"
+
+/*
+ * Storage classes
+ */
+#define SNULL 0
+#define AUTO 1
+#define EXTERN 2
+#define STATIC 3
+#define REGISTER 4
+#define EXTDEF 5
+/* #define LABEL 6*/
+/* #define ULABEL 7*/
+#define MOS 8
+#define PARAM 9
+#define STNAME 10
+#define MOU 11
+#define UNAME 12
+#define TYPEDEF 13
+#define FORTRAN 14
+#define ENAME 15
+#define MOE 16
+#define UFORTRAN 17
+#define USTATIC 18
+#define ILABEL 19
+
+ /* field size is ORed in */
+#define FIELD 0100
+#define FLDSIZ 077
+extern char *scnames(int);
+
+/*
+ * Symbol table flags
+ */
+#define SNORMAL 0
+#define STAGNAME 01
+#define SLBLNAME 02
+#define SMOSNAME 03
+#define SSTRING 04
+#define NSTYPES 05
+#define SMASK 07
+
+#define SSET 00010
+#define SREF 00020
+#define SNOCREAT 00040
+#define STEMP 00100
+#define SDYNARRAY 00200
+#define SINLINE 00400
+#define STNODE 01000
+#ifdef GCC_COMPAT
+#define SRENAME 02000 /* Node is renamed */
+#endif
+#define SASG 04000
+
+#ifndef FIXDEF
+#define FIXDEF(p)
+#endif
+
+ /* alignment of initialized quantities */
+#ifndef AL_INIT
+#define AL_INIT ALINT
+#endif
+
+struct rstack;
+struct symtab;
+union arglist;
+
+/*
+ * Dimension/prototype information.
+ * ddim > 0 holds the dimension of an array.
+ * ddim < 0 is a dynamic array and refers to a tempnode.
+ */
+union dimfun {
+ int ddim; /* Dimension of an array */
+ union arglist *dfun; /* Prototype index */
+};
+
+/*
+ * Struct/union/enum definition.
+ * The first element (size) is used for other types as well.
+ */
+struct suedef {
+ int suesize; /* Size of the struct */
+ struct symtab **suelem;/* points to the list of elements */
+ int suealign; /* Alignment of this struct */
+};
+
+/*
+ * Argument list member info when storing prototypes.
+ */
+union arglist {
+ TWORD type;
+ union dimfun *df;
+ struct suedef *sue;
+};
+#define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
+#define TELLIPSIS INCREF(INCREF(MOETY))
+
+/*
+ * Symbol table definition.
+ *
+ * The symtab_hdr struct is used to save label info in NAME and ICON nodes.
+ */
+struct symtab_hdr {
+ struct symtab *h_next; /* link to other symbols in the same scope */
+ int h_offset; /* offset or value */
+ char h_sclass; /* storage class */
+ char h_slevel; /* scope level */
+ short h_sflags; /* flags, see below */
+};
+
+struct symtab {
+ struct symtab_hdr hdr;
+ char *sname;
+ TWORD stype; /* type word */
+ TWORD squal; /* qualifier word */
+ union dimfun *sdf; /* ptr to the dimension/prototype array */
+ struct suedef *ssue; /* ptr to the definition table */
+ int suse; /* line number of last use of the variable */
+};
+
+#define snext hdr.h_next
+#define soffset hdr.h_offset
+#define sclass hdr.h_sclass
+#define slevel hdr.h_slevel
+#define sflags hdr.h_sflags
+
+#define MKSUE(type) &btdims[type]
+extern struct suedef btdims[];
+
+/*
+ * External definitions
+ */
+struct swents { /* switch table */
+ struct swents *next; /* Next struct in linked list */
+ CONSZ sval; /* case value */
+ int slab; /* associated label */
+};
+void genswitch(int, struct swents **, int);
+
+extern int blevel;
+extern int instruct, got_type;
+extern int oldstyle;
+
+extern int lineno, nerrors;
+
+extern char *ftitle;
+extern struct symtab *cftnsp;
+extern int autooff, maxautooff, argoff, strucoff;
+extern int brkflag;
+extern int lastloc;
+
+extern OFFSZ inoff;
+
+extern int reached;
+extern int isinlining;
+
+/* tunnel to buildtree for name id's */
+
+extern struct symtab *spname;
+
+extern int sdebug, idebug, pdebug;
+
+/* various labels */
+extern int brklab;
+extern int contlab;
+extern int flostat;
+extern int retlab;
+
+/*
+ * Flags used in structures/unions
+ */
+#define INSTRUCT 02
+#define INUNION 04
+
+/*
+ * Flags used in the (elementary) flow analysis ...
+ */
+#define FBRK 02
+#define FCONT 04
+#define FDEF 010
+#define FLOOP 020
+
+/* mark an offset which is undefined */
+
+#define NOOFFSET (-10201)
+
+/* declarations of various functions */
+extern NODE
+ *buildtree(int, NODE *l, NODE *r),
+ *mkty(unsigned, union dimfun *, struct suedef *),
+ *rstruct(char *, int),
+ *dclstruct(struct rstack *),
+ *strend(char *),
+ *wstrend(char *),
+ *tymerge(NODE *typ, NODE *idp),
+ *stref(NODE *),
+ *offcon(OFFSZ, TWORD, union dimfun *, struct suedef *),
+ *bcon(int),
+ *bpsize(NODE *),
+ *convert(NODE *, int),
+ *pconvert(NODE *),
+ *oconvert(NODE *),
+ *ptmatch(NODE *),
+ *tymatch(NODE *),
+ *makety(NODE *, TWORD, TWORD, union dimfun *, struct suedef *),
+ *block(int, NODE *, NODE *r, TWORD, union dimfun *, struct suedef *),
+ *doszof(NODE *),
+ *talloc(void),
+ *optim(NODE *),
+ *clocal(NODE *),
+ *ccopy(NODE *),
+ *btsize(TWORD, union dimfun *, struct suedef *),
+ *tempnode(int, TWORD type, union dimfun *df, struct suedef *sue),
+ *doacall(NODE *f, NODE *a);
+OFFSZ tsize(TWORD, union dimfun *, struct suedef *),
+ psize(NODE *);
+NODE * typenode(NODE *new);
+void spalloc(NODE *, NODE *, OFFSZ);
+char *exname(char *);
+
+int oalloc(struct symtab *p, int *poff);
+void deflabel(char *);
+void deflab1(int);
+void setloc1(int);
+void gotolabel(char *);
+unsigned int esccon(char **sptr);
+void inline_start(char *name);
+void inline_end(void);
+void inline_addarg(struct interpass *);
+void inline_ref(char *);
+void inline_prtout(void);
+void ftnarg(NODE *);
+struct rstack *bstruct(char *, int);
+void moedef(char *);
+void beginit(struct symtab *);
+void simpleinit(struct symtab *, NODE *);
+struct symtab *lookup(char *name, int s);
+struct symtab *getsymtab(char *name, int flags);
+char *addstring(char *);
+char *addname(char *);
+char *newstring(char *, int len);
+void symclear(int level);
+void schedremove(struct symtab *p);
+struct symtab *hide(struct symtab *p);
+int talign(unsigned int, struct suedef *);
+void bfcode(struct symtab **, int);
+int chkftn(union arglist *, union arglist *);
+void branch(int);
+void cbranch(NODE *p, NODE *q);
+void extdec(struct symtab *);
+void commdec(struct symtab *);
+void lcommdec(struct symtab *);
+int falloc(struct symtab *p, int w, int new, NODE *pty);
+TWORD ctype(TWORD);
+void ninval(CONSZ off, int fsz, NODE *);
+void infld(CONSZ off, int fsz, CONSZ);
+void zbits(CONSZ off, int fsz);
+void indata(CONSZ, int);
+void instring(char *);
+void defnam(struct symtab *);
+void plabel(int lab);
+void bjobcode(void);
+void ejobcode(int);
+void calldec(NODE *, NODE *);
+int cisreg(TWORD);
+char *tmpsprintf(char *fmt, ...);
+char *tmpvsprintf(char *fmt, va_list ap);
+void asginit(NODE *);
+void desinit(NODE *);
+void endinit(void);
+void ilbrace(void);
+void irbrace(void);
+void scalinit(NODE *p);
+int ftoint(NODE *, CONSZ **);
+void p1print(char *fmt, ...);
+char *copst(int);
+int cdope(int);
+void myp2tree(NODE *);
+void lcommprint(void);
+void lcommdel(struct symtab *);
+
+#ifdef GCC_COMPAT
+void gcc_init(void);
+int gcc_keyword(char *, NODE **);
+void gcc_rename(struct symtab *sp, char *newname);
+char *gcc_findname(struct symtab *sp);
+#endif
+
+#ifdef STABS
+void stabs_init(void);
+void stabs_file(char *);
+void stabs_line(int);
+void stabs_rbrac(int);
+void stabs_lbrac(int);
+void stabs_func(struct symtab *);
+void stabs_newsym(struct symtab *);
+void stabs_chgsym(struct symtab *);
+void stabs_struct(struct symtab *p, struct suedef *sue);
+#endif
+
+#ifndef CHARCAST
+/* to make character constants into character connstants */
+/* this is a macro to defend against cross-compilers, etc. */
+#define CHARCAST(x) (char)(x)
+#endif
+
+/*
+ * C compiler first pass extra defines.
+ */
+#define QUALIFIER (MAXOP+1)
+#define CLASS (MAXOP+2)
+#define RB (MAXOP+3)
+#define DOT (MAXOP+4)
+#define ELLIPSIS (MAXOP+5)
+#define TYPE (MAXOP+6)
+#define LB (MAXOP+7)
+#define COMOP (MAXOP+8)
+#define QUEST (MAXOP+9)
+#define COLON (MAXOP+10)
+#define ANDAND (MAXOP+11)
+#define OROR (MAXOP+12)
+#define NOT (MAXOP+13)
+#define CAST (MAXOP+14)
+/* #define STRING (MAXOP+15) */
+
+/* The following must be in the same order as their NOASG counterparts */
+#define PLUSEQ (MAXOP+16)
+#define MINUSEQ (MAXOP+17)
+#define DIVEQ (MAXOP+18)
+#define MODEQ (MAXOP+19)
+#define MULEQ (MAXOP+20)
+#define ANDEQ (MAXOP+21)
+#define OREQ (MAXOP+22)
+#define EREQ (MAXOP+23)
+#define LSEQ (MAXOP+24)
+#define RSEQ (MAXOP+25)
+
+#define UNASG (-(PLUSEQ-PLUS))+
+
+#define INCR (MAXOP+26)
+#define DECR (MAXOP+27)
+/*
+ * The following types are only used in pass1.
+ */
+#define SIGNED (MAXTYPES+1)
+#define BOOL (MAXTYPES+2)
+
+
+#define coptype(o) (cdope(o)&TYFLG)
+#define clogop(o) (cdope(o)&LOGFLG)
+#define casgop(o) (cdope(o)&ASGFLG)
+
--- /dev/null
+++ usr.bin/pcc/ccom/main.c
@@ -0,0 +1,317 @@
+/* $Id: main.c,v 1.72 2007/09/25 06:43:06 ragge Exp $ */
+
+/*
+ * Copyright (c) 2002 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 <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pass1.h"
+#include "pass2.h"
+
+int sflag, nflag, oflag, kflag;
+int lflag, odebug, rdebug, radebug, vdebug, s2debug, udebug, x2debug;
+#if !defined(MULTIPASS) || defined(PASST)
+int iTflag, oTflag;
+#endif
+int xdebug, mdebug, sdebug, gflag, c2debug, pdebug;
+int Wstrict_prototypes, Wmissing_prototypes, Wimplicit_int,
+ Wimplicit_function_declaration;
+int xssaflag, xtailcallflag, xtemps, xdeljumps;
+
+int e2debug, t2debug, f2debug, b2debug;
+
+struct suedef btdims[24];
+char *prgname;
+
+static void prtstats(void);
+
+static struct {
+ char *n; int *f;
+} flagstr[] = {
+ { "strict-prototypes", &Wstrict_prototypes, },
+ { "missing-prototypes", &Wmissing_prototypes, },
+ { "implicit-int", &Wimplicit_int, },
+ { "implicit-function-declaration", &Wimplicit_function_declaration, },
+ { NULL, NULL, },
+};
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s [option] [infile] [outfile]...\n",
+ prgname);
+ exit(1);
+}
+
+static void
+segvcatch(int a)
+{
+ fprintf(stderr, "%sinternal compiler error: %s, line %d\n",
+ nerrors ? "" : "major ", ftitle, lineno);
+ fflush(stderr);
+ exit(1);
+}
+
+/*
+ * "emulate" the gcc warning flags.
+ */
+static void
+Wflags(char *str)
+{
+ int i, found = 0, all;
+
+ if (strcmp(str, "implicit") == 0) {
+ Wimplicit_int = Wimplicit_function_declaration = 1;
+ return;
+ }
+ all = strcmp(str, "W") == 0;
+ for (i = 0; flagstr[i].n; i++)
+ if (all || strcmp(flagstr[i].n, str) == 0) {
+ *flagstr[i].f = 1;
+ found++;
+ }
+ if (found == 0)
+ usage();
+}
+
+
+/* control multiple files */
+int
+main(int argc, char *argv[])
+{
+
+ int ch;
+
+ prgname = argv[0];
+
+ while ((ch = getopt(argc, argv, "VlwX:Z:W:sOT:gx:kv")) != -1)
+ switch (ch) {
+#if !defined(MULTIPASS) || defined(PASS1)
+ case 'X':
+ while (*optarg)
+ switch (*optarg++) {
+ case 'd': ++ddebug; break; /* declarations */
+ case 'i': ++idebug; break; /* initializations */
+ case 'b': ++bdebug; break;
+ case 't': ++tdebug; break;
+ case 'e': ++edebug; break; /* pass1 exit */
+ case 'x': ++xdebug; break; /* MD code */
+ case 's': ++sdebug; break;
+ case 'n': ++nflag; break;
+ case 'o': ++oflag; break;
+ case 'p': ++pdebug; break; /* prototype */
+ default:
+ fprintf(stderr, "unknown X flag '%c'\n",
+ optarg[-1]);
+ exit(1);
+ }
+#endif
+ break;
+#if !defined(MULTIPASS) || defined(PASST)
+ case 'T':
+ while (*optarg)
+ switch (*optarg++) {
+ case 'i': ++iTflag; break;
+ case 'o': ++oTflag; break;
+ case 'n': ++nflag; break;
+ default:
+ fprintf(stderr, "unknown T flag '%c'\n",
+ optarg[-1]);
+ exit(1);
+ }
+#endif
+ break;
+#if !defined(MULTIPASS) || defined(PASS2)
+ case 'Z':
+ while (*optarg)
+ switch (*optarg++) {
+ case 'f': /* instruction matching */
+ ++f2debug;
+ break;
+ case 'e': /* print tree upon pass2 enter */
+ ++e2debug;
+ break;
+ case 'o': ++odebug; break;
+ case 'r': /* register alloc/graph coloring */
+ ++rdebug;
+ break;
+ case 'a': ++radebug; break;
+ case 'b': /* basic block and SSA building */
+ ++b2debug;
+ break;
+ case 'c': /* code printout */
+ ++c2debug;
+ break;
+ case 'm': ++mdebug; break;
+ case 'v': ++vdebug; break;
+ case 't': ++t2debug; break;
+ case 's': /* shape matching */
+ ++s2debug;
+ break;
+ case 'u': /* Sethi-Ullman debugging */
+ ++udebug;
+ break;
+ case 'x': ++x2debug; break;
+ case 'n': ++nflag; break;
+ default:
+ fprintf(stderr, "unknown Z flag '%c'\n",
+ optarg[-1]);
+ exit(1);
+ }
+#endif
+ break;
+
+ case 'k': /* PIC code */
+ ++kflag;
+ break;
+
+ case 'l': /* linenos */
+ ++lflag;
+ break;
+
+ case 'g': /* Debugging */
+ gflag = 1;
+ break;
+
+ case 's': /* Statistics */
+ ++sflag;
+ break;
+
+ case 'W': /* Enable different warnings */
+ Wflags(optarg);
+ break;
+
+ case 'x': /* Different optimizations */
+ if (strcmp(optarg, "ssa") == 0)
+ xssaflag++;
+ else if (strcmp(optarg, "tailcall") == 0)
+ xtailcallflag++;
+ else if (strcmp(optarg, "temps") == 0)
+ xtemps++;
+ else if (strcmp(optarg, "deljumps") == 0)
+ xdeljumps++;
+ else
+ usage();
+ break;
+ case 'v':
+ printf("ccom: %s\n", VERSSTR);
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0) {
+ if (freopen(argv[0], "r", stdin) == NULL) {
+ fprintf(stderr, "open input file '%s':",
+ argv[0]);
+ perror(NULL);
+ exit(1);
+ }
+ if (argc != 1)
+ if (freopen(argv[1], "w", stdout) == NULL) {
+ fprintf(stderr, "open output file '%s':",
+ argv[1]);
+ perror(NULL);
+ exit(1);
+ }
+ }
+
+ mkdope();
+ signal(SIGSEGV, segvcatch);
+ fregs = FREGS; /* number of free registers */
+ lineno = 1;
+#ifdef GCC_COMPAT
+ gcc_init();
+#endif
+
+ /* dimension table initialization */
+
+ btdims[VOID].suesize = 0;
+ btdims[BOOL].suesize = SZBOOL;
+ btdims[CHAR].suesize = SZCHAR;
+ btdims[INT].suesize = SZINT;
+ btdims[FLOAT].suesize = SZFLOAT;
+ btdims[DOUBLE].suesize = SZDOUBLE;
+ btdims[LDOUBLE].suesize = SZLDOUBLE;
+ btdims[LONG].suesize = SZLONG;
+ btdims[LONGLONG].suesize = SZLONGLONG;
+ btdims[SHORT].suesize = SZSHORT;
+ btdims[UCHAR].suesize = SZCHAR;
+ btdims[USHORT].suesize = SZSHORT;
+ btdims[UNSIGNED].suesize = SZINT;
+ btdims[ULONG].suesize = SZLONG;
+ btdims[ULONGLONG].suesize = SZLONGLONG;
+ /* starts past any of the above */
+ reached = 1;
+
+ bjobcode();
+
+#ifdef STABS
+ if (gflag) {
+ stabs_file(argc ? argv[0] : "");
+ stabs_init();
+ }
+#endif
+
+ (void) yyparse();
+ yyaccpt();
+
+ ejobcode( nerrors ? 1 : 0 );
+ if (!nerrors)
+ lcommprint();
+
+ if (sflag)
+ prtstats();
+ return(nerrors?1:0);
+
+}
+
+void
+prtstats(void)
+{
+ extern int nametabs, namestrlen, tmpallocsize, permallocsize;
+ extern int lostmem, arglistcnt, dimfuncnt, inlnodecnt, inlstatcnt;
+ extern int symtabcnt, suedefcnt;
+
+ fprintf(stderr, "Name table entries: %d pcs\n", nametabs);
+ fprintf(stderr, "Name string size: %d B\n", namestrlen);
+ fprintf(stderr, "Permanent allocated memory: %d B\n", permallocsize);
+ fprintf(stderr, "Temporary allocated memory: %d B\n", tmpallocsize);
+ fprintf(stderr, "Lost memory: %d B\n", lostmem);
+ fprintf(stderr, "Argument list unions: %d pcs\n", arglistcnt);
+ fprintf(stderr, "Dimension/function unions: %d pcs\n", dimfuncnt);
+ fprintf(stderr, "Struct/union/enum blocks: %d pcs\n", suedefcnt);
+ fprintf(stderr, "Inline node count: %d pcs\n", inlnodecnt);
+ fprintf(stderr, "Inline control blocks: %d pcs\n", inlstatcnt);
+ fprintf(stderr, "Permanent symtab entries: %d pcs\n", symtabcnt);
+}
--- /dev/null
+++ usr.bin/pcc/ccom/cgram.y
@@ -0,0 +1,1400 @@
+/* $Id: cgram.y,v 1.170 2007/09/16 19:25:33 ragge Exp $ */
+
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+/*
+ * Comments for this grammar file. Ragge 021123
+ *
+ * ANSI support required rewrite of the function header and declaration
+ * rules almost totally.
+ *
+ * The lex/yacc shared keywords are now split from the keywords used
+ * in the rest of the compiler, to simplify use of other frontends.
+ */
+
+/*
+ * At last count, there were 3 shift/reduce and no reduce/reduce conflicts
+ * Two was funct_idn and the third was "dangling else".
+ */
+
+/*
+ * Token used in C lex/yacc communications.
+ */
+%token C_WSTRING /* a wide string constant */
+%token C_STRING /* a string constant */
+%token C_ICON /* an integer constant */
+%token C_FCON /* a floating point constant */
+%token C_NAME /* an identifier */
+%token C_TYPENAME /* a typedef'd name */
+%token C_ANDAND /* && */
+%token C_OROR /* || */
+%token C_GOTO /* unconditional goto */
+%token C_RETURN /* return from function */
+%token C_TYPE /* a type */
+%token C_CLASS /* a storage class */
+%token C_ASOP /* assignment ops */
+%token C_RELOP /* <=, <, >=, > */
+%token C_EQUOP /* ==, != */
+%token C_DIVOP /* /, % */
+%token C_SHIFTOP /* <<, >> */
+%token C_INCOP /* ++, -- */
+%token C_UNOP /* !, ~ */
+%token C_STROP /* ., -> */
+%token C_STRUCT
+%token C_IF
+%token C_ELSE
+%token C_SWITCH
+%token C_BREAK
+%token C_CONTINUE
+%token C_WHILE
+%token C_DO
+%token C_FOR
+%token C_DEFAULT
+%token C_CASE
+%token C_SIZEOF
+%token C_ENUM
+%token C_ELLIPSIS
+%token C_QUALIFIER
+%token C_FUNSPEC
+%token C_ASM
+
+/*
+ * Precedence
+ */
+%left ','
+%right '=' C_ASOP
+%right '?' ':'
+%left C_OROR
+%left C_ANDAND
+%left '|'
+%left '^'
+%left '&'
+%left C_EQUOP
+%left C_RELOP
+%left C_SHIFTOP
+%left '+' '-'
+%left '*' C_DIVOP
+%right C_UNOP
+%right C_INCOP C_SIZEOF
+%left '[' '(' C_STROP
+%{
+# include "pass1.h"
+# include <stdarg.h>
+# include <string.h>
+# include <stdlib.h>
+
+static int fun_inline; /* Reading an inline function */
+int oldstyle; /* Current function being defined */
+int noretype;
+static struct symtab *xnf;
+#ifdef GCC_COMPAT
+char *renname; /* for renaming of variables */
+#endif
+
+
+static NODE *bdty(int op, ...);
+static void fend(void);
+static void fundef(NODE *tp, NODE *p);
+static void olddecl(NODE *p);
+static struct symtab *init_declarator(NODE *tn, NODE *p, int assign);
+static void resetbc(int mask);
+static void swend(void);
+static void addcase(NODE *p);
+static void adddef(void);
+static void savebc(void);
+static void swstart(int);
+static NODE * structref(NODE *p, int f, char *name);
+static char *mkpstr(char *str);
+static struct symtab *clbrace(NODE *);
+
+/*
+ * State for saving current switch state (when nested switches).
+ */
+struct savbc {
+ struct savbc *next;
+ int brklab;
+ int contlab;
+ int flostat;
+ int swx;
+} *savbc, *savctx;
+
+%}
+
+%union {
+ int intval;
+ NODE *nodep;
+ struct symtab *symp;
+ struct rstack *rp;
+ char *strp;
+}
+
+ /* define types */
+%start ext_def_list
+
+%type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart
+ type_qualifier_list
+%type <nodep> e .e term enum_dcl struct_dcl cast_type funct_idn declarator
+ direct_declarator elist type_specifier merge_attribs
+ parameter_declaration abstract_declarator initializer
+ parameter_type_list parameter_list addrlbl
+ declaration_specifiers pointer direct_abstract_declarator
+ specifier_qualifier_list merge_specifiers nocon_e
+ identifier_list arg_param_list arg_declaration arg_dcl_list
+ designator_list designator
+%type <strp> string wstring C_STRING C_WSTRING
+%type <rp> enum_head str_head
+%type <symp> xnfdeclarator clbrace
+
+%type <intval> C_CLASS C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
+ C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
+%type <nodep> C_TYPE C_QUALIFIER C_ICON C_FCON
+%type <strp> C_NAME C_TYPENAME
+
+%%
+
+ext_def_list: ext_def_list external_def
+ | { ftnend(); }
+ ;
+
+external_def: function_definition { blevel = 0; }
+ | declaration { blevel = 0; symclear(0); }
+ | asmstatement ';'
+ | ';'
+ | error { blevel = 0; }
+ ;
+
+function_definition:
+ /* Ansi (or K&R header without parameter types) */
+ declaration_specifiers declarator {
+ fundef($1, $2);
+ } compoundstmt { fend(); }
+ /* Same as above but without declaring function type */
+ | declarator {
+ noretype = 1;
+ fundef(mkty(INT, 0, MKSUE(INT)), $1);
+ } compoundstmt { fend(); noretype = 0; }
+ /* K&R function without type declaration */
+ | declarator {
+ noretype = 1;
+ if (oldstyle == 0)
+ uerror("bad declaration in ansi function");
+ fundef(mkty(INT, 0, MKSUE(INT)), $1);
+ } arg_dcl_list compoundstmt { fend(); noretype = 0; }
+ /* K&R function with type declaration */
+ | declaration_specifiers declarator {
+ if (oldstyle == 0)
+ uerror("bad declaration in ansi function");
+ fundef($1, $2);
+ } arg_dcl_list compoundstmt { fend(); }
+ ;
+
+/*
+ * Returns a node pointer or NULL, if no types at all given.
+ * Type trees are checked for correctness and merged into one
+ * type node in typenode().
+ */
+declaration_specifiers:
+ merge_attribs { $$ = typenode($1); }
+ ;
+
+merge_attribs: C_CLASS { $$ = block(CLASS, NIL, NIL, $1, 0, 0); }
+ | C_CLASS merge_attribs { $$ = block(CLASS, $2, NIL, $1,0,0);}
+ | type_specifier { $$ = $1; }
+ | type_specifier merge_attribs { $1->n_left = $2; $$ = $1; }
+ | C_QUALIFIER { $$ = $1; }
+ | C_QUALIFIER merge_attribs { $1->n_left = $2; $$ = $1; }
+ | function_specifiers { $$ = NIL; }
+ | function_specifiers merge_attribs { $$ = $2; }
+ ;
+
+function_specifiers:
+ C_FUNSPEC {
+ if (fun_inline)
+ uerror("too many inline");
+ fun_inline = 1;
+ }
+ ;
+
+type_specifier: C_TYPE { $$ = $1; }
+ | C_TYPENAME {
+ struct symtab *sp = lookup($1, 0);
+ $$ = mkty(sp->stype, sp->sdf, sp->ssue);
+ $$->n_sp = sp;
+ }
+ | struct_dcl { $$ = $1; }
+ | enum_dcl { $$ = $1; }
+ ;
+
+/*
+ * Adds a pointer list to front of the declarators.
+ * Note the UMUL right node pointer usage.
+ */
+declarator: pointer direct_declarator {
+ $$ = $1; $1->n_right->n_left = $2;
+ }
+ | direct_declarator { $$ = $1; }
+ ;
+
+/*
+ * Return an UMUL node type linked list of indirections.
+ */
+pointer: '*' { $$ = bdty(UMUL, NIL); $$->n_right = $$; }
+ | '*' type_qualifier_list {
+ $$ = bdty(UMUL, NIL);
+ $$->n_qual = $2;
+ $$->n_right = $$;
+ }
+ | '*' pointer {
+ $$ = bdty(UMUL, $2);
+ $$->n_right = $2->n_right;
+ }
+ | '*' type_qualifier_list pointer {
+ $$ = bdty(UMUL, $3);
+ $$->n_qual = $2;
+ $$->n_right = $3->n_right;
+ }
+ ;
+
+type_qualifier_list:
+ C_QUALIFIER { $$ = $1->n_type; nfree($1); }
+ | type_qualifier_list C_QUALIFIER {
+ $$ = $1 | $2->n_type; nfree($2);
+ }
+ ;
+
+/*
+ * Sets up a function declarator. The call node will have its parameters
+ * connected to its right node pointer.
+ */
+direct_declarator: C_NAME { $$ = bdty(NAME, $1); }
+ | '(' declarator ')' { $$ = $2; }
+ | direct_declarator '[' nocon_e ']' {
+ $$ = block(LB, $1, $3, INT, 0, MKSUE(INT));
+ }
+ | direct_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
+ | direct_declarator '(' notype parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $4);
+ }
+ | direct_declarator '(' notype identifier_list ')' {
+ $$ = bdty(CALL, $1, $4);
+ if (blevel != 0)
+ uerror("function declaration in bad context");
+ oldstyle = 1;
+ }
+ | direct_declarator '(' ')' { $$ = bdty(UCALL, $1); }
+ ;
+
+notype: { /* extern int notype, doproto; notype = 0; doproto=1; printf("notype\n"); */ }
+ ;
+
+identifier_list: C_NAME { $$ = bdty(NAME, $1); $$->n_type = FARG; }
+ | identifier_list ',' C_NAME {
+ $$ = bdty(NAME, $3);
+ $$->n_type = FARG;
+ $$ = block(CM, $1, $$, 0, 0, 0);
+ }
+ ;
+
+/*
+ * Returns as parameter_list, but can add an additional ELLIPSIS node.
+ * Calls revert() to get the parameter list in the forward order.
+ */
+parameter_type_list:
+ parameter_list { $$ = $1; }
+ | parameter_list ',' C_ELLIPSIS {
+ $$ = block(CM, $1, block(ELLIPSIS, NIL, NIL, 0, 0, 0),
+ 0, 0, 0);
+ }
+ ;
+
+/*
+ * Returns a linked lists of nodes of op CM with parameters on
+ * its right and additional CM nodes of its left pointer.
+ * No CM nodes if only one parameter.
+ */
+parameter_list: parameter_declaration { $$ = $1; }
+ | parameter_list ',' parameter_declaration {
+ $$ = block(CM, $1, $3, 0, 0, 0);
+ }
+ ;
+
+/*
+ * Returns a node pointer to the declaration.
+ */
+parameter_declaration:
+ declaration_specifiers declarator {
+ $$ = tymerge($1, $2);
+ nfree($1);
+ }
+ | declaration_specifiers abstract_declarator {
+ $$ = tymerge($1, $2);
+ nfree($1);
+ }
+ | declaration_specifiers {
+ $$ = tymerge($1, bdty(NAME, NULL));
+ nfree($1);
+ }
+ ;
+
+abstract_declarator:
+ pointer { $$ = $1; $1->n_right->n_left = bdty(NAME, NULL); }
+ | direct_abstract_declarator { $$ = $1; }
+ | pointer direct_abstract_declarator {
+ $$ = $1; $1->n_right->n_left = $2;
+ }
+ ;
+
+direct_abstract_declarator:
+ '(' abstract_declarator ')' { $$ = $2; }
+ | '[' ']' { $$ = bdty(LB, bdty(NAME, NULL), 0); }
+ | '[' con_e ']' { $$ = bdty(LB, bdty(NAME, NULL), $2); }
+ | direct_abstract_declarator '[' ']' { $$ = bdty(LB, $1, 0); }
+ | direct_abstract_declarator '[' con_e ']' {
+ $$ = bdty(LB, $1, $3);
+ }
+ | '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
+ | '(' notype parameter_type_list ')' {
+ $$ = bdty(CALL, bdty(NAME, NULL), $3);
+ }
+ | direct_abstract_declarator '(' ')' {
+ $$ = bdty(UCALL, $1);
+ }
+ | direct_abstract_declarator '(' notype parameter_type_list ')' {
+ $$ = bdty(CALL, $1, $4);
+ }
+ ;
+
+/*
+ * K&R arg declaration, between ) and {
+ */
+arg_dcl_list: arg_declaration
+ | arg_dcl_list arg_declaration
+ ;
+
+
+arg_declaration: declaration_specifiers arg_param_list ';' {
+ nfree($1);
+ }
+ ;
+
+arg_param_list: declarator { olddecl(tymerge($<nodep>0, $1)); }
+ | arg_param_list ',' declarator {
+ olddecl(tymerge($<nodep>0, $3));
+ }
+ ;
+
+/*
+ * Declarations in beginning of blocks.
+ */
+declaration_list: declaration
+ | declaration_list declaration
+ ;
+
+/*
+ * Here starts the old YACC code.
+ */
+
+stmt_list: stmt_list statement
+ | { bccode(); }
+ ;
+
+/*
+ * Variables are declared in init_declarator.
+ */
+declaration: declaration_specifiers ';' { nfree($1); goto inl; }
+ | declaration_specifiers init_declarator_list ';' {
+ nfree($1);
+ inl:
+ fun_inline = 0;
+ }
+ ;
+
+/*
+ * Normal declaration of variables. curtype contains the current type node.
+ * Returns nothing, variables are declared in init_declarator.
+ */
+init_declarator_list:
+ init_declarator
+ | init_declarator_list ',' { $<nodep>$ = $<nodep>0; } init_declarator
+ ;
+
+enum_dcl: enum_head '{' moe_list optcomma '}' { $$ = dclstruct($1); }
+ | C_ENUM C_NAME { $$ = rstruct($2,0); }
+ | C_ENUM C_TYPENAME { $$ = rstruct($2,0); }
+ ;
+
+enum_head: C_ENUM { $$ = bstruct(NULL,0); }
+ | C_ENUM C_NAME { $$ = bstruct($2,0); }
+ | C_ENUM C_TYPENAME { $$ = bstruct($2,0); }
+ ;
+
+moe_list: moe
+ | moe_list ',' moe
+ ;
+
+moe: C_NAME { moedef( $1 ); }
+ | C_NAME '=' con_e { strucoff = $3; moedef( $1 ); }
+ ;
+
+struct_dcl: str_head '{' struct_dcl_list '}' { $$ = dclstruct($1); }
+ | C_STRUCT C_NAME { $$ = rstruct($2,$1); }
+ | C_STRUCT C_TYPENAME { $$ = rstruct($2,$1); }
+ | str_head '{' '}' {
+#ifndef GCC_COMPAT
+ werror("gcc extension");
+#endif
+ $$ = dclstruct($1);
+ }
+ ;
+
+str_head: C_STRUCT { $$ = bstruct(NULL, $1); }
+ | C_STRUCT C_NAME { $$ = bstruct($2,$1); }
+ | C_STRUCT C_TYPENAME { $$ = bstruct($2,$1); }
+ ;
+
+struct_dcl_list: struct_declaration
+ | struct_dcl_list struct_declaration
+ ;
+
+struct_declaration:
+ specifier_qualifier_list struct_declarator_list ';' {
+ nfree($1);
+ }
+ ;
+
+specifier_qualifier_list:
+ merge_specifiers { $$ = typenode($1); }
+ ;
+
+merge_specifiers: type_specifier merge_specifiers { $1->n_left = $2;$$ = $1; }
+ | type_specifier { $$ = $1; }
+ | C_QUALIFIER merge_specifiers { $1->n_left = $2; $$ = $1; }
+ | C_QUALIFIER { $$ = $1; }
+ ;
+
+struct_declarator_list:
+ struct_declarator { }
+ | struct_declarator_list ',' { $<nodep>$=$<nodep>0; }
+ struct_declarator { }
+ ;
+
+struct_declarator: declarator {
+ tymerge($<nodep>0, $1);
+ $1->n_sp = getsymtab((char *)$1->n_sp, SMOSNAME); /* XXX */
+ defid($1, $<nodep>0->n_lval);
+ nfree($1);
+ }
+ | ':' con_e {
+ if (!(instruct&INSTRUCT))
+ uerror( "field outside of structure" );
+ falloc(NULL, $2, -1, $<nodep>0);
+ }
+ | declarator ':' con_e {
+ if (!(instruct&INSTRUCT))
+ uerror( "field outside of structure" );
+ if( $3<0 || $3 >= FIELD ){
+ uerror( "illegal field size" );
+ $3 = 1;
+ }
+ if ($1->n_op == NAME) {
+ tymerge($<nodep>0, $1);
+ $1->n_sp = getsymtab((char *)$1->n_sp,SMOSNAME);
+ defid($1, FIELD|$3);
+ nfree($1);
+ } else
+ uerror("illegal declarator");
+ }
+ ;
+
+ /* always preceeded by attributes */
+xnfdeclarator: declarator { $$ = xnf = init_declarator($<nodep>0, $1, 1); }
+ ;
+
+/*
+ * Handles declarations and assignments.
+ * Returns nothing.
+ */
+init_declarator: declarator { init_declarator($<nodep>0, $1, 0); }
+ | declarator C_ASM '(' string ')' {
+#ifdef GCC_COMPAT
+ renname = $4;
+ init_declarator($<nodep>0, $1, 0);
+#else
+ werror("gcc extension");
+ init_declarator($<nodep>0, $1, 0);
+#endif
+ }
+ | xnfdeclarator '=' e { simpleinit($1, $3); xnf = NULL; }
+ | xnfdeclarator '=' begbr init_list optcomma '}' {
+ endinit();
+ xnf = NULL;
+ }
+ | xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
+ ;
+
+begbr: '{' { beginit($<symp>-1); }
+ ;
+
+initializer: e %prec ',' { $$ = $1; }
+ | addrlbl { $$ = $1; }
+ | ibrace init_list optcomma '}' { $$ = NULL; }
+ ;
+
+init_list: designation initializer { asginit($2); }
+ | init_list ',' designation initializer { asginit($4); }
+ ;
+
+designation: designator_list '=' { desinit($1); }
+ | { /* empty */ }
+ ;
+
+designator_list: designator { $$ = $1; }
+ | designator_list designator { $$ = $2; $$->n_left = $1; }
+ ;
+
+designator: '[' con_e ']' { $$ = bdty(LB, NULL, $2); }
+ | C_STROP C_NAME { $$ = bdty(NAME, $2); }
+ ;
+
+optcomma : /* VOID */
+ | ','
+ ;
+
+ibrace: '{' { ilbrace(); }
+ ;
+
+/* STATEMENTS */
+
+compoundstmt: begin declaration_list stmt_list '}' {
+#ifdef STABS
+ if (gflag && blevel > 2)
+ stabs_rbrac(blevel);
+#endif
+ --blevel;
+ if( blevel == 1 )
+ blevel = 0;
+ symclear(blevel); /* Clean ut the symbol table */
+ if (autooff > maxautooff)
+ maxautooff = autooff;
+ autooff = savctx->contlab;
+ savctx = savctx->next;
+ }
+ | begin stmt_list '}' {
+#ifdef STABS
+ if (gflag && blevel > 2)
+ stabs_rbrac(blevel);
+#endif
+ --blevel;
+ if( blevel == 1 )
+ blevel = 0;
+ symclear(blevel); /* Clean ut the symbol table */
+ if (autooff > maxautooff)
+ maxautooff = autooff;
+ autooff = savctx->contlab;
+ savctx = savctx->next;
+ }
+ ;
+
+begin: '{' {
+ struct savbc *bc = tmpalloc(sizeof(struct savbc));
+ if (blevel == 1) {
+#ifdef STABS
+ if (gflag)
+ stabs_line(lineno);
+#endif
+ dclargs();
+ }
+#ifdef STABS
+ if (gflag && blevel > 1)
+ stabs_lbrac(blevel+1);
+#endif
+ ++blevel;
+ oldstyle = 0;
+ bc->contlab = autooff;
+ bc->next = savctx;
+ savctx = bc;
+ }
+ ;
+
+statement: e ';' { ecomp( $1 ); }
+ | compoundstmt
+ | ifprefix statement { plabel($1); reached = 1; }
+ | ifelprefix statement {
+ if ($1 != NOLAB) {
+ plabel( $1);
+ reached = 1;
+ }
+ }
+ | whprefix statement {
+ branch(contlab);
+ plabel( brklab );
+ if( (flostat&FBRK) || !(flostat&FLOOP))
+ reached = 1;
+ else
+ reached = 0;
+ resetbc(0);
+ }
+ | doprefix statement C_WHILE '(' e ')' ';' {
+ plabel(contlab);
+ if (flostat & FCONT)
+ reached = 1;
+ if (reached)
+ cbranch($5, bcon($1));
+ else
+ tfree($5);
+ plabel( brklab);
+ reached = 1;
+ resetbc(0);
+ }
+ | forprefix .e ')' statement
+ { plabel( contlab );
+ if( flostat&FCONT ) reached = 1;
+ if( $2 ) ecomp( $2 );
+ branch($1);
+ plabel( brklab );
+ if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
+ else reached = 0;
+ resetbc(0);
+ }
+ | switchpart statement
+ { if( reached ) branch( brklab );
+ plabel( $1 );
+ swend();
+ plabel( brklab);
+ if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
+ resetbc(FCONT);
+ }
+ | C_BREAK ';' {
+ if (brklab == NOLAB)
+ uerror("illegal break");
+ else if (reached)
+ branch(brklab);
+ flostat |= FBRK;
+ reached = 0;
+ }
+ | C_CONTINUE ';' {
+ if (contlab == NOLAB)
+ uerror("illegal continue");
+ else
+ branch(contlab);
+ flostat |= FCONT;
+ goto rch;
+ }
+ | C_RETURN ';' {
+ branch(retlab);
+ if (cftnsp->stype != VOID && noretype &&
+ cftnsp->stype != VOID+FTN)
+ uerror("return value required");
+ rch:
+ if (!reached)
+ werror( "statement is not reached");
+ reached = 0;
+ }
+ | C_RETURN e ';' {
+ register NODE *temp;
+
+ spname = cftnsp;
+ temp = buildtree( NAME, NIL, NIL );
+ temp->n_type = DECREF(temp->n_type);
+ temp = buildtree(RETURN, temp, $2);
+
+ if (temp->n_type == VOID)
+ ecomp(temp->n_right);
+ else
+ ecomp(buildtree(FORCE, temp->n_right, NIL));
+ nfree(temp->n_left);
+ nfree(temp);
+ branch(retlab);
+ reached = 0;
+ }
+ | C_GOTO C_NAME ';' { gotolabel($2); goto rch; }
+ | C_GOTO '*' e ';' {
+ ecomp(block(GOTO, $3, NIL, INT, 0, 0));
+ }
+ | asmstatement ';'
+ | ';'
+ | error ';'
+ | error '}'
+ | label statement
+ ;
+
+asmstatement: C_ASM '(' string ')' { send_passt(IP_ASM, mkpstr($3)); }
+ ;
+
+label: C_NAME ':' { deflabel($1); reached = 1; }
+ | C_CASE e ':' { addcase($2); reached = 1; }
+ | C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
+ ;
+
+doprefix: C_DO {
+ savebc();
+ if (!reached)
+ werror("loop not entered at top");
+ brklab = getlab();
+ contlab = getlab();
+ plabel( $$ = getlab());
+ reached = 1;
+ }
+ ;
+ifprefix: C_IF '(' e ')' {
+ cbranch(buildtree(NOT, $3, NIL), bcon($$ = getlab()));
+ reached = 1;
+ }
+ ;
+ifelprefix: ifprefix statement C_ELSE {
+ if (reached)
+ branch($$ = getlab());
+ else
+ $$ = NOLAB;
+ plabel( $1);
+ reached = 1;
+ }
+ ;
+
+whprefix: C_WHILE '(' e ')' {
+ savebc();
+ if (!reached)
+ werror("loop not entered at top");
+ if ($3->n_op == ICON && $3->n_lval != 0)
+ flostat = FLOOP;
+ plabel( contlab = getlab());
+ reached = 1;
+ brklab = getlab();
+ if (flostat == FLOOP)
+ tfree($3);
+ else
+ cbranch(buildtree(NOT, $3, NIL), bcon(brklab));
+ }
+ ;
+forprefix: C_FOR '(' .e ';' .e ';' {
+ if ($3)
+ ecomp($3);
+ else if (!reached)
+ werror("loop not entered at top");
+ savebc();
+ contlab = getlab();
+ brklab = getlab();
+ plabel( $$ = getlab());
+ reached = 1;
+ if ($5)
+ cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
+ else
+ flostat |= FLOOP;
+ }
+ ;
+switchpart: C_SWITCH '(' e ')' {
+ NODE *p;
+ int num;
+
+ savebc();
+ brklab = getlab();
+ if ($3->n_type != INT) {
+ /* must cast to integer */
+ p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
+ p = buildtree(CAST, p, $3);
+ $3 = p->n_right;
+ nfree(p->n_left);
+ nfree(p);
+ }
+// ecomp( buildtree( FORCE, $3, NIL ) );
+ p = tempnode(0, INT, 0, MKSUE(INT));
+ num = p->n_lval;
+ ecomp(buildtree(ASSIGN, p, $3));
+ branch( $$ = getlab());
+ swstart(num);
+ reached = 0;
+ }
+ ;
+/* EXPRESSIONS */
+con_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
+ $$ = icons( $2 );
+ instruct=$<intval>1;
+ }
+ ;
+
+nocon_e: { $<intval>$=instruct; instruct=0; } e %prec ',' {
+ instruct=$<intval>1;
+ $$ = $2;
+ }
+ ;
+
+.e: e
+ | { $$=0; }
+ ;
+
+elist: e %prec ','
+ | elist ',' e { $$ = buildtree(CM, $1, $3); }
+ ;
+
+/*
+ * Precedence order of operators.
+ */
+e: e ',' e { $$ = buildtree(COMOP, $1, $3); }
+ | e '=' e { $$ = buildtree(ASSIGN, $1, $3); }
+ | e C_ASOP e { $$ = buildtree($2, $1, $3); }
+ | e '?' e ':' e {
+ $$=buildtree(QUEST, $1, buildtree(COLON, $3, $5));
+ }
+ | e C_OROR e { $$ = buildtree($2, $1, $3); }
+ | e C_ANDAND e { $$ = buildtree($2, $1, $3); }
+ | e '|' e { $$ = buildtree(OR, $1, $3); }
+ | e '^' e { $$ = buildtree(ER, $1, $3); }
+ | e '&' e { $$ = buildtree(AND, $1, $3); }
+ | e C_EQUOP e { $$ = buildtree($2, $1, $3); }
+ | e C_RELOP e { $$ = buildtree($2, $1, $3); }
+ | e C_SHIFTOP e { $$ = buildtree($2, $1, $3); }
+ | e '+' e { $$ = buildtree(PLUS, $1, $3); }
+ | e '-' e { $$ = buildtree(MINUS, $1, $3); }
+ | e C_DIVOP e { $$ = buildtree($2, $1, $3); }
+ | e '*' e { $$ = buildtree(MUL, $1, $3); }
+ | e '=' addrlbl { $$ = buildtree(ASSIGN, $1, $3); }
+ | term
+ ;
+
+addrlbl: C_ANDAND C_NAME {
+#ifdef GCC_COMPAT
+ struct symtab *s = lookup($2, SLBLNAME);
+ if (s->soffset == 0)
+ s->soffset = -getlab();
+ spname = s;
+ $$ = buildtree(ADDROF, buildtree(NAME, NIL, NIL), NIL);
+#else
+ uerror("gcc extension");
+#endif
+ }
+ ;
+
+term: term C_INCOP { $$ = buildtree( $2, $1, bcon(1) ); }
+ | '*' term { $$ = buildtree(UMUL, $2, NIL); }
+ | '&' term {
+ if( ISFTN($2->n_type) || ISARY($2->n_type) ){
+#ifdef notdef
+ werror( "& before array or function: ignored" );
+#endif
+ $$ = $2;
+ } else
+ $$ = buildtree(ADDROF, $2, NIL);
+ }
+ | '-' term { $$ = buildtree(UMINUS, $2, NIL ); }
+ | '+' term { $$ = $2; }
+ | C_UNOP term { $$ = buildtree( $1, $2, NIL ); }
+ | C_INCOP term {
+ $$ = buildtree($1 == INCR ? PLUSEQ : MINUSEQ,
+ $2, bcon(1));
+ }
+ | C_SIZEOF term { $$ = doszof($2); }
+ | '(' cast_type ')' term %prec C_INCOP {
+ $$ = buildtree(CAST, $2, $4);
+ nfree($$->n_left);
+ nfree($$);
+ $$ = $$->n_right;
+ }
+ | C_SIZEOF '(' cast_type ')' %prec C_SIZEOF {
+ $$ = doszof($3);
+ }
+ | '(' cast_type ')' clbrace init_list '}' {
+ endinit();
+ spname = $4;
+ $$ = buildtree(NAME, NIL, NIL);
+ }
+ | term '[' e ']' {
+ $$ = buildtree( UMUL,
+ buildtree( PLUS, $1, $3 ), NIL );
+ }
+ | funct_idn ')' { $$ = doacall($1, NIL); }
+ | funct_idn elist ')' { $$ = doacall($1, $2); }
+ | term C_STROP C_NAME { $$ = structref($1, $2, $3); }
+ | term C_STROP C_TYPENAME { $$ = structref($1, $2, $3); }
+ | C_NAME {
+ spname = lookup($1, 0);
+ /* recognize identifiers in initializations */
+ if (blevel==0 && spname->stype == UNDEF) {
+ register NODE *q;
+ werror("undeclared initializer name %s",
+ spname->sname);
+ q = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
+ q->n_sp = spname;
+ defid(q, EXTERN);
+ nfree(q);
+ }
+ if (spname->sflags & SINLINE)
+ inline_ref($1);
+ $$ = buildtree(NAME, NIL, NIL);
+ spname->suse = -lineno;
+ if (spname->sflags & SDYNARRAY)
+ $$ = buildtree(UMUL, $$, NIL);
+ }
+ | C_ICON { $$ = $1; }
+ | C_FCON { $$ = $1; }
+ | string { $$ = strend($1); /* get string contents */ }
+ | wstring { $$ = wstrend($1); }
+ | '(' e ')' { $$=$2; }
+ ;
+
+clbrace: '{' { $$ = clbrace($<nodep>-1); }
+ ;
+
+string: C_STRING {
+ int len = strlen($1) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ }
+ | string C_STRING {
+ int len = strlen($1) + strlen($2) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ strlcat($$, $2, len);
+ }
+ ;
+
+wstring: C_WSTRING {
+ int len = strlen($1) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ }
+ | string C_WSTRING {
+ int len = strlen($1) + strlen($2) + 1;
+ $$ = tmpalloc(len);
+ strlcpy($$, $1, len);
+ strlcat($$, $2, len);
+ }
+ ;
+
+cast_type: specifier_qualifier_list {
+ $$ = tymerge($1, bdty(NAME, NULL));
+ nfree($1);
+ }
+ | specifier_qualifier_list abstract_declarator {
+ $$ = tymerge($1, $2);
+ nfree($1);
+ }
+ ;
+
+funct_idn: C_NAME '(' {
+ struct symtab *s = lookup($1, 0);
+ if (s->stype == UNDEF) {
+ register NODE *q;
+ q = block(NAME, NIL, NIL, FTN|INT, 0, MKSUE(INT));
+ q->n_sp = s;
+ defid(q, EXTERN);
+ nfree(q);
+ }
+ if (s->sflags & SINLINE)
+ inline_ref($1);
+ spname = s;
+ $$ = buildtree(NAME, NIL, NIL);
+ s->suse = -lineno;
+ }
+ | term '('
+ ;
+%%
+
+NODE *
+mkty(TWORD t, union dimfun *d, struct suedef *sue)
+{
+ return block(TYPE, NIL, NIL, t, d, sue);
+}
+
+static NODE *
+bdty(int op, ...)
+{
+ va_list ap;
+ register NODE *q;
+
+ va_start(ap, op);
+ q = block(op, NIL, NIL, INT, 0, MKSUE(INT));
+
+ switch (op) {
+ case UMUL:
+ case UCALL:
+ q->n_left = va_arg(ap, NODE *);
+ q->n_rval = 0;
+ break;
+
+ case CALL:
+ q->n_left = va_arg(ap, NODE *);
+ q->n_right = va_arg(ap, NODE *);
+ break;
+
+ case LB:
+ q->n_left = va_arg(ap, NODE *);
+ q->n_right = bcon(va_arg(ap, int));
+ break;
+
+ case NAME:
+ q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */
+ break;
+
+ default:
+ cerror("bad bdty");
+ }
+ va_end(ap);
+
+ return q;
+}
+
+static void
+savebc(void)
+{
+ struct savbc *bc = tmpalloc(sizeof(struct savbc));
+
+ bc->brklab = brklab;
+ bc->contlab = contlab;
+ bc->flostat = flostat;
+ bc->next = savbc;
+ savbc = bc;
+ flostat = 0;
+}
+
+static void
+resetbc(int mask)
+{
+ flostat = savbc->flostat | (flostat&mask);
+ contlab = savbc->contlab;
+ brklab = savbc->brklab;
+ savbc = savbc->next;
+}
+
+struct swdef {
+ struct swdef *next; /* Next in list */
+ int deflbl; /* Label for "default" */
+ struct swents *ents; /* Linked sorted list of case entries */
+ int nents; /* # of entries in list */
+ int num; /* Node value will end up in */
+} *swpole;
+
+/*
+ * add case to switch
+ */
+static void
+addcase(NODE *p)
+{
+ struct swents *w, *sw = tmpalloc(sizeof(struct swents));
+
+ p = optim(p); /* change enum to ints */
+ if (p->n_op != ICON || p->n_sp != NULL) {
+ uerror( "non-constant case expression");
+ return;
+ }
+ if (swpole == NULL) {
+ uerror("case not in switch");
+ return;
+ }
+
+ sw->sval = p->n_lval;
+ plabel( sw->slab = getlab());
+ w = swpole->ents;
+ if (swpole->ents == NULL) {
+ sw->next = NULL;
+ swpole->ents = sw;
+ } else if (swpole->ents->next == NULL) {
+ if (swpole->ents->sval == sw->sval) {
+ uerror("duplicate case in switch");
+ } else if (swpole->ents->sval < sw->sval) {
+ sw->next = NULL;
+ swpole->ents->next = sw;
+ } else {
+ sw->next = swpole->ents;
+ swpole->ents = sw;
+ }
+ } else {
+ while (w->next->next != NULL && w->next->sval < sw->sval) {
+ w = w->next;
+ }
+ if (w->next->sval == sw->sval) {
+ uerror("duplicate case in switch");
+ } else if (w->next->sval > sw->sval) {
+ sw->next = w->next;
+ w->next = sw;
+ } else {
+ sw->next = NULL;
+ w->next->next = sw;
+ }
+ }
+ swpole->nents++;
+ tfree(p);
+}
+
+/*
+ * add default case to switch
+ */
+static void
+adddef(void)
+{
+ if (swpole == NULL)
+ uerror("default not inside switch");
+ else if (swpole->deflbl != 0)
+ uerror("duplicate default in switch");
+ else
+ plabel( swpole->deflbl = getlab());
+}
+
+static void
+swstart(int num)
+{
+ struct swdef *sw = tmpalloc(sizeof(struct swdef));
+
+ sw->deflbl = sw->nents = 0;
+ sw->ents = NULL;
+ sw->next = swpole;
+ sw->num = num;
+ swpole = sw;
+}
+
+/*
+ * end a switch block
+ */
+static void
+swend(void)
+{
+ struct swents *sw, **swp;
+ int i;
+
+ sw = tmpalloc(sizeof(struct swents));
+ swp = tmpalloc(sizeof(struct swents *) * (swpole->nents+1));
+
+ sw->slab = swpole->deflbl;
+ swp[0] = sw;
+
+ for (i = 1; i <= swpole->nents; i++) {
+ swp[i] = swpole->ents;
+ swpole->ents = swpole->ents->next;
+ }
+ genswitch(swpole->num, swp, swpole->nents);
+
+ swpole = swpole->next;
+}
+
+/*
+ * Declare a variable or prototype.
+ */
+static struct symtab *
+init_declarator(NODE *tn, NODE *p, int assign)
+{
+ int class = tn->n_lval;
+ NODE *typ;
+
+ typ = tymerge(tn, p);
+ typ->n_sp = lookup((char *)typ->n_sp, 0); /* XXX */
+
+ if (fun_inline && ISFTN(typ->n_type))
+ typ->n_sp->sflags |= SINLINE;
+
+ if (ISFTN(typ->n_type) == 0) {
+ setloc1(DATA);
+ if (assign) {
+ defid(typ, class);
+ typ->n_sp->sflags |= SASG;
+ lcommdel(typ->n_sp);
+ } else {
+ nidcl(typ, class);
+ }
+ } else {
+ if (assign)
+ uerror("cannot initialise function");
+ defid(typ, uclass(class));
+ }
+ nfree(p);
+ return typ->n_sp;
+}
+
+/*
+ * Declare a function.
+ */
+static void
+fundef(NODE *tp, NODE *p)
+{
+ extern int prolab;
+ struct symtab *s;
+ int class = tp->n_lval, oclass;
+ char *c;
+
+ setloc1(PROG);
+ /* Enter function args before they are clobbered in tymerge() */
+ /* Typecheck against prototype will be done in defid(). */
+ ftnarg(p);
+
+ tymerge(tp, p);
+ s = p->n_sp = lookup((char *)p->n_sp, 0); /* XXX */
+
+ oclass = s->sclass;
+ if (class == STATIC && oclass == EXTERN)
+ werror("%s was first declared extern, then static", s->sname);
+
+ if ((oclass == SNULL || oclass == USTATIC) &&
+ class == STATIC && fun_inline) {
+ /* Unreferenced, store it for (eventual) later use */
+ /* Ignore it if it not declared static */
+ s->sflags |= SINLINE;
+ inline_start(s->sname);
+ }
+ if (class == EXTERN)
+ class = SNULL; /* same result */
+
+ cftnsp = s;
+ defid(p, class);
+ prolab = getlab();
+ c = cftnsp->sname;
+#ifdef GCC_COMPAT
+ c = gcc_findname(cftnsp);
+#endif
+ send_passt(IP_PROLOG, -1, -1, c, cftnsp->stype,
+ cftnsp->sclass == EXTDEF, prolab);
+ blevel = 1;
+#ifdef STABS
+ if (gflag)
+ stabs_func(s);
+#endif
+ nfree(tp);
+ nfree(p);
+
+}
+
+static void
+fend(void)
+{
+ if (blevel)
+ cerror("function level error");
+ ftnend();
+ fun_inline = 0;
+ cftnsp = NULL;
+}
+
+static NODE *
+structref(NODE *p, int f, char *name)
+{
+ NODE *r;
+
+ if (f == DOT)
+ p = buildtree(ADDROF, p, NIL);
+ r = block(NAME, NIL, NIL, INT, 0, MKSUE(INT));
+ r->n_name = name;
+ return buildtree(STREF, p, r);
+}
+
+static void
+olddecl(NODE *p)
+{
+ struct symtab *s;
+
+ s = lookup((char *)p->n_sp, 0);
+ if (s->slevel != 1 || s->stype == UNDEF)
+ uerror("parameter '%s' not defined", s->sname);
+ else if (s->stype != FARG)
+ uerror("parameter '%s' redefined", s->sname);
+ s->stype = p->n_type;
+ s->sdf = p->n_df;
+ s->ssue = p->n_sue;
+ nfree(p);
+}
+
+void
+branch(int lbl)
+{
+ int r = reached++;
+ ecomp(block(GOTO, bcon(lbl), NIL, INT, 0, 0));
+ reached = r;
+}
+
+/*
+ * Create a printable string based on an encoded string.
+ */
+static char *
+mkpstr(char *str)
+{
+ char *s, *os;
+ int v, l = strlen(str)+1;
+
+ os = s = isinlining ? permalloc(l) : tmpalloc(l);
+ for (; *str; ) {
+ if (*str++ == '\\')
+ v = esccon(&str);
+ else
+ v = str[-1];
+ *s++ = v;
+ }
+ *s = 0;
+ return os;
+}
+
+static struct symtab *
+clbrace(NODE *p)
+{
+ struct symtab *sp;
+
+ if (blevel == 0 && xnf != NULL)
+ cerror("no level0 compound literals");
+
+ sp = getsymtab("cl", STEMP);
+ sp->stype = p->n_type;
+ sp->squal = p->n_qual;
+ sp->sdf = p->n_df;
+ sp->ssue = p->n_sue;
+ sp->sclass = blevel ? AUTO : STATIC;
+ if (!ISARY(sp->stype) || sp->sdf->ddim != 0) {
+ sp->soffset = NOOFFSET;
+ oalloc(sp, &autooff);
+ }
+ tfree(p);
+ beginit(sp);
+ return sp;
+}
--- /dev/null
+++ usr.bin/pcc/ccom/ccom.1
@@ -0,0 +1,152 @@
+.\" $Id: ccom.1,v 1.2 2007/09/26 14:48:49 ragge Exp $
+.\" $NetBSD$
+.\" $OpenBSD$
+."\
+.\" Copyright (c) 2007 Jeremy C. Reed <reed at 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 14, 2007
+.Dt ccom 1
+.Os
+.Sh NAME
+.Nm ccom
+.Nd C compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl X Ar flags
+.Op infile
+.Op outfile
+.Pp
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a C compiler.
+The frontend is usually
+.Xr pcc 1 .
+It is \fBnot\fR intended to be run directly.
+.Pp
+.Nm
+reads the C source from
+.Ar infile
+or standard input and writes the assembler source
+to
+.Ar outfile
+or to standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl g
+Enable debugging.
+.\" built into binary, explain stabs?
+.It Fl s
+Print statistics to standard error when complete.
+This includes:
+name table entries, name string size, permanent allocated memory,
+temporary allocated memory, lost memory, argument list unions,
+dimension/function unions, struct/union/enum blocks, inline node count,
+inline control blocks, and permanent symtab entries.
+.\" TODO: explain units for above?
+.It Fl W Ar flags
+Report warnings.
+(Do some basic checks.)
+NOTE! These are subject to change RSN!
+.Ar Flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy implicit
+Implies
+.Sy implicit-int
+and
+.Sy implicit-function-declaration .
+.It Sy implicit-int
+TODO
+.It Sy implicit-function-declaration
+Report if no prototype for function.
+.It Sy missing-prototypes
+TODO
+.It Sy strict-prototypes
+TODO
+.El
+.\"
+.It Fl x Ar optimizations
+.Ar optimizations
+is one or more of the following:
+.Bl -tag -width deljumps
+.It Sy deljumps
+Delete redundant jumps and dead code.
+.It Sy ssa
+Convert statements into SSA form for optimization. Not yet finished.
+.It Sy tailcall
+Currently not implemented.
+.It Sy temps
+Setting this flag allow variables to be put into registers, for further
+optimization by the register allocator.
+.El
+.\"
+.It Fl X Ar C specific debugging flags
+.Ar Flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy b
+Building of parse trees
+.It Sy d
+Declarations, more d gives more output
+.It Sy t
+Type conversions
+.It Sy i
+Initializations
+.It Sy e
+Pass1 trees at exit
+.It Sy x
+Target-specific flag, used in machine-dependent code
+.El
+.\"
+.It Fl Z Ar Code generator (pass2) specific debugging flags
+.Ar Flags
+is one or more of the following:
+.Bl -tag -width Ds
+.It Sy e
+Trees when entering pass2
+.It Sy o
+Instruction generator
+.It Sy f
+Instruction matcher, may provide much output
+.It Sy r
+Register allocator
+.It Sy t
+Type matching in instruction generator
+.It Sy s
+Shape matching in instruction generator
+.It Sy u
+Sethi-Ullman computations
+.It Sy x
+Target-specific flag, used in machine-dependent code
+.El
+.Sh SEE ALSO
+.Xr as 1 ,
+.Xr cpp 1 ,
+.Xr pcc 1
+.Sh HISTORY
+The
+.Nm
+compiler is based on the original Portable C Compiler by S. C.
+Johnson, written in the late 70's.
+Even though much of the compiler has been rewritten, some of the
+basics still remain.
+About 50% of the frontend code and 80% of the backend code has been
+rewritten.
+Most is written by Anders Magnusson, with the exception of
+the data-flow analysis part and the SSA conversion code which is
+written by Peter A Jonsson, and the Mips port that were written as
+part of a project by undergraduate students at Lulea University of
+Technology.
--- /dev/null
+++ usr.bin/pcc/ccom/trees.c
@@ -0,0 +1,2451 @@
+/* $Id: trees.c,v 1.163 2007/09/16 08:26:39 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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 conditionsand 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.
+ */
+/*
+ * Some of the changes from 32V include:
+ * - Understand "void" as type.
+ * - Handle enums as ints everywhere.
+ * - Convert some C-specific ops into branches.
+ */
+
+# include "pass1.h"
+# include "pass2.h"
+
+# include <stdarg.h>
+
+static void chkpun(NODE *p);
+static int opact(NODE *p);
+static int moditype(TWORD);
+static NODE *strargs(NODE *);
+static void rmcops(NODE *p);
+
+int lastloc = -1;
+
+/* some special actions, used in finding the type of nodes */
+# define NCVT 01
+# define PUN 02
+# define TYPL 04
+# define TYPR 010
+# define TYMATCH 040
+# define LVAL 0100
+# define CVTO 0200
+# define CVTL 0400
+# define CVTR 01000
+# define PTMATCH 02000
+# define OTHER 04000
+# define NCVTR 010000
+
+/* node conventions:
+
+ NAME: rval>0 is stab index for external
+ rval<0 is -inlabel number
+ lval is offset in bits
+ ICON: lval has the value
+ rval has the STAB index, or - label number,
+ if a name whose address is in the constant
+ rval = NONAME means no name
+ REG: rval is reg. identification cookie
+
+ */
+
+int bdebug = 0;
+
+NODE *
+buildtree(int o, NODE *l, NODE *r)
+{
+ NODE *p, *q;
+ int actions;
+ int opty;
+ struct symtab *sp = NULL; /* XXX gcc */
+ NODE *lr, *ll;
+ char *name;
+ struct symtab **elem;
+
+#ifdef PCC_DEBUG
+ if (bdebug) {
+ printf("buildtree(%s, %p, %p)\n", copst(o), l, r);
+ if (l) fwalk(l, eprint, 0);
+ if (r) fwalk(r, eprint, 0);
+ }
+#endif
+ opty = coptype(o);
+
+ /* check for constants */
+
+ if( opty == UTYPE && l->n_op == ICON ){
+
+ switch( o ){
+
+ case NOT:
+ case UMINUS:
+ case COMPL:
+ if( conval( l, o, l ) ) return(l);
+ break;
+ }
+ } else if (o == NOT && l->n_op == FCON) {
+ l = clocal(block(SCONV, l, NIL, INT, 0, MKSUE(INT)));
+ } else if( o == UMINUS && l->n_op == FCON ){
+ l->n_dcon = -l->n_dcon;
+ return(l);
+
+ } else if( o==QUEST && l->n_op==ICON ) {
+ CONSZ c = l->n_lval;
+ nfree(l);
+ if (c) {
+ tfree(r->n_right);
+ l = r->n_left;
+ nfree(r);
+ return(l);
+ } else {
+ tfree(r->n_left);
+ l = r->n_right;
+ nfree(r);
+ return(l);
+ }
+ } else if( opty == BITYPE && l->n_op == ICON && r->n_op == ICON ){
+
+ switch( o ){
+
+ case PLUS:
+ case MINUS:
+ case MUL:
+ case DIV:
+ case MOD:
+ /*
+ * Do type propagation for simple types here.
+ * The constant value is correct anyway.
+ * Maybe this op shortcut should be removed?
+ */
+ if (l->n_sp == NULL && r->n_sp == NULL &&
+ l->n_type < BTMASK && r->n_type < BTMASK) {
+ if (l->n_type > r->n_type)
+ r->n_type = l->n_type;
+ else
+ l->n_type = r->n_type;
+ }
+ /* FALLTHROUGH */
+ case ULT:
+ case UGT:
+ case ULE:
+ case UGE:
+ case LT:
+ case GT:
+ case LE:
+ case GE:
+ case EQ:
+ case NE:
+ case ANDAND:
+ case OROR:
+ case AND:
+ case OR:
+ case ER:
+ case LS:
+ case RS:
+ if( conval( l, o, r ) ) {
+ nfree(r);
+ return(l);
+ }
+ break;
+ }
+ } else if (opty == BITYPE && (l->n_op == FCON || l->n_op == ICON) &&
+ (r->n_op == FCON || r->n_op == ICON) && (o == PLUS || o == MINUS ||
+ o == MUL || o == DIV)) {
+ switch(o){
+ case PLUS:
+ case MINUS:
+ case MUL:
+ case DIV:
+ if (l->n_op == ICON)
+ l->n_dcon = l->n_lval;
+ if (r->n_op == ICON)
+ r->n_dcon = r->n_lval;
+ switch (o) {
+ case PLUS:
+ l->n_dcon += r->n_dcon; break;
+ case MINUS:
+ l->n_dcon -= r->n_dcon; break;
+ case MUL:
+ l->n_dcon *= r->n_dcon; break;
+ case DIV:
+ if (r->n_dcon == 0)
+ uerror("division by 0.");
+ else
+ l->n_dcon /= r->n_dcon;
+ }
+ l->n_op = FCON;
+ l->n_type = DOUBLE;
+ l->n_sue = MKSUE(DOUBLE);
+ nfree(r);
+ return(l);
+ }
+ }
+
+ /* its real; we must make a new node */
+
+ p = block(o, l, r, INT, 0, MKSUE(INT));
+
+ actions = opact(p);
+
+ if (actions & LVAL) { /* check left descendent */
+ if (notlval(p->n_left)) {
+ uerror("lvalue required");
+#ifdef notyet
+ } else {
+ if ((l->n_type > BTMASK && ISCON(l->n_qual)) ||
+ (l->n_type <= BTMASK && ISCON(l->n_qual << TSHIFT)))
+ if (blevel > 0)
+ uerror("lvalue is declared const");
+#endif
+ }
+ }
+
+ if( actions & NCVTR ){
+ p->n_left = pconvert( p->n_left );
+ }
+ else if( !(actions & NCVT ) ){
+ switch( opty ){
+
+ case BITYPE:
+ p->n_right = pconvert( p->n_right );
+ case UTYPE:
+ p->n_left = pconvert( p->n_left );
+
+ }
+ }
+
+ if ((actions&PUN) && (o!=CAST))
+ chkpun(p);
+
+ if( actions & (TYPL|TYPR) ){
+
+ q = (actions&TYPL) ? p->n_left : p->n_right;
+
+ p->n_type = q->n_type;
+ p->n_qual = q->n_qual;
+ p->n_df = q->n_df;
+ p->n_sue = q->n_sue;
+ }
+
+ if( actions & CVTL ) p = convert( p, CVTL );
+ if( actions & CVTR ) p = convert( p, CVTR );
+ if( actions & TYMATCH ) p = tymatch(p);
+ if( actions & PTMATCH ) p = ptmatch(p);
+
+ if( actions & OTHER ){
+ l = p->n_left;
+ r = p->n_right;
+
+ switch(o){
+
+ case NAME:
+ sp = spname;
+ if (sp->sflags & STNODE) {
+ /* Generated for optimizer */
+ p->n_op = TEMP;
+ p->n_type = sp->stype;
+ p->n_sue = sp->ssue;
+ p->n_df = sp->sdf;
+ p->n_lval = sp->soffset;
+ break;
+ }
+
+#ifdef GCC_COMPAT
+ /* Get a label name */
+ if (sp->sflags == SLBLNAME) {
+ p->n_type = VOID;
+ p->n_sue = MKSUE(VOID);
+ p->n_lval = 0;
+ p->n_sp = sp;
+ break;
+ } else
+#endif
+ if (sp->stype == UNDEF) {
+ uerror("%s undefined", sp->sname);
+ /* make p look reasonable */
+ p->n_type = INT;
+ p->n_sue = MKSUE(INT);
+ p->n_df = NULL;
+ p->n_sp = sp;
+ p->n_lval = 0;
+ defid(p, SNULL);
+ break;
+ }
+ p->n_type = sp->stype;
+ p->n_qual = sp->squal;
+ p->n_df = sp->sdf;
+ p->n_sue = sp->ssue;
+ p->n_lval = 0;
+ p->n_sp = sp;
+ /* special case: MOETY is really an ICON... */
+ if (p->n_type == MOETY) {
+ p->n_sp = NULL;
+ p->n_lval = sp->soffset;
+ p->n_df = NULL;
+ p->n_type = ENUMTY;
+ p->n_op = ICON;
+ }
+ break;
+
+ case STREF:
+ /* p->x turned into *(p+offset) */
+ /* rhs must be a name; check correctness */
+
+ /* Find member symbol struct */
+ if (l->n_type != PTR+STRTY && l->n_type != PTR+UNIONTY){
+ uerror("struct or union required");
+ break;
+ }
+
+ if ((elem = l->n_sue->suelem) == NULL)
+ uerror("undefined struct or union");
+
+ name = r->n_name;
+ for (; *elem != NULL; elem++) {
+ sp = *elem;
+ if (sp->sname == name)
+ break;
+ }
+ if (*elem == NULL)
+ uerror("member '%s' not declared", name);
+
+ r->n_sp = sp;
+ p = stref(p);
+ break;
+
+ case UMUL:
+ if (l->n_op == ADDROF) {
+ nfree(p);
+ p = l->n_left;
+ nfree(l);
+ }
+ if( !ISPTR(l->n_type))uerror("illegal indirection");
+ p->n_type = DECREF(l->n_type);
+ p->n_qual = DECREF(l->n_qual);
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+ break;
+
+ case ADDROF:
+ switch( l->n_op ){
+
+ case UMUL:
+ nfree(p);
+ p = l->n_left;
+ nfree(l);
+ case TEMP:
+ case NAME:
+ p->n_type = INCREF(l->n_type);
+ p->n_qual = INCQAL(l->n_qual);
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+ break;
+
+ case COMOP:
+ nfree(p);
+ lr = buildtree(ADDROF, l->n_right, NIL);
+ p = buildtree( COMOP, l->n_left, lr );
+ nfree(l);
+ break;
+
+ case QUEST:
+ lr = buildtree( ADDROF, l->n_right->n_right, NIL );
+ ll = buildtree( ADDROF, l->n_right->n_left, NIL );
+ nfree(p); nfree(l->n_right);
+ p = buildtree( QUEST, l->n_left, buildtree( COLON, ll, lr ) );
+ nfree(l);
+ break;
+
+ default:
+ uerror("unacceptable operand of &: %d", l->n_op );
+ break;
+ }
+ break;
+
+ case LS:
+ case RS: /* must make type size at least int... */
+ if (p->n_type == CHAR || p->n_type == SHORT) {
+ p->n_left = makety(l, INT, 0, 0, MKSUE(INT));
+ } else if (p->n_type == UCHAR || p->n_type == USHORT) {
+ p->n_left = makety(l, UNSIGNED, 0, 0,
+ MKSUE(UNSIGNED));
+ }
+ l = p->n_left;
+ p->n_type = l->n_type;
+ p->n_qual = l->n_qual;
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+
+ /* FALLTHROUGH */
+ case LSEQ:
+ case RSEQ: /* ...but not for assigned types */
+ if(tsize(r->n_type, r->n_df, r->n_sue) > SZINT)
+ p->n_right = makety(r, INT, 0, 0, MKSUE(INT));
+ break;
+
+ case RETURN:
+ case ASSIGN:
+ case CAST:
+ /* structure assignment */
+ /* take the addresses of the two sides; then make an
+ * operator using STASG and
+ * the addresses of left and right */
+
+ {
+ struct suedef *sue;
+ TWORD t;
+ union dimfun *d;
+
+ if (l->n_sue != r->n_sue)
+ uerror("assignment of different structures");
+
+ r = buildtree(ADDROF, r, NIL);
+ t = r->n_type;
+ d = r->n_df;
+ sue = r->n_sue;
+
+ l = block(STASG, l, r, t, d, sue);
+
+ if( o == RETURN ){
+ nfree(p);
+ p = l;
+ break;
+ }
+
+ p->n_op = UMUL;
+ p->n_left = l;
+ p->n_right = NIL;
+ break;
+ }
+ case COLON:
+ /* structure colon */
+
+ if (l->n_sue != r->n_sue)
+ uerror( "type clash in conditional" );
+ break;
+
+ case CALL:
+ p->n_right = r = strargs(p->n_right);
+ case UCALL:
+ if (!ISPTR(l->n_type))
+ uerror("illegal function");
+ p->n_type = DECREF(l->n_type);
+ if (!ISFTN(p->n_type))
+ uerror("illegal function");
+ p->n_type = DECREF(p->n_type);
+ p->n_df = l->n_df;
+ p->n_sue = l->n_sue;
+ if (l->n_op == ADDROF && l->n_left->n_op == NAME &&
+ l->n_left->n_sp != NULL && l->n_left->n_sp != NULL &&
+ (l->n_left->n_sp->sclass == FORTRAN ||
+ l->n_left->n_sp->sclass == UFORTRAN)) {
+ p->n_op += (FORTCALL-CALL);
+ }
+ if (p->n_type == STRTY || p->n_type == UNIONTY) {
+ /* function returning structure */
+ /* make function really return ptr to str., with * */
+
+ p->n_op += STCALL-CALL;
+ p->n_type = INCREF(p->n_type);
+ p = clocal(p); /* before recursing */
+ p = buildtree(UMUL, p, NIL);
+
+ }
+ break;
+
+ default:
+ cerror( "other code %d", o );
+ }
+
+ }
+
+ /*
+ * Allow (void)0 casts.
+ * XXX - anything on the right side must be possible to cast.
+ * XXX - remove void types further on.
+ */
+ if (p->n_op == CAST && p->n_type == VOID &&
+ p->n_right->n_op == ICON)
+ p->n_right->n_type = VOID;
+
+ if (actions & CVTO)
+ p = oconvert(p);
+ p = clocal(p);
+
+#ifdef PCC_DEBUG
+ if (bdebug) {
+ printf("End of buildtree:\n");
+ fwalk(p, eprint, 0);
+ }
+#endif
+
+ return(p);
+
+ }
+
+/*
+ * Do a conditional branch.
+ */
+void
+cbranch(NODE *p, NODE *q)
+{
+ p = buildtree(CBRANCH, p, q);
+ if (p->n_left->n_op == ICON) {
+ if (p->n_left->n_lval != 0)
+ branch(q->n_lval); /* branch always */
+ tfree(p);
+ tfree(q);
+ return;
+ }
+ ecomp(p);
+}
+
+NODE *
+strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */
+
+ if( p->n_op == CM ){
+ p->n_left = strargs( p->n_left );
+ p->n_right = strargs( p->n_right );
+ return( p );
+ }
+
+ if( p->n_type == STRTY || p->n_type == UNIONTY ){
+ p = block(STARG, p, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left = buildtree( ADDROF, p->n_left, NIL );
+ p = clocal(p);
+ }
+ return( p );
+}
+
+/*
+ * apply the op o to the lval part of p; if binary, rhs is val
+ */
+int
+conval(NODE *p, int o, NODE *q)
+{
+ int i, u;
+ CONSZ val;
+ U_CONSZ v1, v2;
+
+ val = q->n_lval;
+ u = ISUNSIGNED(p->n_type) || ISUNSIGNED(q->n_type);
+ if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
+
+ if (p->n_sp != NULL && q->n_sp != NULL)
+ return(0);
+ if (q->n_sp != NULL && o != PLUS)
+ return(0);
+ if (p->n_sp != NULL && o != PLUS && o != MINUS)
+ return(0);
+ v1 = p->n_lval;
+ v2 = q->n_lval;
+ switch( o ){
+
+ case PLUS:
+ p->n_lval += val;
+ if (p->n_sp == NULL) {
+ p->n_rval = q->n_rval;
+ p->n_type = q->n_type;
+ }
+ break;
+ case MINUS:
+ p->n_lval -= val;
+ break;
+ case MUL:
+ p->n_lval *= val;
+ break;
+ case DIV:
+ if (val == 0)
+ uerror("division by 0");
+ else {
+ if (u) {
+ v1 /= v2;
+ p->n_lval = v1;
+ } else
+ p->n_lval /= val;
+ }
+ break;
+ case MOD:
+ if (val == 0)
+ uerror("division by 0");
+ else {
+ if (u) {
+ v1 %= v2;
+ p->n_lval = v1;
+ } else
+ p->n_lval %= val;
+ }
+ break;
+ case AND:
+ p->n_lval &= val;
+ break;
+ case OR:
+ p->n_lval |= val;
+ break;
+ case ER:
+ p->n_lval ^= val;
+ break;
+ case LS:
+ i = val;
+ p->n_lval = p->n_lval << i;
+ break;
+ case RS:
+ i = val;
+ if (u) {
+ v1 = v1 >> i;
+ p->n_lval = v1;
+ } else
+ p->n_lval = p->n_lval >> i;
+ break;
+
+ case UMINUS:
+ p->n_lval = - p->n_lval;
+ break;
+ case COMPL:
+ p->n_lval = ~p->n_lval;
+ break;
+ case NOT:
+ p->n_lval = !p->n_lval;
+ break;
+ case LT:
+ p->n_lval = p->n_lval < val;
+ break;
+ case LE:
+ p->n_lval = p->n_lval <= val;
+ break;
+ case GT:
+ p->n_lval = p->n_lval > val;
+ break;
+ case GE:
+ p->n_lval = p->n_lval >= val;
+ break;
+ case ULT:
+ p->n_lval = v1 < v2;
+ break;
+ case ULE:
+ p->n_lval = v1 <= v2;
+ break;
+ case UGT:
+ p->n_lval = v1 > v2;
+ break;
+ case UGE:
+ p->n_lval = v1 >= v2;
+ break;
+ case EQ:
+ p->n_lval = p->n_lval == val;
+ break;
+ case NE:
+ p->n_lval = p->n_lval != val;
+ break;
+ case ANDAND:
+ p->n_lval = p->n_lval && val;
+ break;
+ case OROR:
+ p->n_lval = p->n_lval || val;
+ break;
+ default:
+ return(0);
+ }
+ return(1);
+ }
+
+/*
+ * Checks p for the existance of a pun. This is called when the op of p
+ * is ASSIGN, RETURN, CAST, COLON, or relational.
+ * One case is when enumerations are used: this applies only to lint.
+ * In the other case, one operand is a pointer, the other integer type
+ * we check that this integer is in fact a constant zero...
+ * in the case of ASSIGN, any assignment of pointer to integer is illegal
+ * this falls out, because the LHS is never 0.
+ */
+void
+chkpun(NODE *p)
+{
+ union dimfun *d1, *d2;
+ NODE *q;
+ int t1, t2;
+
+ t1 = p->n_left->n_type;
+ t2 = p->n_right->n_type;
+
+ switch (p->n_op) {
+ case RETURN:
+ /* return of void allowed but nothing else */
+ if (t1 == VOID && t2 == VOID)
+ return;
+ if (t1 == VOID) {
+ werror("returning value from void function");
+ return;
+ }
+ if (t2 == VOID) {
+ uerror("using void value");
+ return;
+ }
+ case COLON:
+ if (t1 == VOID && t2 == VOID)
+ return;
+ break;
+ default:
+ if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID))
+ return uerror("value of void expression used");
+ break;
+ }
+
+ /* allow void pointer assignments in any direction */
+ if (BTYPE(t1) == VOID && (t2 & TMASK))
+ return;
+ if (BTYPE(t2) == VOID && (t1 & TMASK))
+ return;
+
+#ifdef notdef
+ /* C99 says that enums always should be handled as ints */
+ /* check for enumerations */
+ if (t1==ENUMTY || t2==ENUMTY) {
+ if( clogop( p->n_op ) && p->n_op != EQ && p->n_op != NE ) {
+ werror( "comparison of enums" );
+ return;
+ }
+ if (t1==ENUMTY && t2==ENUMTY) {
+ if (p->n_left->n_sue!=p->n_right->n_sue)
+ werror("enumeration type clash, "
+ "operator %s", copst(p->n_op));
+ return;
+ }
+ if ((t1 == ENUMTY && t2 <= BTMASK) ||
+ (t2 == ENUMTY && t1 <= BTMASK))
+ return;
+ }
+#endif
+
+ if (ISPTR(t1) || ISARY(t1))
+ q = p->n_right;
+ else
+ q = p->n_left;
+
+ if (!ISPTR(q->n_type) && !ISARY(q->n_type)) {
+ if (q->n_op != ICON || q->n_lval != 0)
+ werror("illegal combination of pointer and integer");
+ } else {
+ d1 = p->n_left->n_df;
+ d2 = p->n_right->n_df;
+ if (t1 == t2) {
+ if (p->n_left->n_sue != p->n_right->n_sue)
+ werror("illegal structure pointer combination");
+ return;
+ }
+ for (;;) {
+ if (ISARY(t1) || ISPTR(t1)) {
+ if (!ISARY(t2) && !ISPTR(t2))
+ break;
+ if (ISARY(t1) && ISARY(t2) && d1->ddim != d2->ddim) {
+ werror("illegal array size combination");
+ return;
+ }
+ if (ISARY(t1))
+ ++d1;
+ if (ISARY(t2))
+ ++d2;
+ } else if (ISFTN(t1)) {
+ if (chkftn(d1->dfun, d2->dfun)) {
+ werror("illegal function "
+ "pointer combination");
+ return;
+ }
+ ++d1;
+ ++d2;
+ } else
+ break;
+ t1 = DECREF(t1);
+ t2 = DECREF(t2);
+ }
+ werror("illegal pointer combination");
+ }
+}
+
+NODE *
+stref(NODE *p)
+{
+ NODE *r;
+ struct suedef *sue;
+ union dimfun *d;
+ TWORD t, q;
+ int dsc;
+ OFFSZ off;
+ struct symtab *s;
+
+ /* make p->x */
+ /* this is also used to reference automatic variables */
+
+ s = p->n_right->n_sp;
+ nfree(p->n_right);
+ r = p->n_left;
+ nfree(p);
+ p = pconvert(r);
+
+ /* make p look like ptr to x */
+
+ if (!ISPTR(p->n_type))
+ p->n_type = PTR+UNIONTY;
+
+ t = INCREF(s->stype);
+ q = INCQAL(s->squal);
+ d = s->sdf;
+ sue = s->ssue;
+
+ p = makety(p, t, q, d, sue);
+
+ /* compute the offset to be added */
+
+ off = s->soffset;
+ dsc = s->sclass;
+
+ if (dsc & FIELD) { /* make fields look like ints */
+ off = (off/ALINT)*ALINT;
+ sue = MKSUE(INT);
+ }
+ if (off != 0) {
+ p = block(PLUS, p, offcon(off, t, d, sue), t, d, sue);
+ p->n_qual = q;
+ p = optim(p);
+ }
+
+ p = buildtree(UMUL, p, NIL);
+
+ /* if field, build field info */
+
+ if (dsc & FIELD) {
+ p = block(FLD, p, NIL, s->stype, 0, s->ssue);
+ p->n_qual = q;
+ p->n_rval = PKFIELD(dsc&FLDSIZ, s->soffset%ALINT);
+ }
+
+ p = clocal(p);
+ return p;
+}
+
+int
+notlval(p) register NODE *p; {
+
+ /* return 0 if p an lvalue, 1 otherwise */
+
+ again:
+
+ switch( p->n_op ){
+
+ case FLD:
+ p = p->n_left;
+ goto again;
+
+ case NAME:
+ case OREG:
+ case UMUL:
+ if( ISARY(p->n_type) || ISFTN(p->n_type) ) return(1);
+ case TEMP:
+ case REG:
+ return(0);
+
+ default:
+ return(1);
+
+ }
+
+ }
+/* make a constant node with value i */
+NODE *
+bcon(int i)
+{
+ register NODE *p;
+
+ p = block(ICON, NIL, NIL, INT, 0, MKSUE(INT));
+ p->n_lval = i;
+ p->n_sp = NULL;
+ return(clocal(p));
+}
+
+NODE *
+bpsize(NODE *p)
+{
+ return(offcon(psize(p), p->n_type, p->n_df, p->n_sue));
+}
+
+/*
+ * p is a node of type pointer; psize returns the
+ * size of the thing pointed to
+ */
+OFFSZ
+psize(NODE *p)
+{
+
+ if (!ISPTR(p->n_type)) {
+ uerror("pointer required");
+ return(SZINT);
+ }
+ /* note: no pointers to fields */
+ return(tsize(DECREF(p->n_type), p->n_df, p->n_sue));
+}
+
+/*
+ * convert an operand of p
+ * f is either CVTL or CVTR
+ * operand has type int, and is converted by the size of the other side
+ * convert is called when an integer is to be added to a pointer, for
+ * example in arrays or structures.
+ */
+NODE *
+convert(NODE *p, int f)
+{
+ union dimfun *df;
+ TWORD ty, ty2;
+ NODE *q, *r, *s, *rv;
+
+ if (f == CVTL) {
+ q = p->n_left;
+ s = p->n_right;
+ } else {
+ q = p->n_right;
+ s = p->n_left;
+ }
+ ty2 = ty = DECREF(s->n_type);
+ while (ISARY(ty))
+ ty = DECREF(ty);
+
+ r = offcon(tsize(ty, s->n_df, s->n_sue), s->n_type, s->n_df, s->n_sue);
+ ty = ty2;
+ rv = bcon(1);
+ df = s->n_df;
+ while (ISARY(ty)) {
+ rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) :
+ tempnode(-df->ddim, INT, 0, MKSUE(INT)));
+ df++;
+ ty = DECREF(ty);
+ }
+ rv = clocal(block(PMCONV, rv, r, INT, 0, MKSUE(INT)));
+ rv = optim(rv);
+
+ r = block(PMCONV, q, rv, INT, 0, MKSUE(INT));
+ r = clocal(r);
+ /*
+ * Indexing is only allowed with integer arguments, so insert
+ * SCONV here if arg is not an integer.
+ * XXX - complain?
+ */
+ if (r->n_type != INT)
+ r = clocal(block(SCONV, r, NIL, INT, 0, MKSUE(INT)));
+ if (f == CVTL)
+ p->n_left = r;
+ else
+ p->n_right = r;
+ return(p);
+}
+
+/*
+ * change enums to ints, or appropriate types
+ */
+void
+econvert( p ) register NODE *p; {
+
+
+ register TWORD ty;
+
+ if( (ty=BTYPE(p->n_type)) == ENUMTY || ty == MOETY ) {
+ if (p->n_sue->suesize == SZCHAR)
+ ty = INT;
+ else if (p->n_sue->suesize == SZINT)
+ ty = INT;
+ else if (p->n_sue->suesize == SZSHORT)
+ ty = INT;
+ else if (p->n_sue->suesize == SZLONGLONG)
+ ty = LONGLONG;
+ else
+ ty = LONG;
+ ty = ctype(ty);
+ p->n_sue = MKSUE(ty);
+ MODTYPE(p->n_type,ty);
+ if (p->n_op == ICON && ty != LONG && ty != LONGLONG)
+ p->n_type = INT, p->n_sue = MKSUE(INT);
+ }
+}
+
+NODE *
+pconvert( p ) register NODE *p; {
+
+ /* if p should be changed into a pointer, do so */
+
+ if( ISARY( p->n_type) ){
+ p->n_type = DECREF( p->n_type );
+ ++p->n_df;
+ return( buildtree( ADDROF, p, NIL ) );
+ }
+ if( ISFTN( p->n_type) )
+ return( buildtree( ADDROF, p, NIL ) );
+
+ return( p );
+ }
+
+NODE *
+oconvert(p) register NODE *p; {
+ /* convert the result itself: used for pointer and unsigned */
+
+ switch(p->n_op) {
+
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ if( ISUNSIGNED(p->n_left->n_type) || ISUNSIGNED(p->n_right->n_type) ) p->n_op += (ULE-LE);
+ case EQ:
+ case NE:
+ return( p );
+
+ case MINUS:
+ return( clocal( block( PVCONV,
+ p, bpsize(p->n_left), INT, 0, MKSUE(INT))));
+ }
+
+ cerror( "illegal oconvert: %d", p->n_op );
+
+ return(p);
+ }
+
+/*
+ * makes the operands of p agree; they are
+ * either pointers or integers, by this time
+ * with MINUS, the sizes must be the same
+ * with COLON, the types must be the same
+ */
+NODE *
+ptmatch(NODE *p)
+{
+ struct suedef *sue, *sue2;
+ union dimfun *d, *d2;
+ TWORD t1, t2, t, q1, q2, q;
+ int o;
+
+ o = p->n_op;
+ t = t1 = p->n_left->n_type;
+ q = q1 = p->n_left->n_qual;
+ t2 = p->n_right->n_type;
+ q2 = p->n_right->n_qual;
+ d = p->n_left->n_df;
+ d2 = p->n_right->n_df;
+ sue = p->n_left->n_sue;
+ sue2 = p->n_right->n_sue;
+
+ switch( o ){
+
+ case ASSIGN:
+ case RETURN:
+ case CAST:
+ { break; }
+
+ case MINUS:
+ { if( psize(p->n_left) != psize(p->n_right) ){
+ uerror( "illegal pointer subtraction");
+ }
+ break;
+ }
+ case COLON:
+ if (t1 != t2) {
+ /*
+ * Check for void pointer types. They are allowed
+ * to cast to/from any pointers.
+ */
+ if (ISPTR(t1) && ISPTR(t2) &&
+ (BTYPE(t1) == VOID || BTYPE(t2) == VOID))
+ break;
+ uerror("illegal types in :");
+ }
+ break;
+
+ default: /* must work harder: relationals or comparisons */
+
+ if( !ISPTR(t1) ){
+ t = t2;
+ q = q2;
+ d = d2;
+ sue = sue2;
+ break;
+ }
+ if( !ISPTR(t2) ){
+ break;
+ }
+
+ /* both are pointers */
+ if( talign(t2,sue2) < talign(t,sue) ){
+ t = t2;
+ q = q2;
+ sue = sue2;
+ }
+ break;
+ }
+
+ p->n_left = makety( p->n_left, t, q, d, sue );
+ p->n_right = makety( p->n_right, t, q, d, sue );
+ if( o!=MINUS && !clogop(o) ){
+
+ p->n_type = t;
+ p->n_qual = q;
+ p->n_df = d;
+ p->n_sue = sue;
+ }
+
+ return(clocal(p));
+ }
+
+int tdebug = 0;
+
+NODE *
+tymatch(p) register NODE *p; {
+
+ /* satisfy the types of various arithmetic binary ops */
+
+ /* rules are:
+ if assignment, type of LHS
+ if any doubles, make double
+ else if any float make float
+ else if any longlongs, make long long
+ else if any longs, make long
+ else etcetc.
+ if either operand is unsigned, the result is...
+ */
+
+ TWORD t1, t2, t, tu;
+ int o, lu, ru;
+
+ o = p->n_op;
+
+ t1 = p->n_left->n_type;
+ t2 = p->n_right->n_type;
+
+ lu = ru = 0;
+ if( ISUNSIGNED(t1) ){
+ lu = 1;
+ t1 = DEUNSIGN(t1);
+ }
+ if( ISUNSIGNED(t2) ){
+ ru = 1;
+ t2 = DEUNSIGN(t2);
+ }
+
+ if (t1 == ENUMTY || t1 == MOETY)
+ t1 = INT; /* XXX */
+ if (t2 == ENUMTY || t2 == MOETY)
+ t2 = INT; /* XXX */
+#if 0
+ if ((t1 == CHAR || t1 == SHORT) && o!= RETURN)
+ t1 = INT;
+ if (t2 == CHAR || t2 == SHORT)
+ t2 = INT;
+#endif
+
+ if (t1 == LDOUBLE || t2 == LDOUBLE)
+ t = LDOUBLE;
+ else if (t1 == DOUBLE || t2 == DOUBLE)
+ t = DOUBLE;
+ else if (t1 == FLOAT || t2 == FLOAT)
+ t = FLOAT;
+ else if (t1==LONGLONG || t2 == LONGLONG)
+ t = LONGLONG;
+ else if (t1==LONG || t2==LONG)
+ t = LONG;
+ else /* if (t1==INT || t2==INT) */
+ t = INT;
+#if 0
+ else if (t1==SHORT || t2==SHORT)
+ t = SHORT;
+ else
+ t = CHAR;
+#endif
+
+ if( casgop(o) ){
+ tu = p->n_left->n_type;
+ t = t1;
+ } else {
+ tu = ((ru|lu) && UNSIGNABLE(t))?ENUNSIGN(t):t;
+ }
+
+ /* because expressions have values that are at least as wide
+ as INT or UNSIGNED, the only conversions needed
+ are those involving FLOAT/DOUBLE, and those
+ from LONG to INT and ULONG to UNSIGNED */
+
+
+ if (t != t1 || (ru && !lu))
+ p->n_left = makety( p->n_left, tu, 0, 0, MKSUE(tu));
+
+ if (t != t2 || o==CAST || (lu && !ru))
+ p->n_right = makety(p->n_right, tu, 0, 0, MKSUE(tu));
+
+ if( casgop(o) ){
+ p->n_type = p->n_left->n_type;
+ p->n_df = p->n_left->n_df;
+ p->n_sue = p->n_left->n_sue;
+ }
+ else if( !clogop(o) ){
+ p->n_type = tu;
+ p->n_df = NULL;
+ p->n_sue = MKSUE(t);
+ }
+
+#ifdef PCC_DEBUG
+ if (tdebug) {
+ printf("tymatch(%p): ", p);
+ tprint(stdout, t1, 0);
+ printf(" %s ", copst(o));
+ tprint(stdout, t2, 0);
+ printf(" => ");
+ tprint(stdout, tu, 0);
+ printf("\n");
+ }
+#endif
+
+ return(p);
+ }
+
+/*
+ * make p into type t by inserting a conversion
+ */
+NODE *
+makety(NODE *p, TWORD t, TWORD q, union dimfun *d, struct suedef *sue)
+{
+
+ if (p->n_type == ENUMTY && p->n_op == ICON)
+ econvert(p);
+ if (t == p->n_type) {
+ p->n_df = d;
+ p->n_sue = sue;
+ p->n_qual = q;
+ return(p);
+ }
+
+ if ((p->n_type == FLOAT || p->n_type == DOUBLE || p->n_type == LDOUBLE)
+ && (t == FLOAT || t == DOUBLE || t == LDOUBLE) && p->n_op == FCON) {
+ p->n_type = t;
+ p->n_qual = q;
+ p->n_df = d;
+ p->n_sue = sue;
+ return(p);
+ }
+
+ if (t & TMASK) {
+ /* non-simple type */
+ p = block(PCONV, p, NIL, t, d, sue);
+ p->n_qual = q;
+ return clocal(p);
+ }
+
+ if (p->n_op == ICON) {
+ if (t == DOUBLE || t == FLOAT) {
+ p->n_op = FCON;
+ if (ISUNSIGNED(p->n_type))
+ p->n_dcon = (U_CONSZ) p->n_lval;
+ else
+ p->n_dcon = p->n_lval;
+ p->n_type = t;
+ p->n_qual = q;
+ p->n_sue = MKSUE(t);
+ return (clocal(p));
+ }
+ }
+ p = block(SCONV, p, NIL, t, d, sue);
+ p->n_qual = q;
+ return clocal(p);
+
+}
+
+NODE *
+block(int o, NODE *l, NODE *r, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ register NODE *p;
+
+ p = talloc();
+ p->n_rval = 0;
+ p->n_op = o;
+ p->n_lval = 0; /* Protect against large lval */
+ p->n_left = l;
+ p->n_right = r;
+ p->n_type = t;
+ p->n_qual = 0;
+ p->n_df = d;
+ p->n_sue = sue;
+#if !defined(MULTIPASS)
+ /* p->n_reg = */p->n_su = 0;
+ p->n_regw = 0;
+#endif
+ return(p);
+ }
+
+int
+icons(p) register NODE *p; {
+ /* if p is an integer constant, return its value */
+ int val;
+
+ if( p->n_op != ICON ){
+ uerror( "constant expected");
+ val = 1;
+ }
+ else {
+ val = p->n_lval;
+ if( val != p->n_lval ) uerror( "constant too big for cross-compiler" );
+ }
+ tfree( p );
+ return(val);
+}
+
+/*
+ * the intent of this table is to examine the
+ * operators, and to check them for
+ * correctness.
+ *
+ * The table is searched for the op and the
+ * modified type (where this is one of the
+ * types INT (includes char and short), LONG,
+ * DOUBLE (includes FLOAT), and POINTER
+ *
+ * The default action is to make the node type integer
+ *
+ * The actions taken include:
+ * PUN check for puns
+ * CVTL convert the left operand
+ * CVTR convert the right operand
+ * TYPL the type is determined by the left operand
+ * TYPR the type is determined by the right operand
+ * TYMATCH force type of left and right to match,by inserting conversions
+ * PTMATCH like TYMATCH, but for pointers
+ * LVAL left operand must be lval
+ * CVTO convert the op
+ * NCVT do not convert the operands
+ * OTHER handled by code
+ * NCVTR convert the left operand, not the right...
+ *
+ */
+
+# define MINT 01 /* integer */
+# define MDBI 02 /* integer or double */
+# define MSTR 04 /* structure */
+# define MPTR 010 /* pointer */
+# define MPTI 020 /* pointer or integer */
+# define MENU 040 /* enumeration variable or member */
+
+int
+opact(NODE *p)
+{
+ int mt12, mt1, mt2, o;
+
+ mt1 = mt2 = mt12 = 0;
+
+ switch (coptype(o = p->n_op)) {
+ case BITYPE:
+ mt12=mt2 = moditype(p->n_right->n_type);
+ case UTYPE:
+ mt12 &= (mt1 = moditype(p->n_left->n_type));
+ break;
+ }
+
+ switch( o ){
+
+ case NAME :
+ case ICON :
+ case FCON :
+ case CALL :
+ case UCALL:
+ case UMUL:
+ { return( OTHER ); }
+ case UMINUS:
+ if( mt1 & MDBI ) return( TYPL );
+ break;
+
+ case COMPL:
+ if( mt1 & MINT ) return( TYPL );
+ break;
+
+ case ADDROF:
+ return( NCVT+OTHER );
+ case NOT:
+/* case INIT: */
+ case CM:
+ case CBRANCH:
+ case ANDAND:
+ case OROR:
+ return( 0 );
+
+ case MUL:
+ case DIV:
+ if ((mt1&MDBI) && (mt2&MENU)) return( TYMATCH );
+ if ((mt2&MDBI) && (mt1&MENU)) return( TYMATCH );
+ if( mt12 & MDBI ) return( TYMATCH );
+ break;
+
+ case MOD:
+ case AND:
+ case OR:
+ case ER:
+ if( mt12 & MINT ) return( TYMATCH );
+ break;
+
+ case LS:
+ case RS:
+ if( mt12 & MINT ) return( TYPL+OTHER );
+ break;
+
+ case EQ:
+ case NE:
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ if( mt12 & MDBI ) return( TYMATCH+CVTO );
+ else if( mt12 & MPTR ) return( PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( PTMATCH+PUN );
+ else break;
+
+ case QUEST:
+ case COMOP:
+ if( mt2&MENU ) return( TYPR+NCVTR );
+ return( TYPR );
+
+ case STREF:
+ return( NCVTR+OTHER );
+
+ case FORCE:
+ return( TYPL );
+
+ case COLON:
+ if( mt12 & MDBI ) return( TYMATCH );
+ else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
+ else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
+ else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
+ else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
+ break;
+
+ case ASSIGN:
+ case RETURN:
+ if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
+ case CAST:
+ if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+#if 0
+ else if(mt1&MENU && mt2&MDBI) return( TYPL+LVAL+TYMATCH );
+ else if(mt2&MENU && mt1&MDBI) return( TYPL+LVAL+TYMATCH );
+ else if( (mt1&MENU)||(mt2&MENU) )
+ return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+#endif
+ else if( mt1 & MPTR) return( LVAL+PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+ break;
+
+ case LSEQ:
+ case RSEQ:
+ if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
+ break;
+
+ case MULEQ:
+ case DIVEQ:
+ if( mt12 & MDBI ) return( LVAL+TYMATCH );
+ break;
+
+ case MODEQ:
+ case ANDEQ:
+ case OREQ:
+ case EREQ:
+ if (mt12 & MINT)
+ return(LVAL+TYMATCH);
+ break;
+
+ case PLUSEQ:
+ case MINUSEQ:
+ case INCR:
+ case DECR:
+ if (mt12 & MDBI)
+ return(TYMATCH+LVAL);
+ else if ((mt1&MPTR) && (mt2&MINT))
+ return(TYPL+LVAL+CVTR);
+ break;
+
+ case MINUS:
+ if (mt12 & MPTR)
+ return(CVTO+PTMATCH+PUN);
+ if (mt2 & MPTR)
+ break;
+ /* FALLTHROUGH */
+ case PLUS:
+ if (mt12 & MDBI)
+ return(TYMATCH);
+ else if ((mt1&MPTR) && (mt2&MINT))
+ return(TYPL+CVTR);
+ else if ((mt1&MINT) && (mt2&MPTR))
+ return(TYPR+CVTL);
+
+ }
+ uerror("operands of %s have incompatible types", copst(o));
+ return(NCVT);
+}
+
+int
+moditype(TWORD ty)
+{
+ switch (ty) {
+
+ case ENUMTY:
+ case MOETY:
+ return( MENU|MINT|MDBI|MPTI );
+
+ case STRTY:
+ case UNIONTY:
+ return( MSTR );
+
+ case BOOL:
+ case CHAR:
+ case SHORT:
+ case UCHAR:
+ case USHORT:
+ case UNSIGNED:
+ case ULONG:
+ case ULONGLONG:
+ case INT:
+ case LONG:
+ case LONGLONG:
+ return( MINT|MDBI|MPTI );
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+ return( MDBI );
+ default:
+ return( MPTR|MPTI );
+
+ }
+}
+
+int tvaloff = 100;
+
+/*
+ * Returns a TEMP node with temp number nr.
+ * If nr == 0, return a node with a new number.
+ */
+NODE *
+tempnode(int nr, TWORD type, union dimfun *df, struct suedef *sue)
+{
+ NODE *r;
+
+ r = block(TEMP, NIL, NIL, type, df, sue);
+ r->n_lval = nr ? nr : tvaloff;
+ tvaloff += szty(type);
+ return r;
+}
+
+/*
+ * Do sizeof on p.
+ */
+NODE *
+doszof(NODE *p)
+{
+ union dimfun *df;
+ TWORD ty;
+ NODE *rv;
+
+ /*
+ * Arrays may be dynamic, may need to make computations.
+ */
+
+ rv = bcon(1);
+ df = p->n_df;
+ ty = p->n_type;
+ while (ISARY(ty)) {
+ rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) :
+ tempnode(-df->ddim, INT, 0, MKSUE(INT)));
+ df++;
+ ty = DECREF(ty);
+ }
+ rv = buildtree(MUL, rv, bcon(tsize(ty, p->n_df, p->n_sue)/SZCHAR));
+ tfree(p);
+ return rv;
+}
+
+#ifdef PCC_DEBUG
+void
+eprint(NODE *p, int down, int *a, int *b)
+{
+ int ty;
+
+ *a = *b = down+1;
+ while( down > 1 ){
+ printf( "\t" );
+ down -= 2;
+ }
+ if( down ) printf( " " );
+
+ ty = coptype( p->n_op );
+
+ printf("%p) %s, ", p, copst(p->n_op));
+ if (ty == LTYPE) {
+ printf(CONFMT, p->n_lval);
+ printf(", %d, ", p->n_rval);
+ }
+ tprint(stdout, p->n_type, p->n_qual);
+ printf( ", %p, %p\n", p->n_df, p->n_sue );
+}
+# endif
+
+void
+prtdcon(NODE *p)
+{
+ int o = p->n_op, i;
+
+ if (o != FCON)
+ return;
+
+ /* Write float constants to memory */
+ /* Should be volontary per architecture */
+
+ setloc1(RDATA);
+ defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ?
+ ALDOUBLE : ALLDOUBLE );
+ deflab1(i = getlab());
+ ninval(0, btdims[p->n_type].suesize, p);
+ p->n_op = NAME;
+ p->n_lval = 0;
+ p->n_sp = tmpalloc(sizeof(struct symtab_hdr));
+ p->n_sp->sclass = ILABEL;
+ p->n_sp->soffset = i;
+}
+
+extern int negrel[];
+
+/*
+ * Walk up through the tree from the leaves,
+ * removing constant operators.
+ */
+static void
+logwalk(NODE *p)
+{
+ int o = coptype(p->n_op);
+ NODE *l, *r;
+
+ l = p->n_left;
+ r = p->n_right;
+ switch (o) {
+ case LTYPE:
+ return;
+ case BITYPE:
+ logwalk(r);
+ case UTYPE:
+ logwalk(l);
+ }
+ if (!clogop(p->n_op))
+ return;
+ if (p->n_op == NOT && l->n_op == ICON) {
+ p->n_lval = l->n_lval == 0;
+ nfree(l);
+ p->n_op = ICON;
+ }
+ if (l->n_op == ICON && r->n_op == ICON) {
+ if (conval(l, p->n_op, r) == 0) {
+ /*
+ * people sometimes tend to do really odd compares,
+ * like "if ("abc" == "def")" etc.
+ * do it runtime instead.
+ */
+ } else {
+ p->n_lval = l->n_lval;
+ p->n_op = ICON;
+ nfree(l);
+ nfree(r);
+ }
+ }
+}
+
+/*
+ * Removes redundant logical operators for branch conditions.
+ */
+static void
+fixbranch(NODE *p, int label)
+{
+
+ logwalk(p);
+
+ if (p->n_op == ICON) {
+ if (p->n_lval != 0)
+ branch(label);
+ nfree(p);
+ } else {
+ if (!clogop(p->n_op)) /* Always conditional */
+ p = buildtree(NE, p, bcon(0));
+ ecode(buildtree(CBRANCH, p, bcon(label)));
+ }
+}
+
+/*
+ * Write out logical expressions as branches.
+ */
+static void
+andorbr(NODE *p, int true, int false)
+{
+ NODE *q;
+ int o, lab;
+
+ lab = -1;
+ switch (o = p->n_op) {
+ case EQ:
+ case NE:
+ /*
+ * Remove redundant EQ/NE nodes.
+ */
+ while (((o = p->n_left->n_op) == EQ || o == NE) &&
+ p->n_right->n_op == ICON) {
+ o = p->n_op;
+ q = p->n_left;
+ if (p->n_right->n_lval == 0) {
+ nfree(p->n_right);
+ *p = *q;
+ nfree(q);
+ if (o == EQ)
+ p->n_op = negrel[p->n_op - EQ];
+// p->n_op = NE; /* toggla */
+ } else if (p->n_right->n_lval == 1) {
+ nfree(p->n_right);
+ *p = *q;
+ nfree(q);
+ if (o == NE)
+ p->n_op = negrel[p->n_op - EQ];
+// p->n_op = EQ; /* toggla */
+ } else
+ break; /* XXX - should always be false */
+
+ }
+ /* FALLTHROUGH */
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+calc: if (true < 0) {
+ p->n_op = negrel[p->n_op - EQ];
+ true = false;
+ false = -1;
+ }
+
+ rmcops(p->n_left);
+ rmcops(p->n_right);
+ fixbranch(p, true);
+ if (false >= 0)
+ branch(false);
+ break;
+
+ case ULE:
+ case UGT:
+ /* Convert to friendlier ops */
+ if (p->n_right->n_op == ICON && p->n_right->n_lval == 0)
+ p->n_op = o == ULE ? EQ : NE;
+ goto calc;
+
+ case UGE:
+ case ULT:
+ /* Already true/false by definition */
+ if (p->n_right->n_op == ICON && p->n_right->n_lval == 0) {
+ if (true < 0) {
+ o = o == ULT ? UGE : ULT;
+ true = false;
+ }
+ rmcops(p->n_left);
+ ecode(p->n_left);
+ rmcops(p->n_right);
+ ecode(p->n_right);
+ nfree(p);
+ if (o == UGE) /* true */
+ branch(true);
+ break;
+ }
+ goto calc;
+
+ case ANDAND:
+ lab = false<0 ? getlab() : false ;
+ andorbr(p->n_left, -1, lab);
+ andorbr(p->n_right, true, false);
+ if (false < 0)
+ plabel( lab);
+ nfree(p);
+ break;
+
+ case OROR:
+ lab = true<0 ? getlab() : true;
+ andorbr(p->n_left, lab, -1);
+ andorbr(p->n_right, true, false);
+ if (true < 0)
+ plabel( lab);
+ nfree(p);
+ break;
+
+ case NOT:
+ andorbr(p->n_left, false, true);
+ nfree(p);
+ break;
+
+ default:
+ rmcops(p);
+ if (true >= 0)
+ fixbranch(p, true);
+ if (false >= 0) {
+ if (true >= 0)
+ branch(false);
+ else
+ fixbranch(buildtree(EQ, p, bcon(0)), false);
+ }
+ }
+}
+
+/*
+ * Massage the output trees to remove C-specific nodes:
+ * COMOPs are split into separate statements.
+ * QUEST/COLON are rewritten to branches.
+ * ANDAND/OROR/NOT are rewritten to branches for lazy-evaluation.
+ * CBRANCH conditions are rewritten for lazy-evaluation.
+ */
+static void
+rmcops(NODE *p)
+{
+ TWORD type;
+ NODE *q, *r;
+ int o, ty, lbl, lbl2, tval = 0;
+
+again:
+ o = p->n_op;
+ ty = coptype(o);
+ switch (o) {
+ case QUEST:
+
+ /*
+ * Create a branch node from ?:
+ * || and && must be taken special care of.
+ */
+ type = p->n_type;
+ andorbr(p->n_left, -1, lbl = getlab());
+
+ /* Make ASSIGN node */
+ /* Only if type is not void */
+ q = p->n_right->n_left;
+ if (type != VOID) {
+ r = tempnode(0, q->n_type, q->n_df, q->n_sue);
+ tval = r->n_lval;
+ q = buildtree(ASSIGN, r, q);
+ }
+ rmcops(q);
+ ecode(q); /* Done with assign */
+ branch(lbl2 = getlab());
+ plabel( lbl);
+
+ q = p->n_right->n_right;
+ if (type != VOID) {
+ r = tempnode(tval, q->n_type, q->n_df, q->n_sue);
+ q = buildtree(ASSIGN, r, q);
+ }
+ rmcops(q);
+ ecode(q); /* Done with assign */
+
+ plabel( lbl2);
+
+ nfree(p->n_right);
+ if (p->n_type != VOID) {
+ r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
+ *p = *r;
+ nfree(r);
+ } else
+ p->n_op = ICON;
+ break;
+
+ case ULE:
+ case ULT:
+ case UGE:
+ case UGT:
+ case EQ:
+ case NE:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ case ANDAND:
+ case OROR:
+ case NOT:
+#ifdef SPECIAL_CCODES
+#error fix for private CCODES handling
+#else
+ r = talloc();
+ *r = *p;
+ andorbr(r, -1, lbl = getlab());
+ q = tempnode(0, p->n_type, p->n_df, p->n_sue);
+ tval = q->n_lval;
+ r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
+ ecode(buildtree(ASSIGN, q, bcon(1)));
+ branch(lbl2 = getlab());
+ plabel( lbl);
+ ecode(buildtree(ASSIGN, r, bcon(0)));
+ plabel( lbl2);
+ r = tempnode(tval, p->n_type, p->n_df, p->n_sue);
+ *p = *r;
+ nfree(r);
+#endif
+ break;
+ case CBRANCH:
+ andorbr(p->n_left, p->n_right->n_lval, -1);
+ nfree(p->n_right);
+ p->n_op = ICON; p->n_type = VOID;
+ break;
+ case COMOP:
+ rmcops(p->n_left);
+ ecode(p->n_left);
+ /* Now when left tree is dealt with, rm COMOP */
+ q = p->n_right;
+ *p = *p->n_right;
+ nfree(q);
+ goto again;
+
+ default:
+ if (ty == LTYPE)
+ return;
+ rmcops(p->n_left);
+ if (ty == BITYPE)
+ rmcops(p->n_right);
+ }
+}
+
+/*
+ * Return 1 if an assignment is found.
+ */
+static int
+has_se(NODE *p)
+{
+ if (cdope(p->n_op) & ASGFLG)
+ return 1;
+ if (coptype(p->n_op) == LTYPE)
+ return 0;
+ if (has_se(p->n_left))
+ return 1;
+ if (coptype(p->n_op) == BITYPE)
+ return has_se(p->n_right);
+ return 0;
+}
+
+/*
+ * Find and convert asgop's to separate statements.
+ * Be careful about side effects.
+ * assign tells whether ASSIGN should be considered giving
+ * side effects or not.
+ */
+static NODE *
+delasgop(NODE *p)
+{
+ NODE *q, *r;
+ int tval;
+
+ if (p->n_op == INCR || p->n_op == DECR) {
+ /*
+ * Rewrite x++ to (x += 1) -1; and deal with it further down.
+ * Pass2 will remove -1 if unneccessary.
+ */
+ q = ccopy(p);
+ tfree(p->n_left);
+ q->n_op = (p->n_op==INCR)?PLUSEQ:MINUSEQ;
+ p->n_op = (p->n_op==INCR)?MINUS:PLUS;
+ p->n_left = delasgop(q);
+
+ } else if ((cdope(p->n_op)&ASGOPFLG) &&
+ p->n_op != RETURN && p->n_op != CAST) {
+ NODE *l = p->n_left;
+ NODE *ll = l->n_left;
+
+ if (has_se(l)) {
+ q = tempnode(0, ll->n_type, ll->n_df, ll->n_sue);
+ tval = q->n_lval;
+ r = tempnode(tval, ll->n_type, ll->n_df,ll->n_sue);
+ l->n_left = q;
+ /* Now the left side of node p has no side effects. */
+ /* side effects on the right side must be obeyed */
+ p = delasgop(p);
+
+ r = buildtree(ASSIGN, r, ll);
+ r = delasgop(r);
+ ecode(r);
+ } else {
+#if 0 /* Cannot call buildtree() here, it would invoke double add shifts */
+ p->n_right = buildtree(UNASG p->n_op, ccopy(l),
+ p->n_right);
+#else
+ p->n_right = block(UNASG p->n_op, ccopy(l),
+ p->n_right, p->n_type, p->n_df, p->n_sue);
+#endif
+ p->n_op = ASSIGN;
+ p->n_right = delasgop(p->n_right);
+ p->n_right = clocal(p->n_right);
+ }
+
+ } else {
+ if (coptype(p->n_op) == LTYPE)
+ return p;
+ p->n_left = delasgop(p->n_left);
+ if (coptype(p->n_op) == BITYPE)
+ p->n_right = delasgop(p->n_right);
+ }
+ return p;
+}
+
+int edebug = 0;
+void
+ecomp(NODE *p)
+{
+
+#ifdef PCC_DEBUG
+ if (edebug)
+ fwalk(p, eprint, 0);
+#endif
+ if (!reached) {
+ werror("statement not reached");
+ reached = 1;
+ }
+ p = optim(p);
+ rmcops(p);
+ p = delasgop(p);
+ setloc1(PROG);
+ if (p->n_op == ICON && p->n_type == VOID)
+ tfree(p);
+ else
+ ecode(p);
+}
+
+#if defined(MULTIPASS)
+void
+p2tree(NODE *p)
+{
+ struct symtab *q;
+ int ty;
+
+# ifdef MYP2TREE
+ MYP2TREE(p); /* local action can be taken here; then return... */
+# endif
+
+ ty = coptype(p->n_op);
+
+ printf("%d\t", p->n_op);
+
+ if (ty == LTYPE) {
+ printf(CONFMT, p->n_lval);
+ printf("\t");
+ }
+ if (ty != BITYPE) {
+ if (p->n_op == NAME || p->n_op == ICON)
+ printf("0\t");
+ else
+ printf("%d\t", p->n_rval);
+ }
+
+ printf("%o\t", p->n_type);
+
+ /* handle special cases */
+
+ switch (p->n_op) {
+
+ case NAME:
+ case ICON:
+ /* print external name */
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+ q->sclass == ILABEL) {
+ printf(LABFMT, q->soffset);
+ } else
+ printf("%s\n", exname(q->sname));
+ } else
+ printf("\n");
+ break;
+
+ case STARG:
+ case STASG:
+ case STCALL:
+ case USTCALL:
+ /* print out size */
+ /* use lhs size, in order to avoid hassles
+ * with the structure `.' operator
+ */
+
+ /* note: p->left not a field... */
+ printf(CONFMT, (CONSZ)tsize(STRTY, p->n_left->n_df,
+ p->n_left->n_sue));
+ printf("\t%d\t\n", talign(STRTY, p->n_left->n_sue));
+ break;
+
+ default:
+ printf( "\n" );
+ }
+
+ if (ty != LTYPE)
+ p2tree(p->n_left);
+ if (ty == BITYPE)
+ p2tree(p->n_right);
+}
+#else
+void
+p2tree(NODE *p)
+{
+ struct symtab *q;
+ int ty;
+
+# ifdef MYP2TREE
+ MYP2TREE(p); /* local action can be taken here; then return... */
+# endif
+
+ ty = coptype(p->n_op);
+
+ switch( p->n_op ){
+
+ case NAME:
+ case ICON:
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+#ifdef GCC_COMPAT
+ q->sflags == SLBLNAME ||
+#endif
+ q->sclass == ILABEL) {
+ char *cp = (isinlining ?
+ permalloc(32) : tmpalloc(32));
+ int n = q->soffset;
+ if (n < 0)
+ n = -n;
+ snprintf(cp, 32, LABFMT, n);
+ p->n_name = cp;
+ } else {
+#ifdef GCC_COMPAT
+ p->n_name = gcc_findname(q);
+#else
+ p->n_name = exname(q->sname);
+#endif
+ }
+ } else
+ p->n_name = "";
+ break;
+
+ case STASG:
+ /* STASG used for stack array init */
+ if (ISARY(p->n_type)) {
+ int size1 = tsize(p->n_type, p->n_left->n_df,
+ p->n_left->n_sue)/SZCHAR;
+ p->n_stsize = tsize(p->n_type, p->n_right->n_df,
+ p->n_right->n_sue)/SZCHAR;
+ if (size1 < p->n_stsize)
+ p->n_stsize = size1;
+ p->n_stalign = talign(p->n_type,
+ p->n_left->n_sue)/SZCHAR;
+ break;
+ }
+ /* FALLTHROUGH */
+ case STARG:
+ case STCALL:
+ case USTCALL:
+ /* set up size parameters */
+ p->n_stsize = (tsize(STRTY, p->n_left->n_df,
+ p->n_left->n_sue)+SZCHAR-1)/SZCHAR;
+ p->n_stalign = talign(STRTY,p->n_left->n_sue)/SZCHAR;
+ break;
+
+ default:
+ p->n_name = "";
+ }
+
+ if( ty != LTYPE ) p2tree( p->n_left );
+ if( ty == BITYPE ) p2tree( p->n_right );
+ }
+
+#endif
+
+/*
+ * Change void data types into char.
+ */
+static void
+delvoid(NODE *p)
+{
+ /* Convert "PTR undef" (void *) to "PTR uchar" */
+ if (BTYPE(p->n_type) == VOID)
+ p->n_type = (p->n_type & ~BTMASK) | UCHAR;
+ if (BTYPE(p->n_type) == BOOL) {
+ if (p->n_op == SCONV && p->n_type == BOOL) {
+ /* create a jump and a set */
+ NODE *q, *r, *s;
+ int l, val;
+
+ q = talloc();
+ *q = *p;
+ q->n_type = BOOL_TYPE;
+ r = tempnode(0, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
+ val = r->n_lval;
+ s = tempnode(val, BOOL_TYPE, NULL, MKSUE(BOOL_TYPE));
+ *p = *s;
+ q = buildtree(ASSIGN, r, q);
+ cbranch(buildtree(EQ, q, bcon(0)), bcon(l = getlab()));
+ ecode(buildtree(ASSIGN, s, bcon(1)));
+ plabel(l);
+ } else
+ p->n_type = (p->n_type & ~BTMASK) | BOOL_TYPE;
+ }
+
+}
+
+void
+ecode(NODE *p)
+{
+ /* walk the tree and write out the nodes.. */
+
+ if (nerrors)
+ return;
+
+ p = optim(p);
+ p = delasgop(p);
+ walkf(p, prtdcon);
+ walkf(p, delvoid);
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("Fulltree:\n");
+ fwalk(p, eprint, 0);
+ }
+#endif
+ p2tree(p);
+#if !defined(MULTIPASS)
+ send_passt(IP_NODE, p);
+#endif
+}
+
+/*
+ * Send something further on to the next pass.
+ */
+void
+send_passt(int type, ...)
+{
+ struct interpass *ip;
+ struct interpass_prolog *ipp;
+ extern int crslab;
+ va_list ap;
+ int sz;
+
+ va_start(ap, type);
+ if (type == IP_PROLOG || type == IP_EPILOG)
+ sz = sizeof(struct interpass_prolog);
+ else
+ sz = sizeof(struct interpass);
+
+ ip = isinlining ? permalloc(sz) : tmpalloc(sz);
+ ip->type = type;
+ ip->lineno = lineno;
+ switch (type) {
+ case IP_NODE:
+ if (lastloc != PROG)
+ setloc1(PROG);
+ ip->ip_node = va_arg(ap, NODE *);
+ break;
+ case IP_EPILOG:
+ case IP_PROLOG:
+ setloc1(PROG);
+ ipp = (struct interpass_prolog *)ip;
+ ipp->ipp_regs = va_arg(ap, int);
+ ipp->ipp_autos = va_arg(ap, int);
+ ipp->ipp_name = va_arg(ap, char *);
+ ipp->ipp_type = va_arg(ap, TWORD);
+ ipp->ipp_vis = va_arg(ap, int);
+ ip->ip_lbl = va_arg(ap, int);
+ ipp->ip_tmpnum = tvaloff;
+ ipp->ip_lblnum = crslab;
+ if (type == IP_PROLOG)
+ ipp->ip_lblnum--;
+ break;
+ case IP_DEFLAB:
+ ip->ip_lbl = va_arg(ap, int);
+ break;
+ case IP_ASM:
+ if (blevel == 0) { /* outside function */
+ printf("\t%s\n", va_arg(ap, char *));
+ va_end(ap);
+ lastloc = -1;
+ return;
+ }
+ ip->ip_asm = va_arg(ap, char *);
+ break;
+ default:
+ cerror("bad send_passt type %d", type);
+ }
+ va_end(ap);
+ if (isinlining)
+ inline_addarg(ip);
+ else
+ pass2_compile(ip);
+ if (type == IP_EPILOG)
+ lastloc = PROG;
+}
+
+char *
+copst(int op)
+{
+ if (op <= MAXOP)
+ return opst[op];
+#define SNAM(x,y) case x: return #y;
+ switch (op) {
+ SNAM(QUALIFIER,QUALIFIER)
+ SNAM(CLASS,CLASS)
+ SNAM(RB,])
+ SNAM(DOT,.)
+ SNAM(ELLIPSIS,...)
+ SNAM(LB,[)
+ SNAM(TYPE,TYPE)
+ SNAM(COMOP,COMOP)
+ SNAM(QUEST,?)
+ SNAM(COLON,:)
+ SNAM(ANDAND,&&)
+ SNAM(OROR,||)
+ SNAM(NOT,!)
+ SNAM(CAST,CAST)
+ SNAM(PLUSEQ,+=)
+ SNAM(MINUSEQ,-=)
+ SNAM(MULEQ,*=)
+ SNAM(DIVEQ,/=)
+ SNAM(MODEQ,%=)
+ SNAM(ANDEQ,&=)
+ SNAM(OREQ,|=)
+ SNAM(EREQ,^=)
+ SNAM(LSEQ,<<=)
+ SNAM(RSEQ,>>=)
+ SNAM(INCR,++)
+ SNAM(DECR,--)
+ default:
+ cerror("bad copst %d", op);
+ }
+ return 0; /* XXX gcc */
+}
+
+int
+cdope(int op)
+{
+ if (op <= MAXOP)
+ return dope[op];
+ switch (op) {
+ case QUALIFIER:
+ case CLASS:
+ case RB:
+ case DOT:
+ case ELLIPSIS:
+ case TYPE:
+ return LTYPE;
+ case COMOP:
+ case QUEST:
+ case COLON:
+ case LB:
+ return BITYPE;
+ case ANDAND:
+ case OROR:
+ return BITYPE|LOGFLG;
+ case NOT:
+ return UTYPE|LOGFLG;
+ case CAST:
+ return BITYPE|ASGFLG|ASGOPFLG;
+ case PLUSEQ:
+ return BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG;
+ case MINUSEQ:
+ return BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG;
+ case MULEQ:
+ return BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG;
+ case OREQ:
+ case EREQ:
+ case ANDEQ:
+ return BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG;
+ case DIVEQ:
+ return BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG;
+ case MODEQ:
+ return BITYPE|DIVFLG|ASGFLG|ASGOPFLG;
+ case LSEQ:
+ case RSEQ:
+ return BITYPE|SHFFLG|ASGFLG|ASGOPFLG;
+ case INCR:
+ case DECR:
+ return BITYPE|ASGFLG;
+ }
+ return 0; /* XXX gcc */
+}
+
+/*
+ * make a fresh copy of p
+ */
+NODE *
+ccopy(NODE *p)
+{
+ NODE *q;
+
+ q = talloc();
+ *q = *p;
+
+ switch (coptype(q->n_op)) {
+ case BITYPE:
+ q->n_right = ccopy(p->n_right);
+ case UTYPE:
+ q->n_left = ccopy(p->n_left);
+ }
+
+ return(q);
+}
+
+/*
+ * set PROG-seg label.
+ */
+void
+plabel(int label)
+{
+ setloc1(PROG);
+ reached = 1; /* Will this always be correct? */
+ send_passt(IP_DEFLAB, label);
+}
--- /dev/null
+++ usr.bin/pcc/ccom/stabs.c
@@ -0,0 +1,374 @@
+/* $Id: stabs.c,v 1.15 2007/09/15 07:37:44 ragge Exp $ */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson (ragge at 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.
+ */
+
+/*
+ * Simple implementation of the "stabs" debugging format.
+ * Not complete but at least makes it possible to set breakpoints,
+ * examine simple variables and do stack traces.
+ * Based on the stabs documentation that follows gdb.
+ */
+
+#include "pass1.h"
+
+#ifdef STABS
+
+#include <sys/types.h>
+#include <stab.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define STABHASH 256
+#define INTNUM 1 /* internal number of type "int" */
+#define BIT2BYTE(x) ((x)/SZCHAR)
+
+#ifndef STABLBL
+#error macdefs.h must define STABLBL
+#endif
+
+/*
+ * Local type mapping
+ * Types are defined as a typeword, a dimension pointer (in the case
+ * of arrays) and struct/union/enum declarations.
+ * Function prototypes are ignored.
+ */
+static struct stabtype {
+ struct stabtype *next; /* linked list */
+ TWORD type; /* pcc type number */
+ union dimfun *df; /* dimension of arrays */
+ struct suedef *sue; /* struct/union/enum declarations */
+ int num; /* local type number */
+} *stabhash[STABHASH];
+static int ntypes;
+static char *curfun;
+static int stablbl = 10;
+
+void ptype(char *name, int num, int inhnum, long long min, long long max);
+struct stabtype *addtype(TWORD, union dimfun *, struct suedef *);
+struct stabtype *findtype(TWORD t, union dimfun *df, struct suedef *sue);
+void printtype(struct symtab *s, char *str, int len);
+void cprint(int p2, char *fmt, ...);
+
+#define MAXPSTR 100
+
+extern int isinlining;
+#define savestabs isinlining
+
+/*
+ * Output type definitions for the stab debugging format.
+ * Note that "int" is always internal number 1.
+ */
+void
+stabs_init()
+{
+ struct stabtype *st;
+
+#define ADDTYPE(y) addtype(y, NULL, MKSUE(y))
+
+ ptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT);
+
+ st = ADDTYPE(CHAR);
+ ptype("char", st->num, st->num, 0, MAX_CHAR);
+ ptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT);
+ ptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG);
+ ptype("long long", ADDTYPE(LONGLONG)->num, INTNUM,
+ MIN_LONGLONG, MAX_LONGLONG);
+ ptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR);
+ ptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT);
+ ptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED);
+ ptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG);
+ ptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM,
+ 0, MAX_ULONGLONG);
+
+ ptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0);
+ ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0);
+ ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0);
+ st = ADDTYPE(VOID);
+ cprint(savestabs, ".stabs \"void:t%d=r%d\",%d,0,0,0\n",
+ st->num, st->num, N_LSYM);
+
+}
+
+/*
+ * Print a type in stabs format
+ */
+void
+ptype(char *name, int num, int inhnum, long long min, long long max)
+{
+ cprint(savestabs, ".stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0",
+ name, num, inhnum, min, max, N_LSYM);
+}
+
+/*
+ * Add a new local type to the hash table.
+ * The search key is the (type, df, sue) triple.
+ */
+struct stabtype *
+addtype(TWORD t, union dimfun *df, struct suedef *sue)
+{
+ struct stabtype *st;
+
+ st = permalloc(sizeof(struct stabtype));
+ st->type = t;
+ st->df = df;
+ st->sue = sue;
+ st->num = ++ntypes;
+ st->next = stabhash[t & (STABHASH-1)];
+ stabhash[t & (STABHASH-1)] = st;
+ return st;
+}
+
+/*
+ * Search for a given type and return a type pointer (or NULL).
+ */
+struct stabtype *
+findtype(TWORD t, union dimfun *df, struct suedef *sue)
+{
+ struct stabtype *st;
+ union dimfun *dw, *dx;
+ TWORD tw;
+
+ st = stabhash[t & (STABHASH-1)];
+ for (; st; st = st->next) {
+ if (t != st->type || sue != st->sue)
+ continue;
+ /* Ok, type and sue matches, check dimensions */
+ if (st->df == NULL)
+ return st; /* no arrays, got match */
+ dw = st->df;
+ dx = df;
+ tw = t;
+ for (; tw > BTMASK; tw = DECREF(tw)) {
+ if (ISARY(tw)) {
+ if (dw->ddim == dx->ddim)
+ dw++, dx++;
+ else
+ break;
+ }
+ }
+ if (tw <= BTMASK)
+ return st;
+ }
+ return NULL;
+}
+
+/*
+ * Print current line number.
+ */
+void
+stabs_line(int line)
+{
+ cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s", N_SLINE, line, stablbl, curfun);
+ cprint(1, STABLBL ":", stablbl++);
+}
+
+/*
+ * Start of block.
+ */
+void
+stabs_lbrac(int blklvl)
+{
+ cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s",
+ N_LBRAC, blklvl, stablbl, curfun);
+ cprint(1, STABLBL ":", stablbl++);
+}
+
+/*
+ * End of block.
+ */
+void
+stabs_rbrac(int blklvl)
+{
+ cprint(savestabs, ".stabn %d,0,%d," STABLBL "-%s\n",
+ N_RBRAC, blklvl, stablbl, curfun);
+ cprint(1, STABLBL ":", stablbl++);
+}
+
+/*
+ * Print current file and set mark.
+ */
+void
+stabs_file(char *fname)
+{
+ static char *mainfile;
+
+ if (mainfile == NULL)
+ mainfile = fname; /* first call */
+ cprint(savestabs, ".stabs \"%s\",%d,0,0," STABLBL,
+ fname, fname == mainfile ? N_SO : N_SOL, stablbl);
+ cprint(savestabs, STABLBL ":", stablbl++);
+}
+
+/*
+ * Print beginning of function.
+ */
+void
+stabs_func(struct symtab *s)
+{
+ char str[MAXPSTR];
+
+ curfun = s->sname;
+#ifdef GCC_COMPAT
+ curfun = gcc_findname(cftnsp);
+#endif
+ printtype(s, str, sizeof(str));
+ cprint(savestabs, ".stabs \"%s:%c%s\",%d,0,%d,%s",
+ curfun, s->sclass == STATIC ? 'f' : 'F', str,
+ N_FUN, BIT2BYTE(s->ssue->suesize), exname(curfun));
+}
+
+/*
+ * Print a (complex) type.
+ * Will also create subtypes.
+ * Printed string is like "20=*21=*1".
+ */
+void
+printtype(struct symtab *s, char *ostr, int len)
+{
+ struct stabtype *st;
+ union dimfun *df = s->sdf;
+ struct suedef *sue = s->ssue;
+ TWORD t = s->stype;
+ int op = 0;
+
+ /* Print out not-yet-found types */
+ if (ISFTN(t))
+ t = DECREF(t);
+ st = findtype(t, df, sue);
+ while (st == NULL && t > BTMASK) {
+ st = addtype(t, df, sue);
+ op+=snprintf(ostr+op, len - op, "%d=", st->num);
+ if (ISFTN(t))
+ ostr[op++] = 'f';
+ else if (ISPTR(t))
+ ostr[op++] = '*';
+ else if (ISARY(t)) {
+ op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1);
+ } else
+ cerror("printtype: notype");
+ if (ISARY(t))
+ df++;
+ t = DECREF(t);
+ st = findtype(t, df, sue);
+ if (op > MAXPSTR-10)
+ cerror("printtype: too difficult expression");
+ }
+ /* print out basic type. may have to be entered in case of sue */
+ snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num);
+ /* snprintf here null-terminated the string */
+}
+
+void
+stabs_newsym(struct symtab *s)
+{
+ char *sname;
+ char ostr[MAXPSTR];
+
+ if (ISFTN(s->stype))
+ return; /* functions are handled separate */
+
+ if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS ||
+ s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE ||
+ s->sclass == TYPEDEF || (s->sclass & FIELD))
+ return; /* XXX - fix structs */
+
+ sname = s->sname;
+#ifdef GCC_COMPAT
+ sname = gcc_findname(s);
+#endif
+
+ printtype(s, ostr, sizeof(ostr));
+ switch (s->sclass) {
+ case PARAM:
+ cprint(savestabs, ".stabs \"%s:p%s\",%d,0,%d,%d", sname, ostr,
+ N_PSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
+ break;
+
+ case AUTO:
+ cprint(savestabs, ".stabs \"%s:%s\",%d,0,%d,%d", sname, ostr,
+ N_LSYM, BIT2BYTE(s->ssue->suesize), BIT2BYTE(s->soffset));
+ break;
+
+ case STATIC:
+ if (blevel)
+ cprint(savestabs, ".stabs \"%s:V%s\",%d,0,%d," LABFMT, sname, ostr,
+ N_LCSYM, BIT2BYTE(s->ssue->suesize), s->soffset);
+ else
+ cprint(savestabs, ".stabs \"%s:S%s\",%d,0,%d,%s", sname, ostr,
+ N_LCSYM, BIT2BYTE(s->ssue->suesize), exname(sname));
+ break;
+
+ case EXTERN:
+ case EXTDEF:
+ cprint(savestabs, ".stabs \"%s:G%s\",%d,0,%d,0", sname, ostr,
+ N_GSYM, BIT2BYTE(s->ssue->suesize));
+ break;
+
+ case REGISTER:
+ cprint(savestabs, ".stabs \"%s:r%s\",%d,0,%d,%d", sname, ostr,
+ N_RSYM, 1, s->soffset);
+ break;
+
+ default:
+ cerror("fix stab_newsym; class %d", s->sclass);
+ }
+}
+
+void
+stabs_chgsym(struct symtab *s)
+{
+}
+
+/*
+ * define a struct.
+ */
+void
+stabs_struct(struct symtab *p, struct suedef *sue)
+{
+}
+
+void
+cprint(int p2, char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+
+ va_start(ap, fmt);
+ if (p2) {
+ str = tmpvsprintf(fmt, ap);
+ str = newstring(str, strlen(str)); /* XXX - for inlines */
+ send_passt(IP_ASM, str);
+ } else {
+ putchar('\t');
+ vprintf(fmt, ap);
+ putchar('\n');
+ }
+ va_end(ap);
+}
+
+#endif
--- /dev/null
+++ usr.bin/pcc/ccom/symtabs.c
@@ -0,0 +1,356 @@
+/* $Id: symtabs.c,v 1.14 2006/06/16 09:30:32 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+#include "pass1.h"
+
+/*
+ * These definitions are used in the patricia tree that stores
+ * the strings.
+ */
+#define LEFT_IS_LEAF 0x80000000
+#define RIGHT_IS_LEAF 0x40000000
+#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
+#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
+#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
+#define CHECKBITS 8
+
+struct tree {
+ int bitno;
+ struct tree *lr[2];
+};
+
+static struct tree *firstname;
+int nametabs, namestrlen;
+static struct tree *firststr;
+int strtabs, strstrlen;
+static char *symtab_add(char *key, struct tree **, int *, int *);
+
+#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
+#define getree() permalloc(sizeof(struct tree))
+
+char *
+addname(char *key)
+{
+ return symtab_add(key, &firstname, &nametabs, &namestrlen);
+}
+
+char *
+addstring(char *key)
+{
+ return symtab_add(key, &firststr, &strtabs, &strstrlen);
+}
+
+/*
+ * Add a name to the name stack (if its non-existing),
+ * return its address.
+ * This is a simple patricia implementation.
+ */
+char *
+symtab_add(char *key, struct tree **first, int *tabs, int *stlen)
+{
+ struct tree *w, *new, *last;
+ int cix, bit, fbit, svbit, ix, bitno, len;
+ char *m, *k, *sm;
+
+ /* Count full string length */
+ for (k = key, len = 0; *k; k++, len++)
+ ;
+
+ switch (*tabs) {
+ case 0:
+ *first = (struct tree *)newstring(key, len);
+ *stlen += (len + 1);
+ (*tabs)++;
+ return (char *)*first;
+
+ case 1:
+ m = (char *)*first;
+ svbit = 0; /* XXX why? */
+ break;
+
+ default:
+ w = *first;
+ bitno = len * CHECKBITS;
+ for (;;) {
+ bit = BITNO(w->bitno);
+ fbit = bit > bitno ? 0 : P_BIT(key, bit);
+ svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
+ IS_LEFT_LEAF(w->bitno);
+ w = w->lr[fbit];
+ if (svbit) {
+ m = (char *)w;
+ break;
+ }
+ }
+ }
+
+ sm = m;
+ k = key;
+
+ /* Check for correct string and return */
+ for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS)
+ ;
+ if (*m == 0 && *k == 0)
+ return sm;
+
+ ix = *m ^ *k;
+ while ((ix & 1) == 0)
+ ix >>= 1, cix++;
+
+ /* Create new node */
+ new = getree();
+ bit = P_BIT(key, cix);
+ new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ new->lr[bit] = (struct tree *)newstring(key, len);
+ *stlen += (len + 1);
+
+ if ((*tabs)++ == 1) {
+ new->lr[!bit] = *first;
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ *first = new;
+ return (char *)new->lr[bit];
+ }
+
+
+ w = *first;
+ last = NULL;
+ for (;;) {
+ fbit = w->bitno;
+ bitno = BITNO(w->bitno);
+ if (bitno == cix)
+ cerror("bitno == cix");
+ if (bitno > cix)
+ break;
+ svbit = P_BIT(key, bitno);
+ last = w;
+ w = w->lr[svbit];
+ if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
+ break;
+ }
+
+ new->lr[!bit] = w;
+ if (last == NULL) {
+ *first = new;
+ } else {
+ last->lr[svbit] = new;
+ last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ }
+ if (bitno < cix)
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ return (char *)new->lr[bit];
+}
+
+static struct tree *sympole[NSTYPES];
+static struct symtab *tmpsyms[NSTYPES];
+int numsyms[NSTYPES];
+
+/*
+ * Inserts a symbol into the symbol tree.
+ * Returns a struct symtab.
+ */
+struct symtab *
+lookup(char *key, int ttype)
+{
+ struct symtab *sym;
+ struct tree *w, *new, *last;
+ int cix, bit, fbit, svbit, ix, bitno, match;
+ int type, uselvl;
+
+ long code = (long)key;
+ type = ttype & SMASK;
+ uselvl = (blevel > 0 && type != SSTRING);
+
+ /*
+ * The local symbols are kept in a simple linked list.
+ * Check this list first.
+ */
+ if (blevel > 0)
+ for (sym = tmpsyms[type]; sym; sym = sym->snext)
+ if (sym->sname == key)
+ return sym;
+
+ switch (numsyms[type]) {
+ case 0:
+ if (ttype & SNOCREAT)
+ return NULL;
+ if (uselvl) {
+ sym = getsymtab(key, ttype|STEMP);
+ sym->snext = tmpsyms[type];
+ tmpsyms[type] = sym;
+ return sym;
+ }
+ sympole[type] = (struct tree *)getsymtab(key, ttype);
+ numsyms[type]++;
+ return (struct symtab *)sympole[type];
+
+ case 1:
+ w = (struct tree *)sympole[type];
+ svbit = 0; /* XXX why? */
+ break;
+
+ default:
+ w = sympole[type];
+ for (;;) {
+ bit = BITNO(w->bitno);
+ fbit = (code >> bit) & 1;
+ svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
+ IS_LEFT_LEAF(w->bitno);
+ w = w->lr[fbit];
+ if (svbit)
+ break;
+ }
+ }
+
+ sym = (struct symtab *)w;
+ match = (long)sym->sname;
+
+ ix = code ^ match;
+ if (ix == 0)
+ return sym;
+ else if (ttype & SNOCREAT)
+ return NULL;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf(" adding %s as %s at level %d\n",
+ key, uselvl ? "temp" : "perm", blevel);
+#endif
+
+ /*
+ * Insert into the linked list, if feasible.
+ */
+ if (uselvl) {
+ sym = getsymtab(key, ttype|STEMP);
+ sym->snext = tmpsyms[type];
+ tmpsyms[type] = sym;
+ return sym;
+ }
+
+ /*
+ * Need a new node. If type is SNORMAL and inside a function
+ * the node must be allocated as permanent anyway.
+ * This could be optimized by adding a remove routine, but it
+ * may be more trouble than it is worth.
+ */
+ if (ttype == (STEMP|SNORMAL))
+ ttype = SNORMAL;
+
+ for (cix = 0; (ix & 1) == 0; ix >>= 1, cix++)
+ ;
+
+ new = ttype & STEMP ? tmpalloc(sizeof(struct tree)) :
+ permalloc(sizeof(struct tree));
+ bit = (code >> cix) & 1;
+ new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ new->lr[bit] = (struct tree *)getsymtab(key, ttype);
+ if (numsyms[type]++ == 1) {
+ new->lr[!bit] = sympole[type];
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ sympole[type] = new;
+ return (struct symtab *)new->lr[bit];
+ }
+
+
+ w = sympole[type];
+ last = NULL;
+ for (;;) {
+ fbit = w->bitno;
+ bitno = BITNO(w->bitno);
+ if (bitno == cix)
+ cerror("bitno == cix");
+ if (bitno > cix)
+ break;
+ svbit = (code >> bitno) & 1;
+ last = w;
+ w = w->lr[svbit];
+ if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
+ break;
+ }
+
+ new->lr[!bit] = w;
+ if (last == NULL) {
+ sympole[type] = new;
+ } else {
+ last->lr[svbit] = new;
+ last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ }
+ if (bitno < cix)
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ return (struct symtab *)new->lr[bit];
+}
+
+void
+symclear(int level)
+{
+ struct symtab *s;
+ int i;
+
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf("symclear(%d)\n", level);
+#endif
+ if (level < 1) {
+ for (i = 0; i < NSTYPES; i++) {
+ s = tmpsyms[i];
+ tmpsyms[i] = 0;
+ if (i != SLBLNAME)
+ continue;
+ while (s != NULL) {
+ if (s->soffset < 0)
+ uerror("label '%s' undefined",s->sname);
+ s = s->snext;
+ }
+ }
+ } else {
+ for (i = 0; i < NSTYPES; i++) {
+ if (i == SLBLNAME)
+ continue; /* function scope */
+ while (tmpsyms[i] != NULL &&
+ tmpsyms[i]->slevel > level) {
+ tmpsyms[i] = tmpsyms[i]->snext;
+ }
+ }
+ }
+}
+
+struct symtab *
+hide(struct symtab *sym)
+{
+ struct symtab *new;
+
+ new = getsymtab(sym->sname, SNORMAL|STEMP);
+ new->snext = tmpsyms[SNORMAL];
+ tmpsyms[SNORMAL] = new;
+#ifdef PCC_DEBUG
+ if (ddebug)
+ printf("\t%s hidden at level %d (%p -> %p)\n",
+ sym->sname, blevel, sym, new);
+#endif
+ return new;
+}
--- /dev/null
+++ usr.bin/pcc/ccom/optim.c
@@ -0,0 +1,355 @@
+/* $Id: optim.c,v 1.28 2006/07/11 07:54:29 ragge Exp $ */
+/*
+ * 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 conditionsand 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 "pass1.h"
+
+# define SWAP(p,q) {sp=p; p=q; q=sp;}
+# define RCON(p) (p->n_right->n_op==ICON)
+# define RO(p) p->n_right->n_op
+# define RV(p) p->n_right->n_lval
+# define LCON(p) (p->n_left->n_op==ICON)
+# define LO(p) p->n_left->n_op
+# define LV(p) p->n_left->n_lval
+
+static int nncon(NODE *);
+
+int oflag = 0;
+
+/* remove left node */
+static NODE *
+zapleft(NODE *p)
+{
+ NODE *q;
+
+ q = p->n_left;
+ nfree(p->n_right);
+ nfree(p);
+ return q;
+}
+
+/*
+ * fortran function arguments
+ */
+static NODE *
+fortarg(NODE *p)
+{
+ if( p->n_op == CM ){
+ p->n_left = fortarg( p->n_left );
+ p->n_right = fortarg( p->n_right );
+ return(p);
+ }
+
+ while( ISPTR(p->n_type) ){
+ p = buildtree( UMUL, p, NIL );
+ }
+ return( optim(p) );
+}
+
+ /* mapping relationals when the sides are reversed */
+short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
+
+/*
+ * local optimizations, most of which are probably
+ * machine independent
+ */
+NODE *
+optim(NODE *p)
+{
+ int o, ty;
+ NODE *sp, *q;
+ int i;
+ TWORD t;
+
+ if( (t=BTYPE(p->n_type))==ENUMTY || t==MOETY ) econvert(p);
+ if( oflag ) return(p);
+
+ ty = coptype(p->n_op);
+ if( ty == LTYPE ) return(p);
+
+ if( ty == BITYPE ) p->n_right = optim(p->n_right);
+ p->n_left = optim(p->n_left);
+
+ /* collect constants */
+again: o = p->n_op;
+ switch(o){
+
+ case SCONV:
+ case PCONV:
+ return( clocal(p) );
+
+ case FORTCALL:
+ p->n_right = fortarg( p->n_right );
+ break;
+
+ case ADDROF:
+ if (LO(p) == TEMP)
+ return p;
+ if( LO(p) != NAME ) cerror( "& error" );
+
+ if( !andable(p->n_left) ) return(p);
+
+ LO(p) = ICON;
+
+ setuleft:
+ /* paint over the type of the left hand side with the type of the top */
+ p->n_left->n_type = p->n_type;
+ p->n_left->n_df = p->n_df;
+ p->n_left->n_sue = p->n_sue;
+ q = p->n_left;
+ nfree(p);
+ return q;
+
+ case UMUL:
+ if( LO(p) != ICON ) break;
+ LO(p) = NAME;
+ goto setuleft;
+
+ case RS:
+ if (LO(p) == RS && RCON(p->n_left) && RCON(p)) {
+ /* two right-shift by constants */
+ RV(p) += RV(p->n_left);
+ p->n_left = zapleft(p->n_left);
+ }
+#if 0
+ else if (LO(p) == LS && RCON(p->n_left) && RCON(p)) {
+ RV(p) -= RV(p->n_left);
+ if (RV(p) < 0)
+ o = p->n_op = LS, RV(p) = -RV(p);
+ p->n_left = zapleft(p->n_left);
+ }
+#endif
+ if (RO(p) == ICON) {
+ if (RV(p) < 0) {
+ RV(p) = -RV(p);
+ p->n_op = LS;
+ goto again;
+ }
+#ifdef notyet /* must check for side effects, --a >> 32; */
+ if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue) &&
+ ISUNSIGNED(p->n_type)) { /* ignore signed shifts */
+ /* too many shifts */
+ tfree(p->n_left);
+ nfree(p->n_right);
+ p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL;
+ } else
+#endif
+ /* avoid larger shifts than type size */
+ if (RV(p) >= p->n_sue->suesize) {
+ RV(p) = RV(p) % p->n_sue->suesize;
+ werror("shift larger than type");
+ }
+ if (RV(p) == 0)
+ p = zapleft(p);
+ }
+ break;
+
+ case LS:
+ if (LO(p) == LS && RCON(p->n_left) && RCON(p)) {
+ /* two left-shift by constants */
+ RV(p) += RV(p->n_left);
+ p->n_left = zapleft(p->n_left);
+ }
+#if 0
+ else if (LO(p) == RS && RCON(p->n_left) && RCON(p)) {
+ RV(p) -= RV(p->n_left);
+ p->n_left = zapleft(p->n_left);
+ }
+#endif
+ if (RO(p) == ICON) {
+ if (RV(p) < 0) {
+ RV(p) = -RV(p);
+ p->n_op = RS;
+ goto again;
+ }
+#ifdef notyet /* must check for side effects */
+ if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue)) {
+ /* too many shifts */
+ tfree(p->n_left);
+ nfree(p->n_right);
+ p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL;
+ } else
+#endif
+ /* avoid larger shifts than type size */
+ if (RV(p) >= p->n_sue->suesize) {
+ RV(p) = RV(p) % p->n_sue->suesize;
+ werror("shift larger than type");
+ }
+ if (RV(p) == 0)
+ p = zapleft(p);
+ }
+ break;
+
+ case MINUS:
+ if (LCON(p) && RCON(p) && p->n_left->n_sp == p->n_right->n_sp) {
+ /* link-time constants, but both are the same */
+ /* solve it now by forgetting the symbols */
+ p->n_left->n_sp = p->n_right->n_sp = NULL;
+ }
+ if( !nncon(p->n_right) ) break;
+ RV(p) = -RV(p);
+ o = p->n_op = PLUS;
+
+ case MUL:
+ case PLUS:
+ case AND:
+ case OR:
+ case ER:
+ /* commutative ops; for now, just collect constants */
+ /* someday, do it right */
+ if( nncon(p->n_left) || ( LCON(p) && !RCON(p) ) )
+ SWAP( p->n_left, p->n_right );
+ /* make ops tower to the left, not the right */
+ if( RO(p) == o ){
+ NODE *t1, *t2, *t3;
+ t1 = p->n_left;
+ sp = p->n_right;
+ t2 = sp->n_left;
+ t3 = sp->n_right;
+ /* now, put together again */
+ p->n_left = sp;
+ sp->n_left = t1;
+ sp->n_right = t2;
+ p->n_right = t3;
+ }
+ if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->n_left) &&
+ conval(p->n_right, MINUS, p->n_left->n_right)){
+ zapleft:
+
+ q = p->n_left->n_left;
+ nfree(p->n_left->n_right);
+ nfree(p->n_left);
+ p->n_left = q;
+ }
+ if( RCON(p) && LO(p)==o && RCON(p->n_left) &&
+ conval( p->n_right, o, p->n_left->n_right ) ){
+ goto zapleft;
+ }
+ else if( LCON(p) && RCON(p) && conval( p->n_left, o, p->n_right ) ){
+ zapright:
+ nfree(p->n_right);
+ q = makety(p->n_left, p->n_type, p->n_qual,
+ p->n_df, p->n_sue);
+ nfree(p);
+ return clocal(q);
+ }
+
+ /* change muls to shifts */
+
+ if( o == MUL && nncon(p->n_right) && (i=ispow2(RV(p)))>=0){
+ if( i == 0 ) { /* multiplication by 1 */
+ goto zapright;
+ }
+ o = p->n_op = LS;
+ p->n_right->n_type = INT;
+ p->n_right->n_df = NULL;
+ RV(p) = i;
+ }
+
+ /* change +'s of negative consts back to - */
+ if( o==PLUS && nncon(p->n_right) && RV(p)<0 ){
+ RV(p) = -RV(p);
+ o = p->n_op = MINUS;
+ }
+
+ /* remove ops with RHS 0 */
+ if ((o == PLUS || o == MINUS || o == OR || o == ER) &&
+ nncon(p->n_right) && RV(p) == 0) {
+ goto zapright;
+ }
+ break;
+
+ case DIV:
+ if( nncon( p->n_right ) && p->n_right->n_lval == 1 )
+ goto zapright;
+ if (LCON(p) && RCON(p) && conval(p->n_left, DIV, p->n_right))
+ goto zapright;
+ if (RCON(p) && ISUNSIGNED(p->n_type) && (i=ispow2(RV(p))) > 0) {
+ p->n_op = RS;
+ RV(p) = i;
+ q = p->n_right;
+ if(tsize(q->n_type, q->n_df, q->n_sue) > SZINT)
+ p->n_right = makety(q, INT, 0, 0, MKSUE(INT));
+
+ break;
+ }
+ break;
+
+ case MOD:
+ if (RCON(p) && ISUNSIGNED(p->n_type) && ispow2(RV(p)) > 0) {
+ p->n_op = AND;
+ RV(p) = RV(p) -1;
+ break;
+ }
+ break;
+
+ case EQ:
+ case NE:
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ case ULT:
+ case ULE:
+ case UGT:
+ case UGE:
+ if( !LCON(p) ) break;
+
+ /* exchange operands */
+
+ sp = p->n_left;
+ p->n_left = p->n_right;
+ p->n_right = sp;
+ p->n_op = revrel[p->n_op - EQ ];
+ break;
+
+ }
+
+ return(p);
+ }
+
+int
+ispow2(CONSZ c)
+{
+ int i;
+ if( c <= 0 || (c&(c-1)) ) return(-1);
+ for( i=0; c>1; ++i) c >>= 1;
+ return(i);
+}
+
+int
+nncon( p ) NODE *p; {
+ /* is p a constant without a name */
+ return( p->n_op == ICON && p->n_sp == NULL );
+ }
--- /dev/null
+++ usr.bin/pcc/ccom/Makefile
@@ -0,0 +1,5 @@
+# $MidnightBSD: src/usr.bin/pcc/ccom/Makefile,v 1.1 2008/05/14 04:25:57 laffer1 Exp $
+
+SUBDIR+= ${MACHINE_ARCH}
+
+.include <bsd.subdir.mk>
--- /dev/null
+++ usr.bin/pcc/cpp/scanner.l
@@ -0,0 +1,814 @@
+%{
+/* $Id: scanner.l,v 1.20 2007/09/25 20:41:07 ragge Exp $ */
+
+/*
+ * 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 "cpp.h"
+#include "y.tab.h"
+%}
+
+%{
+static long long cvtdig(int rad);
+static int charcon(void);
+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 linestmt(void);
+static void storepb(void);
+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 32768
+#define YY_INPUT(b,r,m) (r = yyinput(b, m))
+#define fprintf(x, ...) error(__VA_ARGS__)
+#define ECHO putstr((usch *)yytext)
+#undef fileno
+#define fileno(x) 0
+
+#if YY_FLEX_SUBMINOR_VERSION >= 31
+/* Hack to avoid unneccessary 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((usch *)yytext);
+%}
+
+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
+
+%%
+
+"\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>"==" { 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})* {
+ if (gotdef) {
+ yylval.val =
+ lookup((usch *)yytext, FIND) != 0;
+ gotdef = 0;
+ return IDENT;
+ }
+ yylval.val = 0;
+ return NUMBER;
+ }
+
+[1-9][0-9]* { if (slow && !YYSTATE) return IDENT; scale = 10; goto num; }
+
+0[xX]{H}+{IS}? { scale = 16;
+ num: if (YYSTATE)
+ yylval.val = cvtdig(scale);
+ PRTOUT(NUMBER);
+ }
+0{D}+{IS}? { scale = 8; goto num; }
+{D}+{IS}? { scale = 10; goto num; }
+L?'(\\.|[^\\'])+' { if (YYSTATE)
+ yylval.val = charcon();
+ PRTOUT(NUMBER);
+ }
+
+<IFR>. { return yytext[0]; }
+
+{D}+{E}{FS}? { PRTOUT(FPOINT); }
+{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); }
+{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); }
+
+^{WS}*#{WS}* { 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(); }
+<CONTR>"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; }
+
+
+
+"//".*$ { /* if (tflag) yyless(..) */
+ if (Cflag)
+ putstr((usch *)yytext);
+ else if (!flslvl)
+ putch(' ');
+ }
+"/*" { int c, wrn;
+ if (Cflag)
+ putstr((usch *)yytext);
+ wrn = 0;
+ more: while ((c = input()) && c != '*') {
+ if (c == '\n')
+ putch(c), ifiles->lineno++;
+ else if (c == 1) /* WARN */
+ wrn = 1;
+ else if (Cflag)
+ putch(c);
+ }
+ if (c == 0)
+ return 0;
+ if (Cflag)
+ putch(c);
+ if ((c = input()) && c != '/') {
+ if (Cflag)
+ putch('*');
+ unput(c);
+ goto more;
+ }
+ if (Cflag)
+ 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((usch *)yytext, FIND)) != 0) {
+ usch *op = stringbuf;
+ putstr(gotident(nl));
+ stringbuf = op;
+ } else
+ putstr((usch *)yytext);
+ xx: ;
+ }
+
+. { PRTOUT(yytext[0]); }
+
+%%
+
+usch *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 */
+ if ((c = inpch()) == '\n') {
+ ifiles->lineno++;
+ putch('\n');
+ goto again;
+ }
+ 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 on failure to open file.
+ */
+int
+pushfile(usch *file)
+{
+ extern struct initar *initar;
+ struct includ ibuf;
+ struct includ *old;
+ struct includ *ic;
+ int c, otrulvl;
+
+ ic = &ibuf;
+ old = ifiles;
+
+ slow = 0;
+ if (file != NULL) {
+ if ((ic->infil = open((char *)file, O_RDONLY)) < 0)
+ return -1;
+ ic->orgfn = ic->fname = file;
+ } else {
+ ic->infil = 0;
+ ic->orgfn = ic->fname = (usch *)"<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 = old;
+ close(ic->infil);
+ return 0;
+}
+
+/*
+ * Print current position to output file.
+ */
+void
+prtline()
+{
+ usch *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
+ 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, 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 some string numbers to long long.
+ * Do not care about UL trailers, should we?
+ */
+static long long
+cvtdig(int rad)
+{
+ long long rv = 0;
+ char *y = yytext;
+ int c;
+
+ c = *y++;
+ if (rad == 16)
+ y++;
+ while (isxdigit(c)) {
+ rv = rv * rad + dig2num(c);
+ c = *y++;
+ }
+ return rv;
+}
+
+static int
+charcon(void)
+{
+ usch *p = (usch *)yytext;
+ int val, c;
+
+ if (*p == 'L')
+ p++;
+ p++; /* 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(void)
+{
+ int t;
+
+ while ((t = yylex()) == WSPACE)
+ ;
+ if (t != '\n')
+ error("newline expected, got %d", t);
+}
+
+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();
+}
+
+static void
+ifdefstmt(void)
+{
+ if (flslvl) {
+ /* just ignore the rest of the line */
+ while (input() != '\n')
+ ;
+ unput('\n');
+ yylex();
+ flslvl++;
+ return;
+ }
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ error("bad ifdef");
+ slow = 0;
+ if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0)
+ trulvl++;
+ else
+ flslvl++;
+ chknl();
+}
+
+static void
+ifndefstmt(void)
+{
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ error("bad ifndef");
+ slow = 0;
+ if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0)
+ trulvl++;
+ else
+ flslvl++;
+ chknl();
+}
+
+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();
+}
+
+/*
+ * Note! Ugly!
+ * Walk over the string s and search for defined, and replace it with
+ * spaces and a 1 or 0.
+ */
+static void
+fixdefined(usch *s)
+{
+ usch *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)
+{
+ usch *opb = stringbuf;
+ int c;
+
+ while ((c = input()) != '\n')
+ 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 usch *
+svinp(void)
+{
+ int c;
+ usch *cp = stringbuf;
+
+ while ((c = input()) && c != '\n')
+ savch(c);
+ savch('\n');
+ savch(0);
+ BEGIN 0;
+ return cp;
+}
+
+static void
+cpperror(void)
+{
+ usch *cp;
+ int c;
+
+ if (flslvl)
+ return;
+ c = yylex();
+ if (c != WSPACE && c != '\n')
+ error("bad error");
+ cp = svinp();
+ if (flslvl)
+ stringbuf = cp;
+ else
+ error("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((usch *)yytext, FIND)))
+ np->value = 0;
+ slow = 0;
+ chknl();
+}
+
+static void
+pragmastmt(void)
+{
+ int c;
+
+ slow = 1;
+ if (yylex() != WSPACE)
+ error("bad pragma");
+ putstr((usch *)"#pragma ");
+ do {
+ putch(c = input()); /* Do arg expansion instead? */
+ } while (c && c != '\n');
+ ifiles->lineno++;
+ prtline();
+ slow = 0;
+}
--- /dev/null
+++ usr.bin/pcc/cpp/token.c
@@ -0,0 +1,495 @@
+/* $Id: token.c,v 1.11 2006/09/28 11:10:08 ragge Exp $ */
+
+/*
+ * 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 "cpp.h"
+
+/* definition for include file info */
+struct includ {
+ struct includ *next;
+ char *fname;
+ int lineno;
+ int infil;
+ usch *curptr;
+ usch *maxread;
+ usch *ostr;
+ usch *buffer;
+ usch bbuf[NAMEMAX+CPPBUF+1];
+} *ifiles;
+
+usch *yyp, *yystr, yybuf[CPPBUF];
+
+int yylex(void);
+int yywrap(void);
+
+static struct includ *
+getbuf(usch *file)
+{
+ struct includ *ic;
+ usch *ostr = stringbuf;
+
+ stringbuf = (usch *)ROUND((int)stringbuf);
+ ic = (struct includ *)stringbuf;
+ stringbuf += sizeof(struct includ);
+ ic->ostr = ostr;
+
+ return ic;
+}
+
+static void
+putbuf(struct includ *ic)
+{
+if (stringbuf < (usch *)&ic[1])
+;
+else
+ stringbuf = ic->ostr;
+}
+
+static int
+input(void)
+{
+ struct includ *ic;
+ int len;
+
+ if (ifiles->curptr < ifiles->maxread)
+ return *ifiles->curptr++;
+
+ if (ifiles->infil < 0) {
+ ic = ifiles;
+ ifiles = ifiles->next;
+ putbuf(ic);
+ return input();
+ }
+ if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
+ error("read error on file %s", ifiles->fname);
+ if (len == 0)
+ return -1;
+ ifiles->curptr = ifiles->buffer;
+ ifiles->maxread = ifiles->buffer + len;
+ return input();
+}
+
+static void
+unput(int c)
+{
+ struct includ *ic;
+
+ if (ifiles->curptr > ifiles->bbuf) {
+ *--ifiles->curptr = c;
+ } else {
+ ic = getbuf(NULL);
+ ic->fname = ifiles->fname;
+ ic->lineno = ifiles->lineno;
+ ic->infil = -1;
+ ic->curptr = &ic->bbuf[NAMEMAX+CPPBUF+1];
+ ic->maxread = ic->curptr;
+ ic->next = ifiles;
+ ifiles = ic;
+ *--ifiles->curptr = c;
+ }
+}
+
+#define UNPUT(c) *--ifiles->curptr = c
+
+static int
+slofgetc(void)
+{
+ int c;
+
+again: switch (c = input()) {
+ case '\\': /* continued lines */
+ if ((c = input()) == '\n') {
+ ifiles->lineno++;
+ putc('\n', obuf);
+ goto again;
+ }
+ cunput(c);
+ return '\\';
+ case '?': /* trigraphs */
+ if ((c = input()) != '?') {
+ cunput(c);
+ return '?';
+ }
+ switch (c = input()) {
+ 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:
+ cunput(c);
+ cunput('?');
+ return '?';
+ }
+ cunput(c);
+ goto again;
+ default:
+ return c;
+ }
+}
+
+int
+yylex()
+{
+ static int wasnl = 1;
+ int c, oc, rval;
+
+fast: yystr = yybuf;
+ yyp = yystr;
+ c = input();
+ if (c != ' ' && c != '\t' && c != '#')
+ wasnl = 0;
+#define ONEMORE() { *yyp++ = c; c = slofgetc(); }
+again: switch (c) {
+ case -1:
+ rval = 0;
+ break;
+
+ case '\'': /* charcon */
+ case '"': /* string */
+chstr: oc = c;
+ if (slow == 0) {
+ do {
+ putch(c);
+ if (c == '\\')
+ putch(slofgetc());
+ } while ((c = slofgetc()) != EOF && c != oc);
+ if (c == oc)
+ putch(c);
+ goto fast;
+ } else {
+ do {
+ *yyp++ = c;
+ if (c == '\\')
+ *yyp++ = slofgetc();
+ } while ((c = slofgetc()) != EOF && c != oc);
+ *yyp++ = c; *yyp = 0;
+ }
+ rval = oc == '"' ? STRING : CHARCON;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ *yyp++ = c;
+ c = slofgetc();
+ if (yyp[-1] == '0' && (c == 'x' || c == 'X')) {
+ do {
+ ONEMORE();
+ } while (isxdigit(c));
+ } else {
+ while (isdigit(c))
+ ONEMORE();
+ }
+ if (c != '.' && c != 'e' && c != 'E') {
+ /* not floating point number */
+ while (c == 'l' || c == 'L' || c == 'u' || c == 'U') {
+ ONEMORE();
+ }
+ cunput(c);
+ *yyp = 0;
+ rval = NUMBER;
+ break;
+ }
+ /* it's a floating point number here */
+ if (c == '.') { /* decimal point */
+F: do { /* may be followed by digits */
+ ONEMORE();
+ } while (isdigit(c));
+ if (c == 'e' || c == 'E') {
+E: ONEMORE();
+ if (c == '-' || c == '+') {
+ ONEMORE();
+ }
+ while (isdigit(c))
+ ONEMORE();
+ }
+ if (c == 'f' || c == 'F' || c == 'l' || c == 'L')
+ ONEMORE();
+ cunput(c);
+ *yyp = 0;
+ rval = FPOINT;
+ break;
+ } else
+ goto E;
+
+ case '.':
+ ONEMORE();
+ if (isdigit(c))
+ goto F;
+ if (!slow) {
+ UNPUT(c);
+ putch('.');
+ goto fast;
+ }
+ if (c == '.') {
+ ONEMORE();
+ if (c == '.') {
+ *yyp++ = '.'; *yyp = 0;
+ rval = ELLIPS;
+ break;
+ }
+ cunput(c);
+ cunput('.');
+ *--yyp = 0;
+ rval = '.';
+ break;
+ }
+ cunput(c);
+ *yyp = 0;
+ rval = '.';
+ break;
+
+ case '\\':
+ c = input();
+ if (c == '\n') {
+ ifiles->lineno++;
+ putch('\n');
+ goto fast;
+ }
+ if (!slow) {
+ putch('\\');
+ goto again;
+ }
+ UNPUT(c);
+ *yyp++ = '\\'; *yyp = 0;
+ rval = '\\';
+ break;
+
+ case '\n':
+ wasnl = 1;
+ ifiles->lineno++;
+ rval = NL;
+ if (slow)
+ break;
+ if (flslvl == 0) {
+ if (curline() == 1)
+ prtline();
+ else
+ putch('\n');
+ }
+ goto fast;
+
+ case '#':
+ if (wasnl) {
+ wasnl = 0;
+ rval = CONTROL;
+ break;
+ }
+ if (!slow) {
+ putch('#');
+ goto fast;
+ }
+ *yyp++ = c;
+ c = input();
+ if (c == '#') {
+ *yyp++ = c;
+ *yyp = 0;
+ rval = CONCAT;
+ } else {
+ unput(c);
+ *yyp = 0;
+ rval = MKSTR;
+ }
+ break;
+
+ case ' ':
+ case '\t': /* whitespace */
+ do {
+ *yyp++ = c;
+ c = input();
+ } while (c == ' ' || c == '\t');
+ if (wasnl && c == '#') {
+ wasnl = 0;
+ rval = CONTROL;
+ } else {
+ unput(c);
+ *yyp = 0;
+ rval = WSPACE;
+ }
+ break;
+
+ case '/':
+ if ((c = slofgetc()) == '/') {
+ if (Cflag)
+ fprintf(obuf, "//");
+ while ((c = slofgetc()) && c != '\n')
+ if (Cflag)
+ putc(c, obuf);
+ goto again;
+ } else if (c == '*') {
+ if (Cflag)
+ fprintf(obuf, "/*");
+ oc = 0;
+ do {
+ while ((c = slofgetc()) && c != '*') {
+ if (c == '\n') {
+ putc(c, obuf);
+ ifiles->lineno++;
+ } else if (Cflag)
+ putc(c, obuf);
+ }
+ if (Cflag)
+ putc(c, obuf);
+ if ((c = slofgetc()) == '/')
+ break;
+ unput(c);
+ } while (c);
+ if (Cflag)
+ putc(c, obuf);
+ if (tflag) {
+ rval = yylex();
+ } else {
+ *yyp++ = ' '; *yyp = 0;
+ rval = WSPACE;
+ }
+ } else {
+ unput(c);
+ *yyp++ = '/'; *yyp = 0;
+ rval = '/';
+ }
+ break;
+
+ case 'L': /* may be STRING, CHARCON or identifier */
+ *yyp++ = c;
+ if ((c = slofgetc()) == '"' || c == '\'')
+ goto chstr;
+gotid: while (isalnum(c) || c == '_') {
+ *yyp++ = c;
+ c = slofgetc();
+ }
+ *yyp = 0;
+ unput(c);
+ rval = IDENT;
+ break;
+
+ default:
+ if (isalpha(c) || c == '_')
+ goto gotid;
+ if (!slow && c > 5) {
+ putch(c);
+ goto fast;
+ }
+ yystr[0] = c; yystr[1] = 0;
+ rval = c;
+ break;
+ }
+ return rval;
+}
+
+/*
+ * A new file included.
+ * If ifiles == NULL, this is the first file and already opened (stdin).
+ * Return 0 on success, -1 on failure to open file.
+ */
+int
+pushfile(char *file)
+{
+ struct includ ibuf;
+ struct includ *old;
+ struct includ *ic;
+
+ ic = &ibuf;
+ old = ifiles;
+
+ slow = 0;
+ if (file != NULL) {
+ if ((ic->infil = open(file, O_RDONLY)) < 0)
+ return -1;
+ ic->fname = file;
+ } else {
+ ic->infil = 0;
+ ic->fname = "<stdin>";
+ }
+ ic->buffer = ic->bbuf+NAMEMAX;
+ ic->curptr = ic->buffer;
+ ifiles = ic;
+ ic->lineno = 0;
+ ic->maxread = ic->curptr;
+ unput('\n');
+
+ mainscan();
+
+ if (trulvl || flslvl)
+ error("unterminated conditional");
+
+ ifiles = old;
+ close(ic->infil);
+ return 0;
+}
+
+/*
+ * Print current position to output file.
+ */
+void
+prtline()
+{
+ fprintf(obuf, "# %d \"%s\"\n", ifiles->lineno, ifiles->fname);
+}
+
+void
+cunput(int c)
+{
+extern int dflag;
+if (dflag)printf(": '%c'(%d)", c, c);
+ unput(c);
+}
+
+void
+setline(int line)
+{
+ if (ifiles)
+ ifiles->lineno = line-1;
+}
+
+void
+setfile(char *name)
+{
+ if (ifiles)
+ ifiles->fname = strdup(name);
+}
+
+int
+curline()
+{
+ return ifiles ? ifiles->lineno : 0;
+}
+
+char *
+curfile()
+{
+ return ifiles ? ifiles->fname : "";
+}
--- /dev/null
+++ usr.bin/pcc/cpp/cpp.c
@@ -0,0 +1,1482 @@
+/* $Id: cpp.c,v 1.65 2007/09/25 20:41:08 ragge Exp $ */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson (ragge at 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.
+ */
+/*
+ * The C preprocessor.
+ * This code originates from the V6 preprocessor with some additions
+ * from V7 cpp, and at last ansi/c99 support.
+ */
+
+#include "../../config.h"
+
+#include <sys/wait.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include "cpp.h"
+#include "y.tab.h"
+
+#define MAXARG 250 /* # of args to a macro, limited by char value */
+#define SBSIZE 600000
+
+static usch sbf[SBSIZE];
+/* C command */
+
+int tflag; /* traditional cpp syntax */
+#ifdef CPP_DEBUG
+int dflag; /* debug printouts */
+#define DPRINT(x) if (dflag) printf x
+#define DDPRINT(x) if (dflag > 1) printf x
+#else
+#define DPRINT(x)
+#define DDPRINT(x)
+#endif
+
+int ofd;
+usch outbuf[CPPBUF];
+int obufp, istty;
+int Cflag, Mflag, dMflag;
+usch *Mfile;
+struct initar *initar;
+
+/* avoid recursion */
+struct recur {
+ struct recur *next;
+ struct symtab *sp;
+};
+
+/* include dirs */
+struct incs {
+ struct incs *next;
+ usch *dir;
+} *incdir[2];
+#define INCINC 0
+#define SYSINC 1
+
+static struct symtab *filloc;
+static struct symtab *linloc;
+static struct symtab *pragloc;
+int trulvl;
+int flslvl;
+int elflvl;
+int elslvl;
+usch *stringbuf = sbf;
+
+/*
+ * Macro replacement list syntax:
+ * - For object-type macros, replacement strings are stored as-is.
+ * - For function-type macros, macro args are substituted for the
+ * character WARN followed by the argument number.
+ * - The value element points to the end of the string, to simplify
+ * pushback onto the input queue.
+ *
+ * The first character (from the end) in the replacement list is
+ * the number of arguments:
+ * VARG - ends with ellipsis, next char is argcount without ellips.
+ * OBJCT - object-type macro
+ * 0 - empty parenthesis, foo()
+ * 1-> - number of args.
+ */
+
+#define VARG 0xfe /* has varargs */
+#define OBJCT 0xff
+#define WARN 1 /* SOH, not legal char */
+#define CONC 2 /* STX, not legal char */
+#define SNUFF 3 /* ETX, not legal char */
+#define NOEXP 4 /* EOT, not legal char */
+#define EXPAND 5 /* ENQ, not legal char */
+
+/* args for lookup() */
+#define FIND 0
+#define ENTER 1
+
+static void expdef(usch *proto, struct recur *, int gotwarn);
+void define(void);
+static int canexpand(struct recur *, struct symtab *np);
+void include(void);
+void line(void);
+void flbuf(void);
+void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ struct initar *it;
+ struct incs *w, *w2;
+ struct symtab *nl;
+ register int ch;
+
+ while ((ch = getopt(argc, argv, "CD:I:MS:U:d:i:tvV?")) != -1)
+ switch (ch) {
+ case 'C': /* Do not discard comments */
+ Cflag++;
+ break;
+
+ case 'i': /* include */
+ case 'U': /* undef */
+ case 'D': /* define something */
+ /* XXX should not need malloc() here */
+ if ((it = malloc(sizeof(struct initar))) == NULL)
+ error("couldn't apply -%c %s", ch, optarg);
+ it->type = ch;
+ it->str = optarg;
+ it->next = initar;
+ initar = it;
+ break;
+
+ case 'M': /* Generate dependencies for make */
+ Mflag++;
+ break;
+
+ case 'S':
+ case 'I':
+ if ((w = calloc(sizeof(struct incs), 1)) == NULL)
+ error("couldn't apply -%c %s", ch, optarg);
+ w->dir = (usch *)optarg;
+ w2 = incdir[ch == 'I' ? INCINC : SYSINC];
+ if (w2 != NULL) {
+ while (w2->next)
+ w2 = w2->next;
+ w2->next = w;
+ } else
+ incdir[ch == 'I' ? INCINC : SYSINC] = w;
+ break;
+
+#ifdef CPP_DEBUG
+ case 'V':
+ dflag++;
+ break;
+#endif
+ case 'v':
+ printf("cpp: %s\n", VERSSTR);
+ break;
+ case 'd':
+ if (optarg[0] == 'M') {
+ dMflag = 1;
+ Mflag = 1;
+ }
+ /* ignore others */
+ break;
+
+ case 't':
+ tflag = 1;
+ break;
+
+ case '?':
+ usage();
+ default:
+ error("bad arg %c\n", ch);
+ }
+ argc -= optind;
+ argv += optind;
+
+ filloc = lookup((usch *)"__FILE__", ENTER);
+ linloc = lookup((usch *)"__LINE__", ENTER);
+ pragloc = lookup((usch *)"_Pragma", ENTER);
+ filloc->value = linloc->value = (usch *)""; /* Just something */
+ pragloc->value = (usch *)"";
+
+ if (tflag == 0) {
+ time_t t = time(NULL);
+ usch *n = (usch *)ctime(&t);
+
+ /*
+ * Manually move in the predefined macros.
+ */
+ nl = lookup((usch *)"__TIME__", ENTER);
+ savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"');
+ savch(OBJCT);
+ nl->value = stringbuf-1;
+
+ nl = lookup((usch *)"__DATE__", ENTER);
+ savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]);
+ savstr(&n[20]); savch('"'); savch(OBJCT);
+ nl->value = stringbuf-1;
+
+ nl = lookup((usch *)"__STDC__", ENTER);
+ savch(0); savch('1'); savch(OBJCT);
+ nl->value = stringbuf-1;
+ }
+
+ if (Mflag && !dMflag) {
+ usch *c;
+
+ if (argc < 1)
+ error("-M and no infile");
+ if ((c = (usch *)strrchr(argv[0], '/')) == NULL)
+ c = (usch *)argv[0];
+ else
+ c++;
+ Mfile = stringbuf;
+ savstr(c); savch(0);
+ if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL)
+ error("-M and no extension: ");
+ c[1] = 'o';
+ c[2] = 0;
+ }
+
+ if (argc == 2) {
+ if ((ofd = open(argv[1], O_WRONLY|O_CREAT, 0600)) < 0)
+ error("Can't creat %s", argv[1]);
+ } else
+ ofd = 1; /* stdout */
+ istty = isatty(ofd);
+
+ if (pushfile((usch *)(argc && strcmp(argv[0], "-") ? argv[0] : NULL)))
+ error("cannot open %s", argv[0]);
+
+ flbuf();
+ close(ofd);
+ return 0;
+}
+
+/*
+ * Expand the symbol nl read from input.
+ * Return a pointer to the fully expanded result.
+ * It is the responsibility of the caller to reset the heap usage.
+ */
+usch *
+gotident(struct symtab *nl)
+{
+ struct symtab *thisnl;
+ usch *osp, *ss2, *base;
+ int c;
+
+ thisnl = NULL;
+ slow = 1;
+ base = osp = stringbuf;
+ goto found;
+
+ while ((c = yylex()) != 0) {
+ switch (c) {
+ case IDENT:
+ if (flslvl)
+ break;
+ osp = stringbuf;
+
+ DPRINT(("IDENT0: %s\n", yytext));
+ nl = lookup((usch *)yytext, FIND);
+ if (nl == 0 || thisnl == 0)
+ goto found;
+ if (thisnl == nl) {
+ nl = 0;
+ goto found;
+ }
+ ss2 = stringbuf;
+ if ((c = yylex()) == WSPACE) {
+ savstr((usch *)yytext);
+ c = yylex();
+ }
+ if (c != EXPAND) {
+ unpstr((usch *)yytext);
+ if (ss2 != stringbuf)
+ unpstr(ss2);
+ unpstr(nl->namep);
+ (void)yylex(); /* get yytext correct */
+ nl = 0; /* ignore */
+ } else {
+ thisnl = NULL;
+ if (nl->value[0] == OBJCT) {
+ unpstr(nl->namep);
+ (void)yylex(); /* get yytext correct */
+ nl = 0;
+ }
+ }
+ stringbuf = ss2;
+
+found: if (nl == 0 || subst(nl, NULL) == 0) {
+ if (nl)
+ savstr(nl->namep);
+ else
+ savstr((usch *)yytext);
+ } else if (osp != stringbuf) {
+ DPRINT(("IDENT1: unput osp %p stringbuf %p\n",
+ osp, stringbuf));
+ ss2 = stringbuf;
+ cunput(EXPAND);
+ while (ss2 > osp)
+ cunput(*--ss2);
+ thisnl = nl;
+ stringbuf = osp; /* clean up heap */
+ }
+ break;
+
+ case EXPAND:
+ DPRINT(("EXPAND!\n"));
+ thisnl = NULL;
+ break;
+
+ case STRING:
+ case '\n':
+ case NUMBER:
+ case FPOINT:
+ case WSPACE:
+ savstr((usch *)yytext);
+ break;
+
+ default:
+ if (c < 256)
+ savch(c);
+ else
+ savstr((usch *)yytext);
+ break;
+ }
+ if (thisnl == NULL) {
+ slow = 0;
+ savch(0);
+ return base;
+ }
+ }
+ error("preamture EOF");
+ /* NOTREACHED */
+ return NULL; /* XXX gcc */
+}
+
+void
+line()
+{
+ static usch *lbuf;
+ static int llen;
+ int c;
+
+ slow = 1;
+ if (yylex() != WSPACE)
+ goto bad;
+ if ((c = yylex()) != IDENT || !isdigit((int)yytext[0]))
+ goto bad;
+ ifiles->lineno = atoi(yytext);
+
+ if ((c = yylex()) != '\n' && c != WSPACE)
+ goto bad;
+ if (c == '\n') {
+ slow = 0;
+ return;
+ }
+ if (yylex() != STRING)
+ goto bad;
+ c = strlen((char *)yytext);
+ if (llen < c) {
+ /* XXX may loose heap space */
+ lbuf = stringbuf;
+ stringbuf += c;
+ llen = c;
+ }
+ yytext[strlen(yytext)-1] = 0;
+ if (strlcpy((char *)lbuf, &yytext[1], SBSIZE) >= SBSIZE)
+ error("line exceeded buffer size");
+
+ ifiles->fname = lbuf;
+ if (yylex() != '\n')
+ goto bad;
+ slow = 0;
+ return;
+
+bad: error("bad line directive");
+}
+
+/*
+ * Include a file. Include order:
+ * - For <...> files, first search -I directories, then system directories.
+ * - For "..." files, first search "current" dir, then as <...> files.
+ */
+void
+include()
+{
+ struct incs *w;
+ struct symtab *nl;
+ usch *osp;
+ usch *fn, *safefn;
+ int i, c, it;
+
+ if (flslvl)
+ return;
+ osp = stringbuf;
+ slow = 1;
+again:
+ if ((c = yylex()) == WSPACE)
+ c = yylex();
+ if (c != STRING && c != '<' && c != IDENT)
+ goto bad;
+
+ if (c == IDENT) {
+ if ((nl = lookup((usch *)yytext, FIND)) == NULL)
+ goto bad;
+ if (subst(nl, NULL) == 0)
+ goto bad;
+ savch('\0');
+ unpstr(osp);
+ goto again;
+ } else if (c == '<') {
+ fn = stringbuf;
+ while ((c = yylex()) != '>' && c != '\n') {
+ if (c == '\n')
+ goto bad;
+ savstr((usch *)yytext);
+ }
+ savch('\0');
+ while ((c = yylex()) == WSPACE)
+ ;
+ if (c != '\n')
+ goto bad;
+ it = SYSINC;
+ safefn = fn;
+ } else {
+ usch *nm = stringbuf;
+
+ yytext[strlen(yytext)-1] = 0;
+ fn = (usch *)&yytext[1];
+ /* first try to open file relative to previous file */
+ /* but only if it is not an absolute path */
+ if (*fn != '/') {
+ savstr(ifiles->orgfn);
+ if ((stringbuf =
+ (usch *)strrchr((char *)nm, '/')) == NULL)
+ stringbuf = nm;
+ else
+ stringbuf++;
+ }
+ safefn = stringbuf;
+ savstr(fn); savch(0);
+ while ((c = yylex()) == WSPACE)
+ ;
+ if (c != '\n')
+ goto bad;
+ slow = 0;
+ if (pushfile(nm) == 0)
+ return;
+ /* XXX may loose stringbuf space */
+ }
+
+ /* create search path and try to open file */
+ slow = 0;
+ for (i = 0; i < 2; i++) {
+ for (w = incdir[i]; w; w = w->next) {
+ usch *nm = stringbuf;
+
+ savstr(w->dir); savch('/');
+ savstr(safefn); savch(0);
+ if (pushfile(nm) == 0)
+ return;
+ stringbuf = nm;
+ }
+ }
+ error("cannot find '%s'", safefn);
+ /* error() do not return */
+
+bad: error("bad include");
+ /* error() do not return */
+}
+
+static int
+definp(void)
+{
+ int c;
+
+ do
+ c = yylex();
+ while (c == WSPACE);
+ return c;
+}
+
+void
+define()
+{
+ struct symtab *np;
+ usch *args[MAXARG], *ubuf, *sbeg;
+ int c, i, redef;
+ int mkstr = 0, narg = -1;
+ int ellips = 0;
+ int len;
+
+ if (flslvl)
+ return;
+ slow = 1;
+ if (yylex() != WSPACE || yylex() != IDENT)
+ goto bad;
+
+ if (isdigit((int)yytext[0]))
+ goto bad;
+
+ np = lookup((usch *)yytext, ENTER);
+ redef = np->value != NULL;
+
+ sbeg = stringbuf;
+ if ((c = yylex()) == '(') {
+ narg = 0;
+ /* function-like macros, deal with identifiers */
+ for (;;) {
+ c = definp();
+ if (c == ')')
+ break;
+ if (c == ELLIPS) {
+ ellips = 1;
+ if (definp() != ')')
+ goto bad;
+ break;
+ }
+ if (c == IDENT) {
+ len = strlen(yytext);
+ args[narg] = alloca(len+1);
+ strlcpy((char *)args[narg], yytext, len+1);
+ narg++;
+ if ((c = definp()) == ',')
+ continue;
+ if (c == ')')
+ break;
+ goto bad;
+ }
+ goto bad;
+ }
+ c = yylex();
+ } else if (c == '\n') {
+ /* #define foo */
+ ;
+ } else if (c != WSPACE)
+ goto bad;
+
+ while (c == WSPACE)
+ c = yylex();
+
+ /* parse replacement-list, substituting arguments */
+ savch('\0');
+ while (c != '\n') {
+ switch (c) {
+ case WSPACE:
+ /* remove spaces if it surrounds a ## directive */
+ ubuf = stringbuf;
+ savstr((usch *)yytext);
+ c = yylex();
+ if (c == CONCAT) {
+ stringbuf = ubuf;
+ savch(CONC);
+ if ((c = yylex()) == WSPACE)
+ c = yylex();
+ }
+ continue;
+
+ case CONCAT:
+ /* No spaces before concat op */
+ savch(CONC);
+ if ((c = yylex()) == WSPACE)
+ c = yylex();
+ continue;
+
+ case MKSTR:
+ if (narg < 0) {
+ /* no meaning in object-type macro */
+ savch('#');
+ break;
+ }
+ /* remove spaces between # and arg */
+ savch(SNUFF);
+ if ((c = yylex()) == WSPACE)
+ c = yylex(); /* whitespace, ignore */
+ mkstr = 1;
+ if (c == VA_ARGS)
+ continue;
+
+ /* FALLTHROUGH */
+ case IDENT:
+ if (narg < 0)
+ goto id; /* just add it if object */
+ /* check if its an argument */
+ for (i = 0; i < narg; i++)
+ if (strcmp(yytext, (char *)args[i]) == 0)
+ break;
+ if (i == narg) {
+ if (mkstr)
+ error("not argument");
+ goto id;
+ }
+ savch(i);
+ savch(WARN);
+ if (mkstr)
+ savch(SNUFF), mkstr = 0;
+ break;
+
+ case VA_ARGS:
+ if (ellips == 0)
+ error("unwanted %s", yytext);
+ savch(VARG);
+ savch(WARN);
+ if (mkstr)
+ savch(SNUFF), mkstr = 0;
+ break;
+
+ default:
+id: savstr((usch *)yytext);
+ break;
+ }
+ c = yylex();
+ }
+ /* remove trailing whitespace */
+ while (stringbuf > sbeg) {
+ if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')
+ stringbuf--;
+ else
+ break;
+ }
+ if (ellips) {
+ savch(narg);
+ savch(VARG);
+ } else
+ savch(narg < 0 ? OBJCT : narg);
+ if (redef) {
+ usch *o = np->value, *n = stringbuf-1;
+
+ /* Redefinition to identical replacement-list is allowed */
+ while (*o && *o == *n)
+ o--, n--;
+ if (*o || *o != *n)
+ error("%s redefined\nprevious define: %s:%d",
+ np->namep, np->file, np->line);
+ stringbuf = sbeg; /* forget this space */
+ } else
+ np->value = stringbuf-1;
+
+#ifdef CPP_DEBUG
+ if (dflag) {
+ usch *w = np->value;
+
+ printf("!define: ");
+ if (*w == OBJCT)
+ printf("[object]");
+ else if (*w == VARG)
+ printf("[VARG%d]", *--w);
+ while (*--w) {
+ switch (*w) {
+ case WARN: printf("<%d>", *--w); break;
+ case CONC: printf("<##>"); break;
+ case SNUFF: printf("<\">"); break;
+ default: putchar(*w); break;
+ }
+ }
+ putchar('\n');
+ }
+#endif
+ slow = 0;
+ return;
+
+bad: error("bad define");
+}
+
+void
+xerror(usch *s)
+{
+ usch *t;
+
+ flbuf();
+ savch(0);
+ if (ifiles != NULL) {
+ t = sheap("%s:%d: ", ifiles->fname, ifiles->lineno);
+ write (2, t, strlen((char *)t));
+ }
+ write (2, s, strlen((char *)s));
+ write (2, "\n", 1);
+ exit(1);
+}
+
+/*
+ * store a character into the "define" buffer.
+ */
+void
+savch(c)
+{
+ if (stringbuf-sbf < SBSIZE) {
+ *stringbuf++ = c;
+ } else {
+ stringbuf = sbf; /* need space to write error message */
+ error("Too much defining");
+ }
+}
+
+/*
+ * convert _Pragma to #pragma for output.
+ */
+static void
+pragoper(void)
+{
+ usch *opb;
+ int t;
+
+ slow = 1;
+ putstr((usch *)"\n#pragma ");
+ if ((t = yylex()) == WSPACE)
+ t = yylex();
+ if (t != '(')
+ goto bad;
+ if ((t = yylex()) == WSPACE)
+ t = yylex();
+ opb = stringbuf;
+ while (t != ')') {
+ savstr((usch *)yytext);
+ t = yylex();
+ }
+ savch(0);
+ cunput(WARN);
+ unpstr(opb);
+ stringbuf = opb;
+ expmac(NULL);
+ while (stringbuf > opb)
+ cunput(*--stringbuf);
+ if ((t = yylex()) != STRING)
+ goto bad;
+ opb = (usch *)yytext;
+ if (*opb++ == 'L')
+ opb++;
+ while ((t = *opb++) != '\"') {
+ if (t == '\\' && (*opb == '\"' || *opb == '\\'))
+ t = *opb++;
+ putch(t);
+ }
+ putch('\n');
+ prtline();
+ return;
+bad: error("bad pragma operator");
+}
+
+/*
+ * substitute namep for sp->value.
+ */
+int
+subst(sp, rp)
+struct symtab *sp;
+struct recur *rp;
+{
+ struct recur rp2;
+ register usch *vp, *cp;
+ int c, rv = 0, ws;
+
+ DPRINT(("subst: %s\n", sp->namep));
+ /*
+ * First check for special macros.
+ */
+ if (sp == filloc) {
+ (void)sheap("\"%s\"", ifiles->fname);
+ return 1;
+ } else if (sp == linloc) {
+ (void)sheap("%d", ifiles->lineno);
+ return 1;
+ } else if (sp == pragloc) {
+ pragoper();
+ return 1;
+ }
+ vp = sp->value;
+
+ rp2.next = rp;
+ rp2.sp = sp;
+
+ if (*vp-- != OBJCT) {
+ int gotwarn = 0;
+
+ /* should we be here at all? */
+ /* check if identifier is followed by parentheses */
+ rv = 1;
+ ws = 0;
+ do {
+ c = yylex();
+ if (c == WARN) {
+ gotwarn++;
+ if (rp == NULL)
+ goto noid;
+ } else if (c == WSPACE || c == '\n')
+ ws = 1;
+ } while (c == WSPACE || c == '\n' || c == WARN);
+
+ cp = (usch *)yytext;
+ while (*cp)
+ cp++;
+ while (cp > (usch *)yytext)
+ cunput(*--cp);
+ DPRINT(("c %d\n", c));
+ if (c == '(' ) {
+ expdef(vp, &rp2, gotwarn);
+ return rv;
+ } else {
+ /* restore identifier */
+noid: while (gotwarn--)
+ cunput(WARN);
+ if (ws)
+ cunput(' ');
+ cp = sp->namep;
+ while (*cp)
+ cp++;
+ while (cp > sp->namep)
+ cunput(*--cp);
+ if ((c = yylex()) != IDENT)
+ error("internal sync error");
+ return 0;
+ }
+ } else {
+ cunput(WARN);
+ cp = vp;
+ while (*cp) {
+ if (*cp != CONC)
+ cunput(*cp);
+ cp--;
+ }
+ expmac(&rp2);
+ }
+ return 1;
+}
+
+/*
+ * do macro-expansion until WARN character read.
+ * read from lex buffer and store result on heap.
+ * will recurse into lookup() for recursive expansion.
+ * when returning all expansions on the token list is done.
+ */
+void
+expmac(struct recur *rp)
+{
+ struct symtab *nl;
+ int c, noexp = 0, orgexp;
+ usch *och, *stksv;
+ extern int yyleng;
+
+#ifdef CPP_DEBUG
+ if (dflag) {
+ struct recur *rp2 = rp;
+ printf("\nexpmac\n");
+ while (rp2) {
+ printf("do not expand %s\n", rp->sp->namep);
+ rp2 = rp2->next;
+ }
+ }
+#endif
+ while ((c = yylex()) != WARN) {
+ switch (c) {
+ case NOEXP: noexp++; break;
+ case EXPAND: noexp--; break;
+
+ case IDENT:
+ /*
+ * Handle argument concatenation here.
+ * If an identifier is found and directly
+ * after EXPAND or NOEXP then push the
+ * identifier back on the input stream and
+ * call yylex() again.
+ * Be careful to keep the noexp balance.
+ */
+ och = stringbuf;
+ savstr((usch *)yytext);
+ DDPRINT(("id: str %s\n", och));
+
+ orgexp = 0;
+ while ((c = yylex()) == EXPAND || c == NOEXP)
+ if (c == EXPAND)
+ orgexp--;
+ else
+ orgexp++;
+
+ DDPRINT(("id1: noexp %d orgexp %d\n", noexp, orgexp));
+ if (c == IDENT) { /* XXX numbers? */
+ DDPRINT(("id2: str %s\n", yytext));
+ /* OK to always expand here? */
+ savstr((usch *)yytext);
+ switch (orgexp) {
+ case 0: /* been EXP+NOEXP */
+ if (noexp == 0)
+ break;
+ if (noexp != 1)
+ error("case 0");
+ cunput(NOEXP);
+ noexp = 0;
+ break;
+ case -1: /* been EXP */
+ if (noexp != 1)
+ error("case -1");
+ noexp = 0;
+ break;
+ case 1:
+ if (noexp != 0)
+ error("case 1");
+ cunput(NOEXP);
+ break;
+ default:
+ error("orgexp = %d", orgexp);
+ }
+ unpstr(och);
+ stringbuf = och;
+ continue; /* New longer identifier */
+ }
+ unpstr((usch *)yytext);
+ if (orgexp == -1)
+ cunput(EXPAND);
+ else if (orgexp == 1)
+ cunput(NOEXP);
+ unpstr(och);
+ stringbuf = och;
+
+
+ yylex(); /* XXX reget last identifier */
+
+ if ((nl = lookup((usch *)yytext, FIND)) == NULL)
+ goto def;
+
+ if (canexpand(rp, nl) == 0)
+ goto def;
+ /*
+ * If noexp == 0 then expansion of any macro is
+ * allowed. If noexp == 1 then expansion of a
+ * fun-like macro is allowed iff there is an
+ * EXPAND between the identifier and the '('.
+ */
+ if (noexp == 0) {
+ if ((c = subst(nl, rp)) == 0)
+ goto def;
+ break;
+ }
+//printf("noexp1 %d nl->namep %s\n", noexp, nl->namep);
+//if (noexp > 1) goto def;
+ if (noexp != 1)
+ error("bad noexp %d", noexp);
+ stksv = NULL;
+ if ((c = yylex()) == WSPACE) {
+ stksv = alloca(yyleng+1);
+ strlcpy((char *)stksv, yytext, yyleng+1);
+ c = yylex();
+ }
+ /* only valid for expansion if fun macro */
+ if (c == EXPAND && *nl->value != OBJCT) {
+ noexp--;
+ if (subst(nl, rp))
+ break;
+ savstr(nl->namep);
+ if (stksv)
+ savstr(stksv);
+ } else {
+ unpstr((usch *)yytext);
+ if (stksv)
+ unpstr(stksv);
+ savstr(nl->namep);
+ }
+ break;
+
+ case STRING:
+ /* remove EXPAND/NOEXP from strings */
+ if (yytext[1] == NOEXP) {
+ savch('"');
+ och = (usch *)&yytext[2];
+ while (*och != EXPAND)
+ savch(*och++);
+ savch('"');
+ break;
+ }
+ /* FALLTHROUGH */
+
+def: default:
+ savstr((usch *)yytext);
+ break;
+ }
+ }
+ if (noexp)
+ error("expmac noexp=%d", noexp);
+ DPRINT(("return from expmac\n"));
+}
+
+/*
+ * expand a function-like macro.
+ * vp points to end of replacement-list
+ * reads function arguments from yylex()
+ * result is written on top of heap
+ */
+void
+expdef(vp, rp, gotwarn)
+ usch *vp;
+ struct recur *rp;
+{
+ usch **args, *sptr, *ap, *bp, *sp;
+ int narg, c, i, plev, snuff, instr;
+ int ellips = 0;
+
+ DPRINT(("expdef %s rp %s\n", vp, (rp ? (char *)rp->sp->namep : "")));
+ if ((c = yylex()) != '(')
+ error("got %c, expected )", c);
+ if (vp[1] == VARG) {
+ narg = *vp--;
+ ellips = 1;
+ } else
+ narg = vp[1];
+ args = alloca(sizeof(usch *) * (narg+ellips));
+
+ /*
+ * read arguments and store them on heap.
+ * will be removed just before return from this function.
+ */
+ sptr = stringbuf;
+ for (i = 0; i < narg && c != ')'; i++) {
+ args[i] = stringbuf;
+ plev = 0;
+ while ((c = yylex()) == WSPACE || c == '\n')
+ ;
+ for (;;) {
+ if (plev == 0 && (c == ')' || c == ','))
+ break;
+ if (c == '(')
+ plev++;
+ if (c == ')')
+ plev--;
+ savstr((usch *)yytext);
+ while ((c = yylex()) == '\n')
+ savch('\n');
+ }
+ while (args[i] < stringbuf &&
+ (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
+ stringbuf--;
+ savch('\0');
+ }
+ if (ellips)
+ args[i] = (usch *)"";
+ if (ellips && c != ')') {
+ args[i] = stringbuf;
+ plev = 0;
+ while ((c = yylex()) == WSPACE)
+ ;
+ for (;;) {
+ if (plev == 0 && c == ')')
+ break;
+ if (c == '(')
+ plev++;
+ if (c == ')')
+ plev--;
+ savstr((usch *)yytext);
+ while ((c = yylex()) == '\n')
+ savch('\n');
+ }
+ while (args[i] < stringbuf &&
+ (stringbuf[-1] == ' ' || stringbuf[-1] == '\t'))
+ stringbuf--;
+ savch('\0');
+
+ }
+ if (narg == 0 && ellips == 0)
+ c = yylex();
+ if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1))
+ error("wrong arg count");
+
+ while (gotwarn--)
+ cunput(WARN);
+
+ sp = vp;
+ instr = snuff = 0;
+
+ /*
+ * push-back replacement-list onto lex buffer while replacing
+ * arguments.
+ */
+ cunput(WARN);
+ while (*sp != 0) {
+ if (*sp == SNUFF)
+ cunput('\"'), snuff ^= 1;
+ else if (*sp == CONC)
+ ;
+ else if (*sp == WARN) {
+
+ if (sp[-1] == VARG) {
+ bp = ap = args[narg];
+ sp--;
+ } else
+ bp = ap = args[(int)*--sp];
+ if (sp[2] != CONC && !snuff && sp[-1] != CONC) {
+ cunput(WARN);
+ while (*bp)
+ bp++;
+ while (bp > ap)
+ cunput(*--bp);
+ DPRINT(("expand arg %d string %s\n", *sp, ap));
+ bp = ap = stringbuf;
+ savch(NOEXP);
+ expmac(NULL);
+ savch(EXPAND);
+ savch('\0');
+ }
+ while (*bp)
+ bp++;
+ while (bp > ap) {
+ bp--;
+ if (snuff && !instr &&
+ (*bp == ' ' || *bp == '\t' || *bp == '\n')){
+ while (*bp == ' ' || *bp == '\t' ||
+ *bp == '\n') {
+ bp--;
+ }
+ cunput(' ');
+ }
+ cunput(*bp);
+ if ((*bp == '\'' || *bp == '"')
+ && bp[-1] != '\\' && snuff) {
+ instr ^= 1;
+ if (instr == 0 && *bp == '"')
+ cunput('\\');
+ }
+ if (instr && (*bp == '\\' || *bp == '"'))
+ cunput('\\');
+ }
+ } else
+ cunput(*sp);
+ sp--;
+ }
+ stringbuf = sptr;
+
+ /* scan the input buffer (until WARN) and save result on heap */
+ expmac(rp);
+}
+
+usch *
+savstr(usch *str)
+{
+ usch *rv = stringbuf;
+
+ do {
+ if (stringbuf >= &sbf[SBSIZE]) {
+ stringbuf = sbf; /* need space to write error message */
+ error("out of macro space!");
+ }
+ } while ((*stringbuf++ = *str++));
+ stringbuf--;
+ return rv;
+}
+
+int
+canexpand(struct recur *rp, struct symtab *np)
+{
+ struct recur *w;
+
+ for (w = rp; w && w->sp != np; w = w->next)
+ ;
+ if (w != NULL)
+ return 0;
+ return 1;
+}
+
+void
+unpstr(usch *c)
+{
+ usch *d = c;
+
+ while (*d)
+ d++;
+ while (d > c) {
+ cunput(*--d);
+ }
+}
+
+void
+flbuf()
+{
+ if (obufp == 0)
+ return;
+ if (Mflag == 0 && write(ofd, outbuf, obufp) < 0)
+ error("obuf write error");
+ obufp = 0;
+}
+
+void
+putch(int ch)
+{
+ outbuf[obufp++] = ch;
+ if (obufp == CPPBUF || (istty && ch == '\n'))
+ flbuf();
+}
+
+void
+putstr(usch *s)
+{
+ for (; *s; s++) {
+ outbuf[obufp++] = *s;
+ if (obufp == CPPBUF || (istty && *s == '\n'))
+ flbuf();
+ }
+}
+
+/*
+ * convert a number to an ascii string. Store it on the heap.
+ */
+static void
+num2str(int num)
+{
+ static usch buf[12];
+ usch *b = buf;
+ int m = 0;
+
+ if (num < 0)
+ num = -num, m = 1;
+ do {
+ *b++ = num % 10 + '0', num /= 10;
+ } while (num);
+ if (m)
+ *b++ = '-';
+ while (b > buf)
+ savch(*--b);
+}
+
+/*
+ * similar to sprintf, but only handles %s and %d.
+ * saves result on heap.
+ */
+usch *
+sheap(char *fmt, ...)
+{
+ va_list ap;
+ usch *op = stringbuf;
+
+ va_start(ap, fmt);
+ for (; *fmt; fmt++) {
+ if (*fmt == '%') {
+ fmt++;
+ switch (*fmt) {
+ case 's':
+ savstr(va_arg(ap, usch *));
+ break;
+ case 'd':
+ num2str(va_arg(ap, int));
+ break;
+ case 'c':
+ savch(va_arg(ap, int));
+ break;
+ default:
+ break; /* cannot call error() here */
+ }
+ } else
+ savch(*fmt);
+ }
+ va_end(ap);
+ *stringbuf = 0;
+ return op;
+}
+
+void
+usage()
+{
+ error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]");
+}
+
+#ifdef notyet
+/*
+ * Symbol table stuff.
+ * The data structure used is a patricia tree implementation using only
+ * bytes to store offsets.
+ * The information stored is (lower address to higher):
+ *
+ * unsigned char bitno[2]; bit number in the string
+ * unsigned char left[3]; offset from base to left element
+ * unsigned char right[3]; offset from base to right element
+ */
+#endif
+
+/*
+ * This patricia implementation is more-or-less the same as
+ * used in ccom for string matching.
+ */
+struct tree {
+ int bitno;
+ struct tree *lr[2];
+};
+
+#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
+#define LEFT_IS_LEAF 0x80000000
+#define RIGHT_IS_LEAF 0x40000000
+#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
+#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
+#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
+#define CHECKBITS 8
+
+static struct tree *sympole;
+static int numsyms;
+
+/*
+ * Allocate a symtab struct and store the string.
+ */
+static struct symtab *
+getsymtab(usch *str)
+{
+ struct symtab *sp = malloc(sizeof(struct symtab));
+
+ if (sp == NULL)
+ error("getsymtab: couldn't allocate symtab");
+ sp->namep = savstr(str);
+ savch('\0');
+ sp->value = NULL;
+ sp->file = ifiles ? ifiles->orgfn : (usch *)"<initial>";
+ sp->line = ifiles ? ifiles->lineno : 0;
+ return sp;
+}
+
+/*
+ * Do symbol lookup in a patricia tree.
+ * Only do full string matching, no pointer optimisations.
+ */
+struct symtab *
+lookup(usch *key, int enterf)
+{
+ struct symtab *sp;
+ struct tree *w, *new, *last;
+ int len, cix, bit, fbit, svbit, ix, bitno;
+ usch *k, *m, *sm;
+
+ /* Count full string length */
+ for (k = key, len = 0; *k; k++, len++)
+ ;
+
+ switch (numsyms) {
+ case 0: /* no symbols yet */
+ if (enterf != ENTER)
+ return NULL;
+ sympole = (struct tree *)getsymtab(key);
+ numsyms++;
+ return (struct symtab *)sympole;
+
+ case 1:
+ w = sympole;
+ svbit = 0; /* XXX gcc */
+ break;
+
+ default:
+ w = sympole;
+ bitno = len * CHECKBITS;
+ for (;;) {
+ bit = BITNO(w->bitno);
+ fbit = bit > bitno ? 0 : P_BIT(key, bit);
+ svbit = fbit ? IS_RIGHT_LEAF(w->bitno) :
+ IS_LEFT_LEAF(w->bitno);
+ w = w->lr[fbit];
+ if (svbit)
+ break;
+ }
+ }
+
+ sp = (struct symtab *)w;
+
+ sm = m = sp->namep;
+ k = key;
+
+ /* Check for correct string and return */
+ for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS)
+ ;
+ if (*m == 0 && *k == 0) {
+ if (enterf != ENTER && sp->value == NULL)
+ return NULL;
+ return sp;
+ }
+
+ if (enterf != ENTER)
+ return NULL; /* no string found and do not enter */
+
+ ix = *m ^ *k;
+ while ((ix & 1) == 0)
+ ix >>= 1, cix++;
+
+ /* Create new node */
+ if ((new = malloc(sizeof *new)) == NULL)
+ error("getree: couldn't allocate tree");
+ bit = P_BIT(key, cix);
+ new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ new->lr[bit] = (struct tree *)getsymtab(key);
+
+ if (numsyms++ == 1) {
+ new->lr[!bit] = sympole;
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ sympole = new;
+ return (struct symtab *)new->lr[bit];
+ }
+
+ w = sympole;
+ last = NULL;
+ for (;;) {
+ fbit = w->bitno;
+ bitno = BITNO(w->bitno);
+ if (bitno == cix)
+ error("bitno == cix");
+ if (bitno > cix)
+ break;
+ svbit = P_BIT(key, bitno);
+ last = w;
+ w = w->lr[svbit];
+ if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF))
+ break;
+ }
+
+ new->lr[!bit] = w;
+ if (last == NULL) {
+ sympole = new;
+ } else {
+ last->lr[svbit] = new;
+ last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF);
+ }
+ if (bitno < cix)
+ new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF);
+ return (struct symtab *)new->lr[bit];
+}
+
--- /dev/null
+++ usr.bin/pcc/cpp/cpy.y
@@ -0,0 +1,166 @@
+/* $Id: cpy.y,v 1.12 2006/10/08 13:41:39 ragge Exp $ */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson (ragge at 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+void yyerror(char *);
+int yylex(void);
+%}
+
+%term stop
+%term EQ NE LE GE LS RS
+%term ANDAND OROR IDENT NUMBER
+/*
+ * The following terminals are not used in the yacc code.
+ */
+%term STRING FPOINT WSPACE VA_ARGS CONCAT MKSTR ELLIPS
+
+%left ','
+%right '='
+%right '?' ':'
+%left OROR
+%left ANDAND
+%left '|' '^'
+%left '&'
+%binary EQ NE
+%binary '<' '>' LE GE
+%left LS RS
+%left '+' '-'
+%left '*' '/' '%'
+%right '!' '~' UMINUS
+%left '(' '.'
+
+%union {
+ long long val;
+}
+
+%type <val> term NUMBER e
+
+%%
+S: e '\n' { return($1 != 0);}
+
+
+e: e '*' e
+ {$$ = $1 * $3;}
+ | e '/' e
+ {$$ = $1 / $3;}
+ | e '%' e
+ {$$ = $1 % $3;}
+ | e '+' e
+ {$$ = $1 + $3;}
+ | e '-' e
+ {$$ = $1 - $3;}
+ | e LS e
+ {$$ = $1 << $3;}
+ | e RS e
+ {$$ = $1 >> $3;}
+ | e '<' e
+ {$$ = $1 < $3;}
+ | e '>' e
+ {$$ = $1 > $3;}
+ | e LE e
+ {$$ = $1 <= $3;}
+ | e GE e
+ {$$ = $1 >= $3;}
+ | e EQ e
+ {$$ = $1 == $3;}
+ | e NE e
+ {$$ = $1 != $3;}
+ | e '&' e
+ {$$ = $1 & $3;}
+ | e '^' e
+ {$$ = $1 ^ $3;}
+ | e '|' e
+ {$$ = $1 | $3;}
+ | e ANDAND e
+ {$$ = $1 && $3;}
+ | e OROR e
+ {$$ = $1 || $3;}
+ | e '?' e ':' e
+ {$$ = $1 ? $3 : $5;}
+ | e ',' e
+ {$$ = $3;}
+ | term
+ {$$ = $1;}
+term:
+ '-' term %prec UMINUS
+ {$$ = -$2;}
+ | '!' term
+ {$$ = !$2;}
+ | '~' term
+ {$$ = ~$2;}
+ | '(' e ')'
+ {$$ = $2;}
+ | NUMBER
+ {$$= $1;}
+%%
+
+#include "cpp.h"
+
+void
+yyerror(char *err)
+{
+ error(err);
+}
--- /dev/null
+++ usr.bin/pcc/cpp/cpp.h
@@ -0,0 +1,120 @@
+/* $Id: cpp.h,v 1.27 2007/09/17 18:16:14 ragge Exp $ */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson (ragge at 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.
+ */
+
+#include <stdio.h> /* for obuf */
+
+#include "../../config.h"
+
+typedef unsigned char usch;
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#else
+extern char yytext[];
+#endif
+extern usch *stringbuf;
+
+extern int trulvl;
+extern int flslvl;
+extern int elflvl;
+extern int elslvl;
+extern int tflag, Cflag;
+extern int Mflag, dMflag;
+extern usch *Mfile;
+extern int ofd;
+
+/* args for lookup() */
+#define FIND 0
+#define ENTER 1
+
+/* buffer used internally */
+#ifndef CPPBUF
+#ifdef __pdp11__
+#define CPPBUF BUFSIZ
+#else
+#define CPPBUF 65536
+#endif
+#endif
+
+#define NAMEMAX 64 /* max len of identifier */
+
+/* definition for include file info */
+struct includ {
+ struct includ *next;
+ usch *fname; /* current fn, changed if #line found */
+ usch *orgfn; /* current fn, not changed */
+ int lineno;
+ int infil;
+ usch *curptr;
+ usch *maxread;
+ usch *buffer;
+ usch bbuf[NAMEMAX+CPPBUF+1];
+} *ifiles;
+
+/* Symbol table entry */
+struct symtab {
+ usch *namep;
+ usch *value;
+ usch *file;
+ int line;
+};
+
+struct initar {
+ struct initar *next;
+ int type;
+ char *str;
+};
+
+struct recur; /* not used outside cpp.c */
+int subst(struct symtab *, struct recur *);
+struct symtab *lookup(usch *namep, int enterf);
+usch *gotident(struct symtab *nl);
+int slow; /* scan slowly for new tokens */
+
+int pushfile(usch *fname);
+void popfile(void);
+void prtline(void);
+int yylex(void);
+void cunput(int);
+int curline(void);
+char *curfile(void);
+void setline(int);
+void setfile(char *);
+int yyparse(void);
+void yyerror(char *);
+void unpstr(usch *);
+usch *savstr(usch *str);
+void savch(int c);
+void mainscan(void);
+void putch(int);
+void putstr(usch *s);
+void line(void);
+usch *sheap(char *fmt, ...);
+void xerror(usch *);
+#define error(...) xerror(sheap(__VA_ARGS__))
+void expmac(struct recur *);
--- /dev/null
+++ usr.bin/pcc/cpp/Makefile
@@ -0,0 +1,15 @@
+# $MidnightBSD: src/usr.bin/pcc/cpp/Makefile,v 1.1 2008/05/14 04:25:57 laffer1 Exp $
+
+PROG= cpp
+PREFIX= /usr/local
+BINDIR= ${PREFIX}/libexec
+MANDIR= ${PREFIX}/man
+TARGOS= midnightbsd
+
+CFLAGS+= -DCPP_DEBUG -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
+CFLAGS+= -DLIBEXECDIR=\"${PREFIX}/libexec\"
+CPPFLAGS+= -I. -I${.CURDIR}
+
+SRCS= cpy.y scanner.l cpp.c
+
+.include <bsd.prog.mk>
--- /dev/null
+++ usr.bin/pcc/cpp/cpp.1
@@ -0,0 +1,191 @@
+.\" $Id: cpp.1,v 1.4 2007/09/26 14:48:51 ragge Exp $
+.\" $NetBSD$
+.\" $OpenBSD$
+."\
+.\" Copyright (c) 2007 Jeremy C. Reed <reed at 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 Cdt
+.Op Fl D Ar var=val
+.Op Fl U Ar var
+.Op Fl I Ar path
+.Op Fl S Ar path
+.Op Ar infile | -
+.Op Ar outfile
+.Pp
+.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 C
+Do not discard comments.
+.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 outputted.
+.\" TODO this doesn't show predefined macros
+.\" other -d options are ignored
+.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 defines as 1.
+.\" TODO: show example
+.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 I Ar directory
+Add
+.Ar directory
+to the list of system 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 M
+Generate dependencies for
+.Xr make 1 .
+.\" TODO: explain and show example?
+.It Fl S Ar directory
+Add
+.Ar directory
+to the list of system directories containing needed header files.
+.Fl S
+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__ ,
+and
+.Dv __STDC__
+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 ?
+Show command line usage for
+.Nm .
+.El
+.Sh 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 Ao stdin Ac .
+.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 ISO Standard C.
+.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.
More information about the Midnightbsd-cvs
mailing list