commit 0ecbf7a103fa60948be1dfb8cd41691272bb909d
parent c50c0b5735d98f2503f99c215efae6c88c7a46c1
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 5 Jul 2016 08:38:51 +0200
Merge remote-tracking branch 'origin/master'
Diffstat:
M | cc1/cc1.h | | | 6 | ++++-- |
M | cc1/cpp.c | | | 58 | +++++++++++++++++++++++++++------------------------------- |
M | cc1/lex.c | | | 62 | +++++++++++++++++++++++++++++--------------------------------- |
M | cc1/main.c | | | 19 | ++++++++++++++++++- |
M | driver/posix/Makefile | | | 2 | +- |
M | driver/posix/scc.c | | | 148 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
M | inc/arg.h | | | 90 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
7 files changed, 226 insertions(+), 159 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -382,8 +382,10 @@ extern int moreinput(void);
extern void expect(unsigned tok);
extern void discard(void);
extern int addinput(char *fname);
+extern void allocinput(char *fname, FILE *fp, char *line);
+extern void delinput(void);
extern void setsafe(int type);
-extern void ilex(char *fname);
+extern void ilex(void);
#define accept(t) ((yytoken == (t)) ? next() : 0)
/* code.c */
@@ -418,7 +420,7 @@ extern int cpp(void);
extern int expand(char *begin, Symbol *sym);
extern void incdir(char *dir);
extern void outcpp(void);
-extern Symbol *defmacro(char *s);
+extern void defdefine(char *macro, char *val);
extern void undefmacro(char *s);
/*
diff --git a/cc1/cpp.c b/cc1/cpp.c
@@ -13,6 +13,7 @@
static char *argp, *macroname;
static unsigned arglen;
+static unsigned ncmdlines;
static Symbol *symline, *symfile;
static unsigned char ifstatus[NR_COND];
static int ninclude;
@@ -21,30 +22,20 @@ static char **dirinclude;
unsigned cppctx;
int disexpand;
-Symbol *
-defmacro(char *s)
+void
+defdefine(char *macro, char *val)
{
- char *p, *q;
- Symbol *sym;
- char def[] = "=1";
-
- if ((p = strchr(s, '=')) == NULL)
- p = def;
- *p++='\0';
- q = xmalloc(strlen(p) + 4);
- sprintf(q, "-1#%s", p);
+ char *def, *fmt = "#define %s %s";
- sym = lookup(NS_CPP, s);
- if (sym->flags & SDECLARED) {
- warn("'%s' redefined");
- free(sym->u.s);
- } else {
- install(NS_CPP, sym);
- sym->flags |= SDECLARED|SSTRING;
- }
+ if (!val)
+ val = "";
+ def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
- sym->u.s = q;
- return sym;
+ sprintf(def, fmt, macro, val);
+ allocinput("command-line", NULL, def);
+ input->nline = ++ncmdlines;
+ cpp();
+ delinput();
}
void
@@ -56,7 +47,7 @@ undefmacro(char *s)
void
icpp(void)
{
- static char sdate[17], stime[14];
+ static char sdate[14], stime[11];
struct tm *tm;
time_t t;
static char **bp, *list[] = {
@@ -81,20 +72,25 @@ icpp(void)
{NULL, 0, 0}
};
+ keywords(keys, NS_CPPCLAUSES);
+
t = time(NULL);
tm = localtime(&t);
- strftime(sdate, sizeof(sdate), "-1#\"%b %d %Y\"", tm);
- strftime(stime, sizeof(stime), "-1#\"%H:%M:%S\"", tm);
- defmacro("__DATE__")->u.s = sdate;
- defmacro("__TIME__")->u.s = stime;
+ strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
+ strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
+ defdefine("__DATE__", sdate);
+ defdefine("__TIME__", stime);
+ defdefine("__STDC_VERSION__", "199409L");
+ defdefine("__LINE__", NULL);
+ defdefine("__FILE__", NULL);
- defmacro("__STDC_VERSION__")->u.s = "-1#199409L";
- symline = defmacro("__LINE__");
- symfile = defmacro("__FILE__");
+ symline = lookup(NS_CPP, "__LINE__");
+ symfile = lookup(NS_CPP, "__FILE__");
for (bp = list; *bp; ++bp)
- defmacro(*bp)->u.s = "-1#1";
- keywords(keys, NS_CPPCLAUSES);
+ defdefine(*bp, NULL);
+
+ ncmdlines = 0;
}
static void
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -22,23 +22,25 @@ int namespace = NS_IDEN;
static int safe, eof;
Input *input;
-static void
-allocinput(char *fname, FILE *fp)
+void
+allocinput(char *fname, FILE *fp, char *line)
{
- Input *ip;
+ Input *ip = xmalloc(sizeof(Input));
- ip = xmalloc(sizeof(Input));
- ip->fname = xstrdup(fname);
- ip->p = ip->begin = ip->line = xmalloc(INPUTSIZ);
- ip->p[0] = '\0';
+ if (!line) {
+ line = xmalloc(INPUTSIZ);
+ line[0] = '\0';
+ }
+ ip->p = ip->begin = ip->line = line;
ip->nline = 0;
+ ip->fname = xstrdup(fname);
ip->next = input;
ip->fp = fp;
input = ip;
}
void
-ilex(char *fname)
+ilex(void)
{
static struct keyword keys[] = {
{"auto", SCLASS, AUTO},
@@ -78,18 +80,6 @@ ilex(char *fname)
{"while", WHILE, WHILE},
{NULL, 0, 0},
};
- FILE *fp;
-
- if (!fname) {
- fp = stdin;
- fname = "<stdin>";
- } else {
- if ((fp = fopen(fname, "r")) == NULL) {
- die("error: failed to open input file '%s': %s",
- fname, strerror(errno));
- }
- }
- allocinput(fname, fp);
keywords(keys, NS_KEYWORD);
}
@@ -98,21 +88,29 @@ addinput(char *fname)
{
FILE *fp;
- if ((fp = fopen(fname, "r")) == NULL)
- return 0;
- allocinput(fname, fp);
+ if (fname) {
+ if ((fp = fopen(fname, "r")) == NULL)
+ return 0;
+ } else {
+ fp = stdin;
+ fname = "<stdin>";
+ }
+ allocinput(fname, fp, NULL);
return 1;
}
-static void
+void
delinput(void)
{
Input *ip = input;
- if (!ip->next)
- eof = 1;
- if (fclose(ip->fp))
- die("error: failed to read from input file '%s'", ip->fname);
+ if (ip->fp) {
+ if (fclose(ip->fp))
+ die("error: failed to read from input file '%s'",
+ ip->fname);
+ if (!ip->next)
+ eof = 1;
+ }
if (eof)
return;
input = ip->next;
@@ -130,14 +128,12 @@ newline(void)
static int
readchar(void)
{
+ FILE *fp = input->fp;
int c;
- FILE *fp;
-repeat:
- if (eof)
+ if (eof || !fp)
return 0;
- fp = input->fp;
-
+repeat:
switch (c = getc(fp)) {
case EOF:
c = '\0';
diff --git a/cc1/main.c b/cc1/main.c
@@ -29,6 +29,19 @@ clean(void)
}
static void
+defmacro(char *macro)
+{
+ char *p = strchr(macro, '=');
+
+ if (p)
+ *p++ = '\0';
+ else
+ p = "1";
+
+ defdefine(macro, p);
+}
+
+static void
usage(void)
{
die(!strcmp(name, "cpp") ?
@@ -46,6 +59,7 @@ main(int argc, char *argv[])
atexit(clean);
icpp();
+ ilex();
/* if run as cpp, only run the preprocessor */
name = (cp = strrchr(*argv, '/')) ? cp + 1 : *argv;
@@ -88,7 +102,10 @@ main(int argc, char *argv[])
for (i = 0; i < uflags.n; ++i)
undefmacro(uflags.s[i]);
- ilex(*argv);
+ if (!addinput(*argv)) {
+ die("error: failed to open input file '%s': %s",
+ *argv, strerror(errno));
+ }
if (onlycpp) {
outcpp();
} else {
diff --git a/driver/posix/Makefile b/driver/posix/Makefile
@@ -7,7 +7,7 @@ OBJS = scc.o
all: scc
-$(OBJS): ../../inc/cc.h
+$(OBJS): ../../inc/cc.h ../../inc/arg.h
../../lib/libcc.a:
cd ../../lib && $(MAKE) -e
diff --git a/driver/posix/scc.c b/driver/posix/scc.c
@@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */
#define _POSIX_SOURCE
+#define _XOPEN_SOURCE 500
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -48,7 +49,9 @@ static struct tool {
};
char *argv0;
-static char *arch, *outfile;
+static char *arch, *objfile, *outfile;
+static char *tmpdir;
+static size_t tmpdirln;
static struct items objtmp, objout;
static int Eflag, Sflag, cflag, kflag, sflag;
@@ -134,30 +137,35 @@ inittool(int tool)
}
static char *
-outfilename(char *path, char *ext)
+outfname(char *path, char *type)
{
- char *new, *name, *dot;
- size_t newsz, nameln;
- int n;
-
- if (!(name = strrchr(path, '/')))
- name = path;
- else
- ++name;
-
- nameln = strlen(name);
-
- if (!(dot = strrchr(name, '.')))
- dot = &name[nameln];
-
- nameln = nameln - strlen(dot);
- newsz = nameln + strlen(ext) + 1 + 1;
+ char *new, sep, *p;
+ size_t newsz, pathln;
+ int tmpfd, n;
+
+ if (path) {
+ sep = '.';
+ if (p = strrchr(path, '/'))
+ path = p + 1;
+ pathln = strlen(path);
+ if (p = strrchr(path, '.'))
+ pathln -= strlen(p);
+ } else {
+ sep = '/';
+ type = "scc-XXXXXX";
+ path = tmpdir;
+ pathln = tmpdirln;
+ }
+ newsz = pathln + 1 + strlen(type) + 1;
new = xmalloc(newsz);
-
- n = snprintf(new, newsz, "%.*s.%s", nameln, name, ext);
+ n = snprintf(new, newsz, "%.*s%c%s", pathln, path, sep, type);
if (n < 0 || n >= newsz)
die("scc: wrong output filename");
+ if ((tmpfd = mkstemp(new)) < 0 && errno != EINVAL)
+ die("scc: could not create output file '%s': %s",
+ new, strerror(errno));
+ close(tmpfd);
return new;
}
@@ -172,27 +180,27 @@ settool(int tool, char *infile, int nexttool)
switch (tool) {
case TEEIR:
- t->outfile = outfilename(infile, "ir");
+ t->outfile = outfname(infile, "ir");
addarg(tool, t->outfile);
break;
case TEEQBE:
- t->outfile = outfilename(infile, "qbe");
+ t->outfile = outfname(infile, "qbe");
addarg(tool, t->outfile);
break;
case TEEAS:
- t->outfile = outfilename(infile, "as");
+ t->outfile = outfname(infile, "as");
addarg(tool, t->outfile);
break;
case AS:
- t->outfile = outfile ? outfile : outfilename(infile, "o");
+ if (cflag && outfile) {
+ objfile = outfile;
+ } else {
+ objfile = (cflag || kflag) ? infile : NULL;
+ objfile = outfname(objfile, "o");
+ }
+ t->outfile = xstrdup(objfile);
addarg(tool, t->outfile);
break;
- case LD:
- for (i = 0; i < objtmp.n; ++i)
- addarg(tool, xstrdup(objtmp.s[i]));
- for (i = 0; i < objout.n; ++i)
- addarg(tool, xstrdup(objout.s[i]));
- break;
case STRIP:
if (cflag || kflag) {
for (i = 0; i < objout.n; ++i)
@@ -298,16 +306,20 @@ validatetools(void)
t->pid = 0;
}
}
+ if (failed < LAST_TOOL) {
+ unlink(objfile);
+ free(objfile);
+ objfile = NULL;
+ return 0;
+ }
- return failed == LAST_TOOL;
+ return 1;
}
-static void
-build(char *file)
+static int
+buildfile(char *file, int tool)
{
- int tool = toolfor(file), nexttool;
- struct items *objs = (tool == LD || cflag || kflag) ?
- &objout : &objtmp;
+ int nexttool;
for (; tool < LAST_TOOL; tool = nexttool) {
switch (tool) {
@@ -346,8 +358,39 @@ build(char *file)
spawn(settool(inittool(tool), file, nexttool));
}
- if (validatetools())
- newitem(objs, outfilename(file, "o"));
+ return validatetools();
+}
+
+static void
+build(struct items *chain, int link)
+{
+ int i, tool;
+
+ if (link)
+ inittool(LD);
+
+ for (i = 0; i < chain->n; ++i) {
+ if (!strcmp(chain->s[i], "-l")) {
+ if (link) {
+ addarg(LD, xstrdup(chain->s[i++]));
+ addarg(LD, xstrdup(chain->s[i]));
+ } else {
+ ++i;
+ }
+ continue;
+ }
+ tool = toolfor(chain->s[i]);
+ if (tool == LD) {
+ if (link)
+ addarg(LD, xstrdup(chain->s[i]));
+ continue;
+ }
+ if (buildfile(chain->s[i], tool)) {
+ if (link)
+ addarg(LD, xstrdup(objfile));
+ newitem((!link || kflag) ? &objout : &objtmp, objfile);
+ }
+ }
}
static void
@@ -367,6 +410,9 @@ usage(void)
int
main(int argc, char *argv[])
{
+ struct items linkchain = { .n = 0, };
+ int link;
+
atexit(terminate);
arch = getenv("ARCH");
@@ -406,8 +452,8 @@ main(int argc, char *argv[])
kflag = 1;
break;
case 'l':
- addarg(LD, "-l");
- addarg(LD, EARGF(usage()));
+ newitem(&linkchain, "-l");
+ newitem(&linkchain, EARGF(usage()));
break;
case 'm':
arch = EARGF(usage());
@@ -427,19 +473,29 @@ main(int argc, char *argv[])
break;
default:
usage();
+ } ARGOPERAND {
+operand:
+ newitem(&linkchain, ARGOP());
} ARGEND
- if (Eflag && (Sflag || kflag) || argc > 1 && cflag && outfile || !argc)
+ for (; *argv; --argc, ++argv)
+ goto operand;
+
+ if (Eflag && (Sflag || kflag) || linkchain.n == 0 ||
+ linkchain.n > 1 && cflag && outfile)
usage();
- for (; *argv; ++argv)
- build(*argv);
+ if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
+ tmpdir = ".";
+ tmpdirln = strlen(tmpdir);
+
+ build(&linkchain, (link = !(Eflag || Sflag || cflag)));
- if (Eflag || Sflag)
+ if (!(link || cflag))
return failure;
- if (!cflag && !failure) {
- spawn(settool(inittool(LD), NULL, LAST_TOOL));
+ if (link && !failure) {
+ spawn(settool(LD, NULL, LAST_TOOL));
validatetools();
}
diff --git a/inc/arg.h b/inc/arg.h
@@ -9,57 +9,57 @@
extern char *argv0;
/* use main(int argc, char *argv[]) */
-#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
- argv[0] && argv[0][0] == '-'\
- && argv[0][1];\
- argc--, argv++) {\
- char argc_;\
- char **argv_;\
- int brk_;\
- if (argv[0][1] == '-' && argv[0][2] == '\0') {\
- argv++;\
- argc--;\
- break;\
- }\
- for (brk_ = 0, argv[0]++, argv_ = argv;\
- argv[0][0] && !brk_;\
- argv[0]++) {\
- if (argv_ != argv)\
- break;\
- argc_ = argv[0][0];\
- switch (argc_)
+#define ARGBEGIN \
+for (argv0 = *argv, argv++, argc--;\
+ argv[0];\
+ argc--, argv++) {\
+ if (argv[0][0] == '-') {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
-/* Handles obsolete -NUM syntax */
-#define ARGNUM case '0':\
- case '1':\
- case '2':\
- case '3':\
- case '4':\
- case '5':\
- case '6':\
- case '7':\
- case '8':\
- case '9'
+#define ARGOPERAND \
+ }\
+ } else if (argv[0][0] != '\0') {\
+ {
-#define ARGEND }\
- }
+#define ARGEND \
+ }\
+ }\
+}
-#define ARGC() argc_
+#define ARGC() argc_
-#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
+#define ARGOP() argv[0]
-#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
- ((x), abort(), (char *)0) :\
- (brk_ = 1, (argv[0][1] != '\0')?\
- (&argv[0][1]) :\
- (argc--, argv++, argv[0])))
+#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
-#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
- (char *)0 :\
- (brk_ = 1, (argv[0][1] != '\0')?\
- (&argv[0][1]) :\
- (argc--, argv++, argv[0])))
+#define EARGF(x) \
+((argv[0][1] == '\0' && argv[1] == NULL) ?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][1] != '\0') ?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
-#define LNGARG() &argv[0][0]
+#define ARGF() \
+((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define LNGARG() &argv[0][0]
#endif