Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <stdio.h>
#include "cpp.h"

extern  int getopt(int, char **, char *);
extern  char    *optarg;
extern  int     optind;
int     verbose;
int     Mflag;
int     Cplusplus;
int     nolineinfo;
Nlist   *kwdefined;
char    wd[128];

#define NLSIZE  128

Nlist   *nlist[NLSIZE];

struct  kwtab {
        char    *kw;
        int     val;
        int     flag;
} kwtab[] = {
        "if",           KIF,            ISKW,
        "ifdef",        KIFDEF,         ISKW,
        "ifndef",       KIFNDEF,        ISKW,
        "elif",         KELIF,          ISKW,
        "else",         KELSE,          ISKW,
        "endif",        KENDIF,         ISKW,
        "include",      KINCLUDE,       ISKW,
        "define",       KDEFINE,        ISKW,
        "undef",        KUNDEF,         ISKW,
        "line",         KLINE,          ISKW,
        "error",        KERROR,         ISKW,
        "warning",      KWARNING,       ISKW,           // extension to ANSI
        "pragma",       KPRAGMA,        ISKW,
        "eval",         KEVAL,          ISKW,
        "defined",      KDEFINED,       ISDEFINED+ISUNCHANGE,
        "__LINE__",     KLINENO,        ISMAC+ISUNCHANGE,
        "__FILE__",     KFILE,          ISMAC+ISUNCHANGE,
        "__DATE__",     KDATE,          ISMAC+ISUNCHANGE,
        "__TIME__",     KTIME,          ISMAC+ISUNCHANGE,
        "__STDC__",     KSTDC,          ISUNCHANGE,
        NULL
};

unsigned long   namebit[077+1];
Nlist   *np;

void
setup(int argc, char **argv)
{
        struct kwtab *kp;
        Nlist *np;
        Token t;
        int fd, i;
        char *fp, *dp;
        Tokenrow tr;
        char *objtype;
        char *includeenv;
        int firstinclude;
        static char nbuf[40];
        static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
        static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
        int debuginclude = 0;
        int nodot = 0;
        char xx[2] = { 0, 0};

        for (kp=kwtab; kp->kw; kp++) {
                t.t = (uchar*)kp->kw;
                t.len = strlen(kp->kw);
                np = lookup(&t, 1);
                np->flag = kp->flag;
                np->val = kp->val;
                if (np->val == KDEFINED) {
                        kwdefined = np;
                        np->val = NAME;
                        np->vp = &deftr;
                        np->ap = 0;
                }
        }
        /*
         * For Plan 9, search /objtype/include, then /sys/include
         * (Note that includelist is searched from high end to low)
         */
        if ((objtype = getenv("objtype"))){
                snprintf(nbuf, sizeof nbuf, "/%s/include", objtype);
                includelist[1].file = nbuf;
                includelist[1].always = 1;
        } else {
                includelist[1].file = NULL;
                error(WARNING, "Unknown $objtype");
        }
        if (getwd(wd, sizeof(wd))==0)
                wd[0] = '\0';
        includelist[0].file = "/sys/include";
        includelist[0].always = 1;
        firstinclude = NINCLUDE-2;
        if ((includeenv=getenv("include")) != NULL) {
                char *cp;
                includeenv = strdup(includeenv);
                for (;firstinclude>0; firstinclude--) {
                        cp = strtok(includeenv, " ");
                        if (cp==NULL)
                                break;
                        includelist[firstinclude].file = cp;
                        includelist[firstinclude].always = 1;
                        includeenv = NULL;
                }
        }
        setsource("", -1, 0);
        ARGBEGIN {
                case 'N':
                        for (i=0; i<NINCLUDE; i++)
                                if (includelist[i].always==1)
                                        includelist[i].deleted = 1;
                        break;
                case 'I':
                        for (i=firstinclude; i>=0; i--) {
                                if (includelist[i].file==NULL) {
                                        includelist[i].always = 1;
                                        includelist[i].file = ARGF();
                                        break;
                                }
                        }
                        if (i<0)
                                error(WARNING, "Too many -I directives");
                        break;
                case 'D':
                case 'U':
                        setsource("<cmdarg>", -1, ARGF());
                        maketokenrow(3, &tr);
                        gettokens(&tr, 1);
                        doadefine(&tr, ARGC());
                        unsetsource();
                        break;
                case 'M':
                        Mflag++;
                        break;
                case 'V':
                        verbose++;
                        break;
                case '+':
                        Cplusplus++;
                        break;
                case 'i':
                        debuginclude++;
                        break;
                case 'P':
                        nolineinfo++;
                        break;
                case '.':
                        nodot++;
                        break;
                default:
                        xx[0] = ARGC();
                        error(FATAL, "Unknown argument '%s'", xx);
                        break;
        } ARGEND
        dp = ".";
        fp = "<stdin>";
        fd = 0;
        if (argc > 2)
                error(FATAL, "Too many file arguments; see cpp(1)");
        if (argc > 0) {
                if ((fp = strrchr(argv[0], '/')) != NULL) {
                        int len = fp - argv[0];
                        dp = (char*)newstring((uchar*)argv[0], len+1, 0);
                        dp[len] = '\0';
                }
                fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
                if ((fd = open(fp, 0)) < 0)
                        error(FATAL, "Can't open input file %s", fp);
        }
        if (argc > 1) {
                int fdo = create(argv[1], 1, 0666);
                if (fdo<0)
                        error(FATAL, "Can't open output file %s", argv[1]);
                dup(fdo, 1);
        }
        if (Mflag)
                setobjname(fp);
        includelist[NINCLUDE-1].always = 0;
        includelist[NINCLUDE-1].file = dp;
        if(nodot)
                includelist[NINCLUDE-1].deleted = 1;
        setsource(fp, fd, NULL);
        if (debuginclude) {
                for (i=0; i<NINCLUDE; i++)
                        if (includelist[i].file && includelist[i].deleted==0)
                                error(WARNING, "Include: %s", includelist[i].file);
        }
}

Nlist *
lookup(Token *tp, int install)
{
        unsigned int h;
        Nlist *np;
        uchar *cp, *cpe;

        h = 0;
        for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
                h += *cp++;
        h %= NLSIZE;
        np = nlist[h];
        while (np) {
                if (*tp->t==*np->name && tp->len==np->len 
                 && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
                        return np;
                np = np->next;
        }
        if (install) {
                np = new(Nlist);
                np->val = 0;
                np->vp = NULL;
                np->ap = NULL;
                np->flag = 0;
                np->len = tp->len;
                np->name = newstring(tp->t, tp->len, 0);
                np->next = nlist[h];
                nlist[h] = np;
                quickset(tp->t[0], tp->len>1? tp->t[1]:0);
                return np;
        }
        return NULL;
}