commit b8e51de07999a695f7e66bcfa1b270e61896dd5d
parent 34f9e3e9ce1c23c5d0c4d8bf5a9728495604d629
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 6 Oct 2015 09:13:15 +0200
Merge remote-tracking branch 'origin/master'
Diffstat:
15 files changed, 381 insertions(+), 131 deletions(-)
diff --git a/cc1/Makefile b/cc1/Makefile
@@ -12,6 +12,9 @@ $(OBJS) : cc1.h ../inc/cc.h ../inc/sizes.h arch/$(ARCH)/arch.h
cc1: $(OBJS) ../lib/libcc.a
$(CC) $(LDFLAGS) $(OBJS) ../lib/libcc.a -o $@
+cpp: cc1
+ ln -f cc1 cpp
+
test:
cd tests && ./chktest.sh
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -46,6 +46,10 @@ struct limits {
} min;
};
+struct keyword {
+ char *str;
+ unsigned char token, value;
+};
struct type {
unsigned char op; /* type builder operator */
@@ -345,9 +349,9 @@ extern Symbol *nextsym(Symbol *sym, int ns);
extern Symbol *install(int ns, Symbol *sym);
extern Symbol *newsym(int ns);
extern void pushctx(void), popctx(void);
-extern void ikeywords(void);
-extern void delmacro(Symbol *sym);
+extern void killsym(Symbol *sym);
extern Symbol *newlabel(void);
+extern void keywords(struct keyword *key, int ns);
/* stmt.c */
extern void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
@@ -396,6 +400,8 @@ extern void icpp(void);
extern bool cpp(void);
extern bool expand(char *begin, Symbol *sym);
extern void incdir(char *dir);
+extern void outcpp(void);
+extern Symbol *defmacro(char *s);
/*
* Definition of global variables
@@ -407,7 +413,7 @@ extern unsigned short yylen;
extern int cppoff, disexpand;
extern unsigned cppctx;
extern Input *input;
-extern int lexmode, namespace;
+extern int lexmode, namespace, onlycpp;
extern unsigned curctx;
extern Symbol *curfun, *zero, *one;
diff --git a/cc1/cpp.c b/cc1/cpp.c
@@ -25,10 +25,23 @@ static char **dirinclude;
unsigned cppctx;
int disexpand;
-static Symbol *
+Symbol *
defmacro(char *s)
{
- return install(NS_CPP, lookup(NS_CPP, s));
+ char *p, *q;
+ Symbol *sym;
+ size_t len;
+
+ if ((p = strchr(s, '=')) != NULL) {
+ *p++='\0';
+ len = strlen(p);
+ q = xmalloc(len+4);
+ sprintf(q, "-1#%s", p);
+ p = q;
+ }
+ sym = install(NS_CPP, lookup(NS_CPP, s));
+ sym->u.s = p;
+ return sym;
}
void
@@ -37,12 +50,27 @@ icpp(void)
static char sdate[17], stime[14];
struct tm *tm;
time_t t;
- char **bp, *list[] = {
+ static char **bp, *list[] = {
"__STDC__",
"__STDC_HOSTED__",
"__SCC__",
NULL
};
+ static struct keyword keys[] = {
+ {"define", DEFINE, DEFINE},
+ {"include", INCLUDE, INCLUDE},
+ {"line", LINE, LINE},
+ {"ifdef", IFDEF, IFDEF},
+ {"if", IF, IF},
+ {"elif", ELIF, ELIF},
+ {"else", ELSE, ELSE},
+ {"ifndef", IFNDEF, IFNDEF},
+ {"endif", ENDIF, ENDIF},
+ {"undef", UNDEF, UNDEF},
+ {"pragma", PRAGMA, PRAGMA},
+ {"error", ERROR, ERROR},
+ {NULL, 0, 0}
+ };
t = time(NULL);
tm = localtime(&t);
@@ -57,6 +85,7 @@ icpp(void)
for (bp = list; *bp; ++bp)
defmacro(*bp)->u.s = "-1#1";
+ keywords(keys, NS_CPPCLAUSES);
}
static void
@@ -145,21 +174,39 @@ parsepars(char *buffer, char **listp, int nargs)
return 1;
}
+/* FIXME: characters in the definition break the macro definition */
static size_t
copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
{
- char prevc, c, *arg, *bp = buffer;
+ char prevc, c, *p, *arg, *bp = buffer;
+ size_t size;
for (prevc = '\0'; c = *s; prevc = c, ++s) {
if (c != '@') {
- if (c == '#')
+ switch (c) {
+ case '$':
+ while (bp[-1] == ' ')
+ --bp, ++bufsiz;
+ while (s[1] == ' ')
+ ++s;
+ case '#':
+ continue;
+ case '\"':
+ for (p = s; *++s != '"'; )
+ /* nothing */;
+ size = s - p + 1;
+ if (size > bufsiz)
+ goto expansion_too_long;
+ memcpy(bp, p, size);
+ bufsiz -= size;
+ bp += size;
continue;
+ // case '\'';
+ }
if (bufsiz-- == 0)
goto expansion_too_long;
*bp++ = c;
} else {
- size_t size;
-
if (prevc == '#')
bufsiz -= 2;
arg = arglist[atoi(++s)];
@@ -194,7 +241,9 @@ expand(char *begin, Symbol *sym)
char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[BUFSIZE];
macroname = sym->name;
- if (!(sym->flags & ISDECLARED)) {
+ if ((sym->flags & ISDECLARED) == 0) {
+ if (namespace == NS_CPP && !strcmp(sym->name, "defined"))
+ return 0; /* we found a 'defined in an #if */
/*
* This case happens in #if were macro not defined must
* be expanded to 0
@@ -216,12 +265,12 @@ expand(char *begin, Symbol *sym)
if (!parsepars(arguments, arglist, atoi(s)))
return 0;
for (n = 0; n < atoi(s); ++n)
- DBG("MACRO par%d:%s\n", n, arglist[n]);
+ DBG("MACRO par%d:%s", n, arglist[n]);
elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
substitute:
- DBG("MACRO '%s' expanded to :'%s'\n", macroname, buffer);
+ DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
rlen = strlen(input->p); /* rigth length */
llen = begin - input->line; /* left length */
ilen = input->p - begin; /* invocation length */
@@ -241,7 +290,7 @@ substitute:
input->p = input->begin = begin;
if (!(sym->flags & ISDECLARED))
- delmacro(sym);
+ killsym(sym);
return 1;
}
@@ -285,6 +334,11 @@ getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
size_t len;
int prevc = 0, ispar;
+ if (yytoken == '$') {
+ cpperror("'##' cannot appear at either end of a macro expansion");
+ return 0;
+ }
+
for (;;) {
ispar = 0;
if (yytoken == IDEN && nargs >= 0) {
@@ -308,10 +362,15 @@ getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
cpperror("too long macro");
return 0;
}
- memcpy(bp, yytext, len);
- bp += len;
- bufsiz -= len;
- if ((prevc = yytoken) != '#')
+ if (yytoken == '$') {
+ *bp++ = '$';
+ --bufsiz;
+ } else {
+ memcpy(bp, yytext, len);
+ bp += len;
+ bufsiz -= len;
+ }
+ if ((prevc = yytoken) != '#')
*bp++ = ' ';
next();
}
@@ -342,7 +401,7 @@ define(void)
free(sym->u.s);
} else {
sym = install(NS_CPP, sym);
- sym->flags |= ISDECLARED;
+ sym->flags |= ISDECLARED|ISSTRING;
}
namespace = NS_IDEN; /* Avoid polution in NS_CPP */
@@ -353,11 +412,11 @@ define(void)
if (!getdefs(args, n, buff+3, LINESIZ-3))
goto delete;
sym->u.s = xstrdup(buff);
- DBG("MACRO '%s' defined as '%s'\n", sym->name, buff);
+ DBG("MACRO '%s' defined as '%s'", sym->name, buff);
return;
delete:
- delmacro(sym);
+ killsym(sym);
}
void
@@ -531,7 +590,7 @@ ifclause(int negate, int isifdef)
next();
status = (sym->flags & ISDECLARED) != 0;
if (!status)
- delmacro(sym);
+ killsym(sym);
} else {
/* TODO: catch recovery here */
if ((expr = iconstexpr()) == NULL) {
@@ -589,6 +648,7 @@ static void
elif(void)
{
elseclause();
+ --cppctx;
cppif();
}
@@ -614,7 +674,7 @@ undef(void)
error("no macro name given in #undef directive");
return;
}
- delmacro(yylval.sym);
+ killsym(yylval.sym);
next();
}
@@ -670,3 +730,47 @@ cpp(void)
return 1;
}
+
+void
+outcpp(void)
+{
+ char c, *s, *t;
+
+ for (next(); yytoken != EOFTOK; next()) {
+ if (yytoken != CONSTANT || *yytext != '"') {
+ printf("%s ", yytext);
+ continue;
+ }
+ for (s = yylval.sym->u.s; c = *s; ++s) {
+ switch (c) {
+ case '\n':
+ t = "\\n";
+ goto print_str;
+ case '\v':
+ t = "\\v";
+ goto print_str;
+ case '\b':
+ t = "\\b";
+ goto print_str;
+ case '\t':
+ t = "\\t";
+ goto print_str;
+ case '\a':
+ t = "\\a";
+ print_str:
+ fputs(t, stdout);
+ break;
+ case '\\':
+ putchar('\\');
+ default:
+ if (!isprint(c))
+ printf("\\x%x", c);
+ else
+ putchar(c);
+ break;
+ }
+ }
+ }
+ putchar('\n');
+}
+
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -496,6 +496,32 @@ negation(char op, Node *np)
}
}
+static Symbol *
+notdefined(Symbol *sym)
+{
+ int isdef;
+
+ if (namespace == NS_CPP && !strcmp(sym->name, "defined")) {
+ disexpand = 1;
+ next();
+ expect('(');
+ sym = yylval.sym;
+ expect(IDEN);
+ expect(')');
+
+ isdef = (sym->flags & ISDECLARED) != 0;
+ sym = newsym(NS_IDEN);
+ sym->type = inttype;
+ sym->flags |= ISCONSTANT;
+ sym->u.i = isdef;
+ disexpand = 0;
+ return sym;
+ }
+ errorp("'%s' undeclared", yytext);
+ sym->type = inttype;
+ return install(sym->ns, yylval.sym);
+}
+
/*************************************************************
* grammar functions *
*************************************************************/
@@ -505,17 +531,18 @@ primary(void)
Node *np;
Symbol *sym;
+ sym = yylval.sym;
switch (yytoken) {
case CONSTANT:
- np = constnode(yylval.sym);
+ np = constnode(sym);
next();
break;
case IDEN:
- sym = yylval.sym;
- if ((sym->flags & ISDECLARED) == 0) {
- errorp("'%s' undeclared", yytext);
- sym->type = inttype;
- install(sym->ns, yylval.sym);
+ if ((sym->flags & ISDECLARED) == 0)
+ sym = notdefined(sym);
+ if (sym->flags & ISCONSTANT) {
+ np = constnode(sym);
+ break;
}
sym->flags |= ISUSED;
np = varnode(sym);
@@ -566,8 +593,6 @@ arguments(Node *np)
arg = convert(arg, doubletype, 1);
break;
}
- if (arg->type->op == INT)
- arg = promote(arg);
par = node(OPAR, arg->type, par, arg);
continue;
}
diff --git a/cc1/fold.c b/cc1/fold.c
@@ -480,6 +480,11 @@ change_to_comma:
return NULL;
}
+/*
+ * TODO: transform simplify in a recursivity
+ * function, because we are losing optimization
+ * chances
+ */
Node *
simplify(int op, Type *tp, Node *lp, Node *rp)
{
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -39,6 +39,44 @@ allocinput(char *fname, FILE *fp)
void
ilex(char *fname)
{
+ static struct keyword keys[] = {
+ {"auto", SCLASS, AUTO},
+ {"break", BREAK, BREAK},
+ {"_Bool", TYPE, BOOL},
+ {"case", CASE, CASE},
+ {"char", TYPE, CHAR},
+ {"const", TQUALIFIER, CONST},
+ {"continue", CONTINUE, CONTINUE},
+ {"default", DEFAULT, DEFAULT},
+ {"do", DO, DO},
+ {"double", TYPE, DOUBLE},
+ {"else", ELSE, ELSE},
+ {"enum", TYPE, ENUM},
+ {"extern", SCLASS, EXTERN},
+ {"float", TYPE, FLOAT},
+ {"for", FOR, FOR},
+ {"goto", GOTO, GOTO},
+ {"if", IF, IF},
+ {"inline", TQUALIFIER, INLINE},
+ {"int", TYPE, INT},
+ {"long", TYPE, LONG},
+ {"register", SCLASS, REGISTER},
+ {"restrict", TQUALIFIER, RESTRICT},
+ {"return", RETURN, RETURN},
+ {"short", TYPE, SHORT},
+ {"signed", TYPE, SIGNED},
+ {"sizeof", SIZEOF, SIZEOF},
+ {"static", SCLASS, STATIC},
+ {"struct", TYPE, STRUCT},
+ {"switch", SWITCH, SWITCH},
+ {"typedef", SCLASS, TYPEDEF},
+ {"union", TYPE, UNION},
+ {"unsigned", TYPE, UNSIGNED},
+ {"void", TYPE, VOID},
+ {"volatile", TQUALIFIER, VOLATILE},
+ {"while", WHILE, WHILE},
+ {NULL, 0, 0},
+ };
FILE *fp;
if (!fname) {
@@ -52,6 +90,7 @@ ilex(char *fname)
}
allocinput(fname, fp);
*input->begin = '\0';
+ keywords(keys, NS_KEYWORD);
}
bool
@@ -176,6 +215,10 @@ repeat:
bool
moreinput(void)
{
+ static char file[FILENAME_MAX];
+ static unsigned nline;
+ char *s;
+
repeat:
if (!readline())
return 0;
@@ -187,6 +230,19 @@ repeat:
goto repeat;
}
+ if (onlycpp) {
+ putchar('\n');
+ if (strcmp(file, input->fname)) {
+ strcpy(file, input->fname);
+ s = "#line %u %s\n";
+ } else if (nline+1 != input->nline) {
+ s = "#line %u\n";
+ } else {
+ s = "";
+ }
+ nline = input->nline;
+ printf(s, nline, file);
+ }
input->begin = input->p;
return 1;
}
@@ -525,6 +581,7 @@ operator(void)
case '*': t = follow('=', MUL_EQ, '*'); break;
case '/': t = follow('=', DIV_EQ, '/'); break;
case '!': t = follow('=', NE, '!'); break;
+ case '#': t = follow('#', '$', '#'); break;
case '-': t = minus(); break;
case '+': t = plus(); break;
case '.': t = dot(); break;
@@ -576,7 +633,7 @@ next(void)
yytoken = operator();
exit:
- DBG("TOKEN %s\n", yytext);
+ DBG("TOKEN %s", yytext);
return yytoken;
}
diff --git a/cc1/main.c b/cc1/main.c
@@ -12,8 +12,8 @@
int warnings;
jmp_buf recover;
-static char *output;
-static int onlycpp;
+static char *output, *arg0;
+int onlycpp;
static void
clean(void)
@@ -27,7 +27,9 @@ clean(void)
static void
usage(void)
{
- fputs("usage: cc1 [-w] [-o output] [input]\n", stderr);
+ fprintf(stderr,
+ "usage: %s [-E] [-Dmacro[=value]] [-Idir] [-w] [-d] [-o output] [input]\n",
+ arg0);
exit(1);
}
@@ -38,6 +40,10 @@ main(int argc, char *argv[])
atexit(clean);
+ arg0 = (cp = strrchr(*argv, '/')) ? cp+1 : *argv;
+ if (!strcmp(arg0, "cpp"))
+ onlycpp = 1;
+
for (;;) {
nextiter:
--argc, ++argv;
@@ -51,6 +57,12 @@ main(int argc, char *argv[])
case 'E':
onlycpp = 1;
break;
+ case 'D':
+ defmacro(cp+1);
+ goto nextiter;
+ case 'd':
+ DBGON();
+ break;
case 'I':
incdir(cp+1);
goto nextiter;
@@ -72,12 +84,10 @@ main(int argc, char *argv[])
usage();
icpp();
- ikeywords();
ilex(*argv);
if (onlycpp) {
- for (next(); yytoken != EOFTOK; next())
- printf("%s ", yytext);
+ outcpp();
} else {
for (next(); yytoken != EOFTOK; decl())
/* nothing */;
diff --git a/cc1/symbol.c b/cc1/symbol.c
@@ -76,7 +76,7 @@ pushctx(void)
error("too much nested blocks");
}
-static void
+void
killsym(Symbol *sym)
{
short f;
@@ -87,14 +87,14 @@ killsym(Symbol *sym)
free(sym->u.s);
if (sym->ns == NS_TAG)
sym->type->defined = 0;
- if ((name = sym->name) != NULL) {
- unlinkhash(sym);
+ unlinkhash(sym);
+ if ((name = sym->name) != NULL && sym->ns != NS_CPP) {
if ((f & (ISUSED|ISGLOBAL|ISDECLARED)) == ISDECLARED)
warn("'%s' defined but not used", name);
if ((f & ISDEFINED) == 0 && sym->ns == NS_LABEL)
errorp("label '%s' is not defined", name);
- free(name);
}
+ free(name);
free(sym);
}
@@ -168,7 +168,6 @@ linksym(Symbol *sym)
{
Symbol *p, *prev;
- sym->flags |= ISDECLARED;
switch (sym->ns) {
case NS_CPP:
return sym;
@@ -198,7 +197,6 @@ linkhash(Symbol *sym)
Symbol **h, *p, *prev;
h = &htab[hash(sym->name)];
-
for (prev = p = *h; p; prev = p, p = p->hash) {
if (p->ctx <= sym->ctx)
break;
@@ -214,16 +212,14 @@ linkhash(Symbol *sym)
if (sym->ns != NS_CPP)
sym->id = newid();
+ sym->flags |= ISDECLARED;
return linksym(sym);
}
Symbol *
newsym(int ns)
{
- Symbol *sym;
-
- sym = linksym(allocsym(ns, NULL));
- return sym;
+ return linksym(allocsym(ns, NULL));
}
Symbol *
@@ -253,15 +249,6 @@ lookup(int ns, char *name)
return allocsym(ns, name);
}
-void
-delmacro(Symbol *sym)
-{
- unlinkhash(sym);
- free(sym->name);
- free(sym->u.s);
- free(sym);
-}
-
Symbol *
nextsym(Symbol *sym, int ns)
{
@@ -296,77 +283,14 @@ install(int ns, Symbol *sym)
}
void
-ikeywords(void)
+keywords(struct keyword *key, int ns)
{
- static struct {
- char *str;
- unsigned char token, value;
- } *bp, keywords[] = {
- {"auto", SCLASS, AUTO},
- {"break", BREAK, BREAK},
- {"_Bool", TYPE, BOOL},
- {"case", CASE, CASE},
- {"char", TYPE, CHAR},
- {"const", TQUALIFIER, CONST},
- {"continue", CONTINUE, CONTINUE},
- {"default", DEFAULT, DEFAULT},
- {"do", DO, DO},
- {"double", TYPE, DOUBLE},
- {"else", ELSE, ELSE},
- {"enum", TYPE, ENUM},
- {"extern", SCLASS, EXTERN},
- {"float", TYPE, FLOAT},
- {"for", FOR, FOR},
- {"goto", GOTO, GOTO},
- {"if", IF, IF},
- {"inline", TQUALIFIER, INLINE},
- {"int", TYPE, INT},
- {"long", TYPE, LONG},
- {"register", SCLASS, REGISTER},
- {"restrict", TQUALIFIER, RESTRICT},
- {"return", RETURN, RETURN},
- {"short", TYPE, SHORT},
- {"signed", TYPE, SIGNED},
- {"sizeof", SIZEOF, SIZEOF},
- {"static", SCLASS, STATIC},
- {"struct", TYPE, STRUCT},
- {"switch", SWITCH, SWITCH},
- {"typedef", SCLASS, TYPEDEF},
- {"union", TYPE, UNION},
- {"unsigned", TYPE, UNSIGNED},
- {"void", TYPE, VOID},
- {"volatile", TQUALIFIER, VOLATILE},
- {"while", WHILE, WHILE},
- {NULL, 0, 0},
- }, cppclauses[] = {
- {"define", DEFINE, DEFINE},
- {"include", INCLUDE, INCLUDE},
- {"line", LINE, LINE},
- {"ifdef", IFDEF, IFDEF},
- {"if", IF, IF},
- {"elif", ELIF, ELIF},
- {"else", ELSE, ELSE},
- {"ifndef", IFNDEF, IFNDEF},
- {"endif", ENDIF, ENDIF},
- {"undef", UNDEF, UNDEF},
- {"pragma", PRAGMA, PRAGMA},
- {"error", ERROR, ERROR},
- {NULL, 0, 0}
- }, *list[] = {
- keywords,
- cppclauses,
- NULL
- }, **lp;
Symbol *sym;
- int ns = NS_KEYWORD;
- for (lp = list; *lp; ++lp) {
- for (bp = *lp; bp->str; ++bp) {
- sym = linkhash(allocsym(ns, bp->str));
- sym->token = bp->token;
- sym->u.token = bp->value;
- }
- ns = NS_CPPCLAUSES;
+ for ( ; key->str; ++key) {
+ sym = linkhash(allocsym(ns, key->str));
+ sym->token = key->token;
+ sym->u.token = key->value;
}
/*
* Remove all the predefined symbols from * the symbol list. It
diff --git a/cc1/tests/test031.c b/cc1/tests/test031.c
@@ -0,0 +1,33 @@
+
+/*
+name: TEST031
+description: Test concatenation in preprocessor
+output:
+F5 I
+G6 F5 main
+{
+\
+A7 I foo
+A8 I bar
+A9 I foobar
+ A9 A7 A8 +I :I
+ A9 A7 A8 +I :I
+ r #I0
+}
+*/
+
+#define CAT(x,y) x ## y
+#define XCAT(x,y) CAT(x,y)
+#define FOO foo
+#define BAR bar
+
+int
+main(void)
+{
+ int foo, bar, foobar;
+
+ CAT(foo,bar) = foo + bar;
+ XCAT(FOO,BAR) = foo + bar;
+ return 0;
+}
+
diff --git a/cc1/tests/test032.c b/cc1/tests/test032.c
@@ -0,0 +1,25 @@
+
+/*
+name: TEST032
+description: test special characters @ and $ in macro definitions
+output:
+F3 I
+G4 F3 main
+{
+\
+A6 P p
+ A6 "54686973206973206120737472696E672024206F722023206F72202323616E64206974206973206F6B2021 'P :P
+ r A6 #P0 !I
+}
+*/
+
+#define M1(x) "This is a string $ or # or ##" ## #x
+
+int
+main(void)
+{
+ char *p = M1(and it is ok!);
+
+ return p != 0;
+}
+
diff --git a/cc1/tests/test033.c b/cc1/tests/test033.c
@@ -0,0 +1,17 @@
+/*
+name: TEST033
+description: test for #if defined()
+output:
+G1 I c
+*/
+
+#if defined(FOO)
+int a;
+#elif !defined(FOO) && defined(BAR)
+int b;
+#elif !defined(FOO) && !defined(BAR)
+int c;
+#else
+int d;
+#endif
+
diff --git a/cc1/tests/update.sh b/cc1/tests/update.sh
@@ -1,8 +1,26 @@
#!/bin/sh
+update()
+{
+ (echo '/^output/+;/^\*\//-c'
+ ../cc1 -I./ -w $1 2>&1
+ printf ".\nw\n") | ed -s $1
+}
+
+
+case $# in
+1)
+ update $1
+ exit
+ ;;
+*)
+ echo "usage: update.sh [test]" >&2
+ exit 1
+ ;;
+esac
+
+
for i in *.c
do
- (echo '/^output/+;/^\*\//-c'
- ../cc1 -w $i 2>&1
- printf ".\nw\n") | ed -s $i
+ update $i
done
diff --git a/inc/cc.h b/inc/cc.h
@@ -8,9 +8,12 @@ typedef unsigned bool;
#endif
#ifndef NDEBUG
-#define DBG(...) fprintf(stderr, __VA_ARGS__)
+extern int debug;
+#define DBG(fmt, ...) dbg(fmt, __VA_ARGS__)
+#define DBGON() (debug = 1)
#else
#define DBG(...)
+#define DBGON()
#endif
#define L_INT8 'C'
@@ -39,8 +42,8 @@ typedef unsigned bool;
#define L_EXTERN 'X'
extern void die(const char *fmt, ...);
+extern void dbg(const char *fmt, ...);
extern void *xmalloc(size_t size);
extern void *xcalloc(size_t nmemb, size_t size);
extern char *xstrdup(const char *s);
extern void *xrealloc(void *buff, register size_t size);
-
diff --git a/lib/Makefile b/lib/Makefile
@@ -1,6 +1,6 @@
include ../config.mk
-OBJS = die.o xcalloc.o xmalloc.o xrealloc.o xstrdup.o
+OBJS = die.o xcalloc.o xmalloc.o xrealloc.o xstrdup.o debug.o
all: libcc.a
diff --git a/lib/debug.c b/lib/debug.c
@@ -0,0 +1,20 @@
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "../inc/cc.h"
+
+int debug;
+
+void
+dbg(const char *fmt, ...)
+{
+ if (!debug)
+ return;
+ va_list va;
+ va_start(va, fmt);
+ vfprintf(stderr, fmt, va);
+ putc('\n', stderr);
+ va_end(va);
+ return;
+}