[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