1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
|
/*
\funcref{directive}{void directive()}
{}
{}
{error(), pushfile(), insert()}
{lexer()}
{directiv.c}
{
{\em directive()} is called from {\em lexer()} when a `\#' character is
read in the input file. {\em directive()} does not expect to read the
`\#' character. Three directives are recognized:
\begin{itemize}
\item {\bf \#} {\em[spaces]} {\bf include} {\em[spaces]} {\bf
"}{\em filename}{\bf "}. When this directive is read, {\em
pushfile()} is called to start processing the included file.
Analogous to {\bf C}, an {\bf \#include} $<$...$>$ form is
supported.
\item {\bf \#} {\em[spaces]} {\bf define} {\em[spaces]} {\em name}
{\em[spaces]} {\em[redefinition]}. When this directive is read,
{\em insert()} is called to insert the definition in the symbol
table. The defined {\em name} is passed to {\em insert()} as
argument; the redefinition is stored in the lexical buffer {\em
lexbuf}.
\item {\bf \#\!} \ldots
The line containing this directive is skipped. The directive is
intended to be used on {\sc unix} platforms, where it can be used
to execute an icmake script.
\end{itemize}
Other directives following the `\#' character lead to an error.
}
*/
#include "icm-pp.h"
static int isdefd(STRING_ *str)
{
register int i;
register char *id = str->data;
return (i = finddef(id)) >= 0 && strcmp(defined[i].redef, "0");
}
static int skipline(void)
{
register int ch = 0;
while (1)
{
register int previous = ch;
ch = nextchar();
if (ch == '\n')
{
if (previous == '\\')
continue;
pushback('\n'); /* push back the last char */
return '\n';
}
if (ch == EOF)
return EOF;
}
}
static void terminate_line(char const *what)
{
if (skipline() == EOF)
error("%s: #%s at end-of-file", filestack[filesp].n, what);
}
static void fill_line(void)
{
register int ch;
/* read the line-remainder */
lexbuf.len = 0;
while (1)
{
while ((ch = nextchar()) != '\n' && ch != EOF)
string_append(&lexbuf, ch);
if (!string_continue(&lexbuf))
break;
}
string_append(&lexbuf, 0);
pushback(ch);
}
void include_directive(void)
{
register int ch;
register int imdir_used = 0; /* assume include "..." form */
skipblanks();
ch = nextchar();
if (ch != '\"' && ch != '<')
error("%s: %d: \" or < expected after #include directive",
filestack[filesp].n, filestack[filesp].l);
if (ch == '<') /* include <...> form? */
imdir_used++;
lexbuf.len = 0;
while ( (ch = nextchar()) != '\"' && ch != '>')
if (ch == '\n' || ch == EOF)
error("%s: %d: unterminated name after #include directive",
filestack[filesp].n, filestack[filesp].l);
else
string_append(&lexbuf, ch);
string_append(&lexbuf, 0);
skipline();
if (output_active)
{
if (imdir_used)
{
static char dirsep[2] = { DIRSEP, '\0' };
char filename[_MAX_PATH];
char *im = xstrdup(imdir);
char *path = strtok(im, ":"); /* get the first path element */
while (path)
{
strcpy(filename, path);
strcat(filename, dirsep);
strcat(filename, lexbuf.data);
if (access(filename, R_OK) == 0)
{
pushfile(filename);
break;
}
path = strtok(0, ":");
}
free(im);
if (!path)
error("cannot find `%s' in `%s'", lexbuf, imdir);
}
else
pushfile(lexbuf.data);
}
}
static STRING_ idname = {0, 0, NULL};
static void define_directive(void)
{
getident(&idname); /* get the name of the define */
skipblanks(); /* skip blanks again */
fill_line();
no_comment(); /* remove comment from lexbuf */
if (output_active)
insert(idname.data);
}
static void undef_directive(void)
{
getident(&idname); /* symbol to undef */
terminate_line("undef");
if (output_active)
undef(idname.data);
}
static void ifndef_directive(void)
{
getident(&idname); /* get the name of the define */
terminate_line("ifndef");
output_active = push_active(!isdefd(&idname));
}
static void ifdef_directive(void)
{
getident(&idname); /* get the name of the define */
terminate_line("ifdef");
output_active = push_active(isdefd(&idname));
}
static void else_directive(void)
{
terminate_line("else");
output_active = negate_active();
}
static void endif_directive(void)
{
terminate_line("endif");
output_active = pop_active();
}
void directive(void)
{
register int ch;
/* directive is #! */
if ((ch = nextchar()) == '!')
{ /* skip while not \n and not EOF */
skipline();
return; /* all done here */
}
pushback(ch); /* push back the first char which may */
/* be a blank or the first char of a */
/* directive */
getident(&lexbuf);
if (!strncmp(lexbuf.data, "include", 7))
include_directive();
else if (!strncmp(lexbuf.data, "define", 6))
define_directive();
else if (!strncmp(lexbuf.data, "undef", 5))
undef_directive();
else if (!strncmp(lexbuf.data, "ifndef", 6))
ifndef_directive();
else if (!strncmp(lexbuf.data, "ifdef", 5))
ifdef_directive();
else if (!strncmp(lexbuf.data, "else", 4))
else_directive();
else if (!strncmp(lexbuf.data, "endif", 5))
endif_directive();
else
error("%s: %d: bad preprocessor directive `%s'",
filestack[filesp].n, filestack[filesp].l, &lexbuf.data);
}
|