summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorragge <ragge>2009-12-31 11:46:13 +0000
committerragge <ragge>2009-12-31 11:46:13 +0000
commitc0199e5a6297875646a8ada4f9cf169634e9e1bb (patch)
tree930e8808674bf2f43ae29814cb7c5a4b49df2bdb
parent6c327e7cf3d36a5cbba11b352857025c544deb91 (diff)
Understand gcc directive #include_next. Solves Jira#PCC-106 by Altamiranus.
-rw-r--r--cpp.c60
-rw-r--r--cpp.h5
-rw-r--r--token.c13
3 files changed, 59 insertions, 19 deletions
diff --git a/cpp.c b/cpp.c
index 92ac324..aac6129 100644
--- a/cpp.c
+++ b/cpp.c
@@ -171,6 +171,7 @@ static void expdef(usch *proto, struct recur *, int gotwarn);
void define(void);
static int canexpand(struct recur *, struct symtab *np);
void include(void);
+void include_next(void);
void line(void);
void flbuf(void);
void usage(void);
@@ -185,6 +186,7 @@ main(int argc, char **argv)
struct incs *w, *w2;
struct symtab *nl;
register int ch;
+ usch *fn1, *fn2;
#ifdef TIMING
struct timeval t1, t2;
@@ -316,7 +318,13 @@ main(int argc, char **argv)
ofd = 1; /* stdout */
istty = isatty(ofd);
- if (pushfile((usch *)(argc && strcmp(argv[0], "-") ? argv[0] : NULL)))
+ if (argc && strcmp(argv[0], "-")) {
+ fn1 = fn2 = (usch *)argv[0];
+ } else {
+ fn1 = NULL;
+ fn2 = (usch *)"";
+ }
+ if (pushfile(fn1, fn2, 0, NULL))
error("cannot open %s", argv[0]);
flbuf();
@@ -485,6 +493,31 @@ bad: error("bad line directive");
}
/*
+ * Search for and include next file.
+ * Return 1 on success.
+ */
+static int
+fsrch(usch *fn, int idx, struct incs *w)
+{
+ int i;
+
+ for (i = idx; i < 2; i++) {
+ if (i > idx)
+ w = incdir[i];
+ for (; w; w = w->next) {
+ usch *nm = stringbuf;
+
+ savstr(w->dir); savch('/');
+ savstr(fn); savch(0);
+ if (pushfile(nm, fn, i, w->next) == 0)
+ return 1;
+ stringbuf = nm;
+ }
+ }
+ return 0;
+}
+
+/*
* Include a file. Include order:
* - For <...> files, first search -I directories, then system directories.
* - For "..." files, first search "current" dir, then as <...> files.
@@ -493,10 +526,9 @@ void
include()
{
struct symtab *nl;
- struct incs *w;
usch *osp;
usch *fn, *safefn;
- int i, c, it;
+ int c, it;
if (flslvl)
return;
@@ -549,23 +581,14 @@ include()
c = yylex();
if (c != '\n')
goto bad;
- if (pushfile(nm) == 0)
+ if (pushfile(nm, safefn, 0, NULL) == 0)
goto okret;
/* XXX may loose stringbuf space */
}
- /* create search path and try to open file */
- for (i = 0; i < 2; i++) {
- for (w = incdir[i]; w; w = w->next) {
- usch *nm = stringbuf;
+ if (fsrch(safefn, 0, incdir[0]))
+ goto okret;
- savstr(w->dir); savch('/');
- savstr(safefn); savch(0);
- if (pushfile(nm) == 0)
- goto okret;
- stringbuf = nm;
- }
- }
error("cannot find '%s'", safefn);
/* error() do not return */
@@ -575,6 +598,13 @@ okret:
prtline();
}
+void
+include_next()
+{
+ if (fsrch(ifiles->fn, ifiles->idx, ifiles->incs) == 0)
+ error("cannot find '%s'", ifiles->fn);
+}
+
static int
definp(void)
{
diff --git a/cpp.h b/cpp.h
index fd62803..2b3ad22 100644
--- a/cpp.h
+++ b/cpp.h
@@ -78,6 +78,9 @@ struct includ {
usch *maxread;
usch *ostr;
usch *buffer;
+ int idx;
+ void *incs;
+ usch *fn;
usch bbuf[NAMEMAX+CPPBUF+1];
} *ifiles;
@@ -118,7 +121,7 @@ struct symtab *lookup(usch *namep, int enterf);
usch *gotident(struct symtab *nl);
int slow; /* scan slowly for new tokens */
-int pushfile(usch *fname);
+int pushfile(usch *fname, usch *fn, int idx, void *incs);
void popfile(void);
void prtline(void);
int yylex(void);
diff --git a/token.c b/token.c
index 3201cc0..f377be9 100644
--- a/token.c
+++ b/token.c
@@ -71,6 +71,7 @@ static void badop(const char *);
static int chktg(void);
static void ppdir(void);
void include(void);
+void include_next(void);
void define(void);
static int inpch(void);
@@ -672,7 +673,7 @@ prinit(struct initar *it, struct includ *ic)
* Return 0 on success, -1 if file to be included is not found.
*/
int
-pushfile(usch *file)
+pushfile(usch *file, usch *fn, int idx, void *incs)
{
extern struct initar *initar;
struct includ ibuf;
@@ -697,6 +698,9 @@ pushfile(usch *file)
ifiles = ic;
ic->lineno = 1;
ic->maxread = ic->curptr;
+ ic->idx = idx;
+ ic->incs = incs;
+ ic->fn = fn;
prtline();
if (initar) {
*ic->maxread = 0;
@@ -1117,6 +1121,9 @@ static struct {
{ "line", line },
{ "pragma", pragmastmt },
{ "elif", elifstmt },
+#ifdef GCC_COMPAT
+ { "include_next", include_next },
+#endif
};
/*
@@ -1125,7 +1132,7 @@ static struct {
void
ppdir(void)
{
- char bp[10];
+ char bp[20];
int ch, i;
while ((ch = inch()) == ' ' || ch == '\t')
@@ -1138,7 +1145,7 @@ ppdir(void)
if (i == sizeof(bp)-1)
goto out; /* too long */
ch = inch();
- } while (ch >= 'a' && ch <= 'z');
+ } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
unch(ch);
bp[i++] = 0;