23 |
#include "m4.h" |
#include "m4.h" |
24 |
#include "m4private.h" |
#include "m4private.h" |
25 |
|
|
26 |
static void expand_macro (const char *name, m4_symbol *token); |
static void expand_macro (const char *name, m4_symbol *); |
27 |
static void expand_token (struct obstack *, m4_token_t t, m4_symbol *token); |
static void expand_token (struct obstack *, m4_token_t, m4_token_data *); |
28 |
|
|
29 |
/* Current recursion level in expand_macro (). */ |
/* Current recursion level in expand_macro (). */ |
30 |
int m4_expansion_level = 0; |
int m4_expansion_level = 0; |
37 |
m4_expand_input (void) |
m4_expand_input (void) |
38 |
{ |
{ |
39 |
m4_token_t t; |
m4_token_t t; |
40 |
m4_symbol tokenbuf; |
m4_token_data td; |
41 |
|
|
42 |
while ((t = m4_next_token (&tokenbuf)) != M4_TOKEN_EOF) |
while ((t = m4_next_token (&td)) != M4_TOKEN_EOF) |
43 |
expand_token ((struct obstack *) NULL, t, &tokenbuf); |
expand_token ((struct obstack *) NULL, t, &td); |
44 |
} |
} |
45 |
|
|
46 |
|
|
49 |
macro definition. If they have, they are expanded as macros, otherwise |
macro definition. If they have, they are expanded as macros, otherwise |
50 |
the text are just copied to the output. */ |
the text are just copied to the output. */ |
51 |
static void |
static void |
52 |
expand_token (struct obstack *obs, m4_token_t t, m4_symbol *token) |
expand_token (struct obstack *obs, m4_token_t t, m4_token_data *td) |
53 |
{ |
{ |
54 |
m4_symbol *symbol; |
m4_symbol *symbol; |
55 |
char *text = xstrdup (M4_SYMBOL_TEXT (token)); |
char *text = xstrdup (M4_TOKEN_DATA_TEXT (td)); |
56 |
|
|
57 |
switch (t) |
switch (t) |
58 |
{ /* TOKSW */ |
{ /* TOKSW */ |
79 |
&& M4_SYMBOL_BLIND_NO_ARGS (symbol) |
&& M4_SYMBOL_BLIND_NO_ARGS (symbol) |
80 |
&& !M4_IS_OPEN(m4_peek_input ()))) |
&& !M4_IS_OPEN(m4_peek_input ()))) |
81 |
{ |
{ |
82 |
m4_shipout_text (obs, M4_SYMBOL_TEXT (token), |
m4_shipout_text (obs, M4_TOKEN_DATA_TEXT (td), |
83 |
strlen (M4_SYMBOL_TEXT (token))); |
strlen (M4_TOKEN_DATA_TEXT (td))); |
84 |
} |
} |
85 |
else |
else |
86 |
expand_macro (p, symbol); |
expand_macro (p, symbol); |
95 |
|
|
96 |
XFREE (text); |
XFREE (text); |
97 |
} |
} |
|
|
|
|
|
|
98 |
|
|
99 |
|
|
100 |
/* This function parses one argument to a macro call. It expects the first |
/* This function parses one argument to a macro call. It expects the first |
101 |
left parenthesis, or the separating comma to have been read by the |
left parenthesis, or the separating comma to have been read by the |
102 |
caller. It skips leading whitespace, and reads and expands tokens, |
caller. It skips leading whitespace, and reads and expands tokens, |
105 |
the last for the active macro call. The argument are build on the |
the last for the active macro call. The argument are build on the |
106 |
obstack OBS, indirectly through expand_token (). */ |
obstack OBS, indirectly through expand_token (). */ |
107 |
static boolean |
static boolean |
108 |
expand_argument (struct obstack *obs, m4_symbol *argp) |
expand_argument (struct obstack *obs, m4_token_data *argp) |
109 |
{ |
{ |
110 |
m4_token_t t; |
m4_token_t t; |
111 |
m4_symbol tokenbuf; |
m4_token_data td; |
112 |
char *text; |
char *text; |
113 |
int paren_level; |
int paren_level; |
114 |
|
|
115 |
M4_SYMBOL_TYPE (argp) = M4_TOKEN_VOID; |
M4_TOKEN_DATA_TYPE (argp) = M4_TOKEN_VOID; |
116 |
|
|
117 |
/* Skip leading white space. */ |
/* Skip leading white space. */ |
118 |
do |
do |
119 |
{ |
{ |
120 |
t = m4_next_token (&tokenbuf); |
t = m4_next_token (&td); |
121 |
} |
} |
122 |
while (t == M4_TOKEN_SPACE); |
while (t == M4_TOKEN_SPACE); |
123 |
|
|
125 |
|
|
126 |
while (1) |
while (1) |
127 |
{ |
{ |
128 |
|
|
129 |
switch (t) |
switch (t) |
130 |
{ /* TOKSW */ |
{ /* TOKSW */ |
131 |
case M4_TOKEN_SIMPLE: |
case M4_TOKEN_SIMPLE: |
132 |
text = M4_SYMBOL_TEXT (&tokenbuf); |
text = M4_TOKEN_DATA_TEXT (&td); |
133 |
if ((M4_IS_COMMA (*text) || M4_IS_CLOSE (*text)) && paren_level == 0) |
if ((M4_IS_COMMA(*text) || M4_IS_CLOSE(*text)) && paren_level == 0) |
134 |
{ |
{ |
135 |
|
|
136 |
/* The argument MUST be finished, whether we want it or not. */ |
/* The argument MUST be finished, whether we want it or not. */ |
137 |
obstack_1grow (obs, '\0'); |
obstack_1grow (obs, '\0'); |
138 |
text = obstack_finish (obs); |
text = obstack_finish (obs); |
139 |
|
|
140 |
if (M4_SYMBOL_TYPE (argp) == M4_TOKEN_VOID) |
if (M4_TOKEN_DATA_TYPE (argp) == M4_TOKEN_VOID) |
141 |
{ |
{ |
142 |
M4_SYMBOL_TYPE (argp) = M4_TOKEN_TEXT; |
M4_TOKEN_DATA_TYPE (argp) = M4_TOKEN_TEXT; |
143 |
M4_SYMBOL_TEXT (argp) = text; |
M4_TOKEN_DATA_TEXT (argp) = text; |
144 |
} |
} |
145 |
return (boolean) (M4_IS_COMMA (*M4_SYMBOL_TEXT (&tokenbuf))); |
return (boolean) (M4_IS_COMMA(*M4_TOKEN_DATA_TEXT (&td))); |
146 |
} |
} |
147 |
|
|
148 |
if (M4_IS_OPEN(*text)) |
if (M4_IS_OPEN(*text)) |
149 |
paren_level++; |
paren_level++; |
150 |
else if (M4_IS_CLOSE(*text)) |
else if (M4_IS_CLOSE(*text)) |
151 |
paren_level--; |
paren_level--; |
152 |
expand_token (obs, t, &tokenbuf); |
expand_token (obs, t, &td); |
153 |
break; |
break; |
154 |
|
|
155 |
case M4_TOKEN_EOF: |
case M4_TOKEN_EOF: |
160 |
case M4_TOKEN_WORD: |
case M4_TOKEN_WORD: |
161 |
case M4_TOKEN_SPACE: |
case M4_TOKEN_SPACE: |
162 |
case M4_TOKEN_STRING: |
case M4_TOKEN_STRING: |
163 |
expand_token (obs, t, &tokenbuf); |
expand_token (obs, t, &td); |
164 |
break; |
break; |
165 |
|
|
166 |
case M4_TOKEN_MACDEF: |
case M4_TOKEN_MACDEF: |
167 |
if (obstack_object_size (obs) == 0) |
if (obstack_object_size (obs) == 0) |
168 |
{ |
{ |
169 |
M4_SYMBOL_TYPE (argp) = M4_TOKEN_FUNC; |
M4_TOKEN_DATA_TYPE (argp) = M4_TOKEN_FUNC; |
170 |
M4_SYMBOL_HANDLE (argp) = M4_SYMBOL_HANDLE (&tokenbuf); |
M4_TOKEN_DATA_HANDLE (argp) = M4_TOKEN_DATA_HANDLE (&td); |
171 |
M4_SYMBOL_FUNC (argp) = M4_SYMBOL_FUNC (&tokenbuf); |
M4_TOKEN_DATA_FUNC (argp) = M4_TOKEN_DATA_FUNC (&td); |
172 |
M4_SYMBOL_TRACED (argp) = M4_SYMBOL_TRACED (&tokenbuf); |
M4_TOKEN_TRACED (argp) = M4_TOKEN_TRACED (&td); |
173 |
} |
} |
174 |
break; |
break; |
175 |
|
|
179 |
abort (); |
abort (); |
180 |
} |
} |
181 |
|
|
182 |
t = m4_next_token (&tokenbuf); |
t = m4_next_token (&td); |
183 |
} |
} |
184 |
} |
} |
185 |
|
|
191 |
struct obstack *argptr, struct obstack *arguments) |
struct obstack *argptr, struct obstack *arguments) |
192 |
{ |
{ |
193 |
int ch; /* lookahead for ( */ |
int ch; /* lookahead for ( */ |
194 |
m4_symbol tokenbuf; |
m4_token_data td; |
195 |
m4_symbol *token; |
m4_token_data *tdp; |
196 |
boolean more_args; |
boolean more_args; |
197 |
boolean groks_macro_args = M4_SYMBOL_MACRO_ARGS (symbol); |
boolean groks_macro_args = M4_SYMBOL_MACRO_ARGS (symbol); |
198 |
|
|
199 |
M4_SYMBOL_TYPE (&tokenbuf) = M4_TOKEN_TEXT; |
M4_TOKEN_DATA_TYPE (&td) = M4_TOKEN_TEXT; |
200 |
M4_SYMBOL_TEXT (&tokenbuf) = (char *) name; |
M4_TOKEN_DATA_TEXT (&td) = (char *) name; |
201 |
token = (m4_symbol *) obstack_copy (arguments, (void *) &tokenbuf, sizeof (tokenbuf)); |
tdp = (m4_token_data *) obstack_copy (arguments, (void *) &td, sizeof (td)); |
202 |
obstack_grow (argptr, (void *) &token, sizeof (token)); |
obstack_grow (argptr, (void *) &tdp, sizeof (tdp)); |
203 |
|
|
204 |
ch = m4_peek_input (); |
ch = m4_peek_input (); |
205 |
if (M4_IS_OPEN(ch)) |
if (M4_IS_OPEN(ch)) |
206 |
{ |
{ |
207 |
m4_next_token (&tokenbuf); /* gobble parenthesis */ |
m4_next_token (&td); /* gobble parenthesis */ |
208 |
do |
do |
209 |
{ |
{ |
210 |
more_args = expand_argument (arguments, &tokenbuf); |
more_args = expand_argument (arguments, &td); |
211 |
|
|
212 |
if (!groks_macro_args && M4_SYMBOL_TYPE (&tokenbuf) == M4_TOKEN_FUNC) |
if (!groks_macro_args && M4_TOKEN_DATA_TYPE (&td) == M4_TOKEN_FUNC) |
213 |
{ |
{ |
214 |
M4_SYMBOL_TYPE (&tokenbuf) = M4_TOKEN_TEXT; |
M4_TOKEN_DATA_TYPE (&td) = M4_TOKEN_TEXT; |
215 |
M4_SYMBOL_TEXT (&tokenbuf) = ""; |
M4_TOKEN_DATA_TEXT (&td) = ""; |
216 |
} |
} |
217 |
token = (m4_symbol *) |
tdp = (m4_token_data *) |
218 |
obstack_copy (arguments, (void *) &tokenbuf, sizeof (tokenbuf)); |
obstack_copy (arguments, (void *) &td, sizeof (td)); |
219 |
obstack_grow (argptr, (void *) &token, sizeof (token)); |
obstack_grow (argptr, (void *) &tdp, sizeof (tdp)); |
220 |
} |
} |
221 |
while (more_args); |
while (more_args); |
222 |
} |
} |
231 |
arguments to the call, stored in the ARGV table. The expansion is |
arguments to the call, stored in the ARGV table. The expansion is |
232 |
left on the obstack EXPANSION. Macro tracing is also handled here. */ |
left on the obstack EXPANSION. Macro tracing is also handled here. */ |
233 |
void |
void |
234 |
m4_call_macro (m4_symbol *symbol, int argc, m4_symbol **argv, |
m4_call_macro (m4_symbol *symbol, int argc, m4_token_data **argv, |
235 |
struct obstack *expansion) |
struct obstack *expansion) |
236 |
{ |
{ |
237 |
switch (M4_SYMBOL_TYPE (symbol)) |
switch (M4_SYMBOL_TYPE (symbol)) |
263 |
{ |
{ |
264 |
struct obstack arguments; |
struct obstack arguments; |
265 |
struct obstack argptr; |
struct obstack argptr; |
266 |
m4_symbol **argv; |
m4_token_data **argv; |
267 |
int argc; |
int argc; |
268 |
struct obstack *expansion; |
struct obstack *expansion; |
269 |
const char *expanded; |
const char *expanded; |
289 |
|
|
290 |
collect_arguments (name, symbol, &argptr, &arguments); |
collect_arguments (name, symbol, &argptr, &arguments); |
291 |
|
|
292 |
argc = obstack_object_size (&argptr) / sizeof (m4_symbol *); |
argc = obstack_object_size (&argptr) / sizeof (m4_token_data *); |
293 |
argv = (m4_symbol **) obstack_finish (&argptr); |
argv = (m4_token_data **) obstack_finish (&argptr); |
294 |
|
|
295 |
if (traced) |
if (traced) |
296 |
m4_trace_pre (name, my_call_id, argc, argv); |
m4_trace_pre (name, my_call_id, argc, argv); |
315 |
as usual. */ |
as usual. */ |
316 |
void |
void |
317 |
m4_process_macro (struct obstack *obs, m4_symbol *symbol, int argc, |
m4_process_macro (struct obstack *obs, m4_symbol *symbol, int argc, |
318 |
m4_symbol **argv) |
m4_token_data **argv) |
319 |
{ |
{ |
320 |
const unsigned char *text; |
const unsigned char *text; |
321 |
int i; |
int i; |
344 |
text = endp; |
text = endp; |
345 |
} |
} |
346 |
if (i < argc) |
if (i < argc) |
347 |
m4_shipout_string (obs, M4_SYMBOL_TEXT (argv[i]), 0, FALSE); |
m4_shipout_string (obs, M4_TOKEN_DATA_TEXT (argv[i]), 0, FALSE); |
348 |
break; |
break; |
349 |
|
|
350 |
case '#': /* number of arguments */ |
case '#': /* number of arguments */ |