1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1986-2009 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
19 ***********************************************************************/
25 * preprocessor builtin macro support
33 * process a #(...) builtin macro call
34 * `#(' has already been seen
56 pp
.state
|= DISABLE
|FILEPOP
|NOSPACE
;
58 p
= pp
.token
= pp
.tmpbuf
;
60 if ((c
= pplex()) != T_ID
)
62 error(2, "%s: #(<identifier>...) expected", p
);
65 switch (op
= (int)hashget(pp
.strtab
, p
))
69 p
= pp
.token
= pp
.valbuf
;
70 if ((c
= pplex()) == ',')
80 error(2, "%s in #(...) argument", pptokchr(c
));
84 else if (c
== ')' && !n
--) break;
85 else if (c
== ',' && !n
&& op
> 0) op
= 0;
86 if (op
) pp
.token
= pp
.toknxt
;
95 if ((c
= pplex()) == ')') *p
= '1';
104 error(2, "%s in #(...) argument", pptokchr(c
));
108 else if (c
== ')' && !n
--) break;
118 pp
.token
= pp
.valbuf
;
119 if ((c
= pplex()) != T_ID
|| !(sym
= ppsymref(pp
.symtab
, pp
.token
)) || !sym
->macro
|| sym
->macro
->arity
!= 1 || (c
= pplex()) != ',')
121 error(2, "#(%s <macro(x)>, ...) expected", p
);
126 error(2, "%s in #(...) argument", pptokchr(c
));
130 else if (c
== ')' && !n
--) break;
135 else while (c
!= ')')
138 if (pp
.token
> pp
.valbuf
) *pp
.token
++ = ' ';
139 STRCOPY(pp
.token
, sym
->name
, a
);
141 if (!c
|| !(c
= pplex()))
144 error(2, "%s in #(...) argument", pptokchr(c
));
147 pp
.state
&= ~NOSPACE
;
151 else if (c
== ')' && !n
--) break;
152 else if (c
== ',' && !n
) break;
153 pp
.token
= pp
.toknxt
;
169 error(2, "%s in #(...) argument", pptokchr(c
));
172 if ((c
= pplex()) == T_ID
&& !*a
)
180 for (in
= pp
.in
; in
; in
= in
->prev
)
181 if ((in
->type
== IN_MACRO
|| in
->type
== IN_MULTILINE
) && (in
->symbol
->flags
& SYM_FUNCTION
))
183 c
= *((unsigned char*)(pp
.macp
->arg
[0] - 2));
186 sfsprintf(p
= pp
.valbuf
, MAXTOKEN
, "%d", c
);
189 p
= (a
= strrchr(error_info
.file
, '/')) ? a
+ 1 : error_info
.file
;
197 a
= p
= ctime(&tm
) + 4;
199 for (p
+= 7; *p
= *(p
+ 9); p
++);
200 pp
.date
= p
= strdup(a
);
207 sfsprintf(p
= pp
.valbuf
, MAXTOKEN
, "%d", error_info
.line
);
214 for (in
= pp
.in
; in
->prev
; in
= in
->prev
)
215 if (in
->prev
->type
== IN_FILE
&& in
->file
)
220 p
[0] = ((pp
.state
& (COMPATIBILITY
|TRANSITION
)) || (pp
.mode
& (HOSTED
|HOSTEDTRANSITION
)) == (HOSTED
|HOSTEDTRANSITION
)) ? '0' : '1';
231 pp
.time
= p
= strdup(p
);
235 p
= (char*)pp
.version
;
240 strcpy(p
= pp
.valbuf
, "#");
243 if (!(p
= getenv(a
))) p
= "";
246 p
= (sym
= pprefmac(a
, REF_NORMAL
)) ? sym
->macro
->value
: "";
249 sfsprintf(p
= pp
.valbuf
, MAXTOKEN
, "%ld", ppoption(a
));
252 p
= (list
= (struct pplist
*)hashget(pp
.prdtab
, a
)) ? list
->value
: "";
255 if ((c
= pplex()) == '(')
258 pp
.state
|= NOSPACE
|STRIP
;
261 if (c
== T_STRING
|| c
== T_WSTRING
)
263 if (!(sp
= sfstropen()))
264 error(3, "temporary buffer allocation error");
265 sfprintf(sp
, "#%s %s\n", dirname(PRAGMA
), pp
.token
);
267 if ((c
= pplex()) == ')')
270 PUSH_BUFFER(p
, a
, 1);
276 error(2, "%s: (\"...\") expected", p
);
280 #define BACK(a,p) ((a>p)?*--a:(number++?0:((p=pp.outbuf+PPBUFSIZ),(a=pp.outbuf+2*PPBUFSIZ),*--a)))
281 #define PEEK(a,p) ((a>p)?*(a-1):(number?0:*(pp.outbuf+2*PPBUFSIZ-1)))
283 number
= pp
.outbuf
!= pp
.outb
;
287 while (c
= BACK(a
, p
))
289 if (c
== '"' || c
== '\'')
292 while ((n
= BACK(a
, p
)) && n
!= c
|| PEEK(a
, p
) == '\\');
297 while (c
= BACK(a
, p
))
303 else if (c
== '#' && PEEK(a
, p
) == '\n')
308 else if (c
== '{') /* '}' */
324 else if (c
== '(' && !--n
)
331 for (t
= p
, token
= a
, onumber
= number
; ppisidig(PEEK(a
, p
)) && a
>= p
; BACK(a
, p
));
335 for (; a
< pp
.outbuf
+2*PPBUFSIZ
; *p
++ = *a
++);
338 for (; a
<= token
; *p
++ = *a
++);
341 if (streq(p
, "for") || streq(p
, "if") || streq(p
, "switch") || streq(p
, "while"))
355 p
= strncpy(pp
.funbuf
, p
, sizeof(pp
.funbuf
) - 1);
362 if (pp
.builtin
&& (a
= (*pp
.builtin
)(pp
.valbuf
, p
, a
)))
376 if (p
< pp
.valbuf
+ MAXTOKEN
- 2)
395 if (p
== pp
.valbuf
+ 1)
399 if (strlen(p
) > MAXTOKEN
- 2)
400 error(1, "%-.16s: builtin value truncated", p
);
401 sfsprintf(pp
.valbuf
, MAXTOKEN
, "\"%-.*s", MAXTOKEN
- 2, p
);
403 PUSH_QUOTE(pp
.valbuf
, 1);