1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
36 * parm[], parmp, and parlist[] are used to store #define() argument
37 * lists. nargs contains the actual number of parameters stored.
39 static char parm
[NPARMWORK
+ 1]; /* define param work buffer */
40 static char *parmp
; /* Free space in parm */
41 static char *parlist
[LASTPARM
]; /* -> start of each parameter */
42 static int nargs
; /* Parameters for this macro */
47 for( i
= 0; i
< NPARMWORK
; i
++ )
49 for( i
= 0; i
< LASTPARM
; i
++ )
58 * Called from control when a #define is scanned. This module
59 * parses formal parameters and the replacement string. When
60 * the formal parameter name is encountered in the replacement
61 * string, it is replaced by a character in the range 128 to
62 * 128+NPARAM (this allows up to 32 parameters within the
63 * Dec Multinational range). If cpp is ported to an EBCDIC
64 * machine, you will have to make other arrangements.
66 * There is some special case code to distinguish
68 * from #define foo() bar
70 * Also, we make sure that
72 * expands to "foo" but doesn't put cpp into an infinite loop.
74 * A warning message is printed if you redefine a symbol to a
75 * different text. I.e,
83 * The following subroutines are called from define():
84 * checkparm called when a token is scanned. It checks through the
85 * array of formal parameters. If a match is found, the
86 * token is replaced by a control byte which will be used
87 * to locate the parameter when the macro is expanded.
88 * textput puts a string in the macro work area (parm[]), updating
89 * parmp to point to the first free byte in parm[].
90 * textput() tests for work buffer overflow.
91 * charput puts a single character in the macro work area (parm[])
92 * in a manner analogous to textput().
96 register DEFBUF
*dp
; /* -> new definition */
97 int isredefine
; /* TRUE if redefined */
98 char *old
= 0; /* Remember redefined */
100 if (type
[(c
= skipws())] != LET
)
102 isredefine
= FALSE
; /* Set if redefining */
103 if ((dp
= lookid(c
)) == NULL
) /* If not known now */
104 dp
= defendel(token
, FALSE
); /* Save the name */
105 else { /* It's known: */
106 isredefine
= TRUE
; /* Remember this fact */
107 old
= dp
->repl
; /* Remember replacement */
108 dp
->repl
= NULL
; /* No replacement now */
110 parlist
[0] = parmp
= parm
; /* Setup parm buffer */
111 if ((c
= get()) == '(') { /* With arguments? */
112 nargs
= 0; /* Init formals counter */
113 do { /* Collect formal parms */
114 if (nargs
>= LASTPARM
)
115 cfatal("Too many arguments for macro", NULLST
);
116 else if ((c
= skipws()) == ')')
117 break; /* Got them all */
118 else if (type
[c
] != LET
) /* Bad formal syntax */
120 scanid(c
); /* Get the formal param */
121 parlist
[nargs
++] = parmp
; /* Save its start */
122 textput(token
); /* Save text in parm[] */
123 } while ((c
= skipws()) == ','); /* Get another argument */
124 if (c
!= ')') /* Must end at ) */
126 c
= ' '; /* Will skip to body */
130 * DEF_NOARGS is needed to distinguish between
131 * "#define foo" and "#define foo()".
133 nargs
= DEF_NOARGS
; /* No () parameters */
135 if (type
[c
] == SPA
) /* At whitespace? */
136 c
= skipws(); /* Not any more. */
137 workp
= work
; /* Replacement put here */
138 inmacro
= TRUE
; /* Keep \<newline> now */
139 while (c
!= EOF_CHAR
&& c
!= '\n') { /* Compile macro body */
141 #if COMMENT_INVISIBLE
142 if (c
== COM_SEP
) { /* Token concatenation? */
143 save(TOK_SEP
); /* Stuff a delimiter */
146 if (c
== '#') { /* Token concatenation? */
147 while (workp
> work
&& type
[(int)workp
[-1]] == SPA
)
148 --workp
; /* Erase leading spaces */
149 save(TOK_SEP
); /* Stuff a delimiter */
150 c
= skipws(); /* Eat whitespace */
152 if (type
[c
] == LET
) /* Another token here? */
153 ; /* Stuff it normally */
154 else if (type
[c
] == DIG
) { /* Digit string after? */
155 while (type
[c
] == DIG
) { /* Stuff the digits */
159 save(TOK_SEP
); /* Delimit 2nd token */
162 #if ! COMMENT_INVISIBLE
163 ciwarn("Strange character after # (%d.)", c
);
171 checkparm(c
, dp
); /* Might be a formal */
174 case DIG
: /* Number in mac. body */
175 case DOT
: /* Maybe a float number */
176 scannumber(c
, save
); /* Scan it off */
179 case QUO
: /* String in mac. body */
181 stparmscan(c
, dp
); /* Do string magic */
187 case BSH
: /* Backslash */
189 if ((c
= get()) == '\n')
194 case SPA
: /* Absorb whitespace */
196 * Note: the "end of comment" marker is passed on
197 * to allow comments to separate tokens.
199 if (workp
[-1] == ' ') /* Absorb multiple */
202 c
= ' '; /* Normalize tabs */
203 /* Fall through to store character */
204 default: /* Other character */
210 inmacro
= FALSE
; /* Stop newline hack */
211 unget(); /* For control check */
212 if (workp
> work
&& workp
[-1] == ' ') /* Drop trailing blank */
214 *workp
= EOS
; /* Terminate work */
215 dp
->repl
= savestring(work
); /* Save the string */
216 dp
->nargs
= nargs
; /* Save arg count */
217 #if OSL_DEBUG_LEVEL > 1
219 dumpadef("macro definition", dp
);
223 if (isredefine
) { /* Error if redefined */
224 if ((old
!= NULL
&& dp
->repl
!= NULL
&& !streq(old
, dp
->repl
))
225 || (old
== NULL
&& dp
->repl
!= NULL
)
226 || (old
!= NULL
&& dp
->repl
== NULL
)) {
228 cerror("Redefining defined variable \"%s\"", dp
->name
);
230 cwarn("Redefining defined variable \"%s\"", dp
->name
);
233 if (old
!= NULL
) /* We don't need the */
234 free(old
); /* old definition now. */
239 cerror("#define syntax error", NULLST
);
240 inmacro
= FALSE
; /* Stop <newline> hack */
243 void checkparm(int c
, DEFBUF
* dp
)
245 * Replace this param if it's defined. Note that the macro name is a
246 * possible replacement token. We stuff DEF_MAGIC in front of the token
247 * which is treated as a LETTER by the token scanner and eaten by
248 * the output routine. This prevents the macro expander from
249 * looping if someone writes "#define foo foo".
255 scanid(c
); /* Get parm to token[] */
256 for (i
= 0; i
< nargs
; i
++) { /* For each argument */
257 if (streq(parlist
[i
], token
)) { /* If it's known */
261 save(i
+ MAC_PARM
); /* Save a magic cookie */
262 return; /* And exit the search */
265 if (streq(dp
->name
, token
)) /* Macro name in body? */
266 save(DEF_MAGIC
); /* Save magic marker */
267 for (cp
= token
; *cp
!= EOS
;) /* And save */
268 save(*cp
++); /* The token itself */
272 void stparmscan(delim
, dp
)
276 * Scan the string (starting with the given delimiter).
277 * The token is replaced if it is the only text in this string or
278 * character constant. The algorithm follows checkparm() above.
279 * Note that scanstring() has approved of the string.
285 * Warning -- this code hasn't been tested for a while.
286 * It exists only to preserve compatibility with earlier
287 * implementations of cpp. It is not part of the Draft
288 * ANSI Standard C language.
292 while ((c
= get()) != delim
295 if (type
[c
] == LET
) /* Maybe formal parm */
305 cerror("Unterminated string in macro body", NULLST
);
309 void stparmscan(int delim
)
311 * Normal string parameter scan.
317 wp
= workp
; /* Here's where it starts */
318 if (!scanstring(delim
, save
))
319 return; /* Exit on scanstring error */
320 workp
[-1] = EOS
; /* Erase trailing quote */
321 wp
++; /* -> first string content byte */
322 for (i
= 0; i
< nargs
; i
++) {
323 if (streq(parlist
[i
], wp
)) {
326 *wp
++ = MAC_PARM
+ PAR_MAC
; /* Stuff a magic marker */
327 *wp
++ = (char)(i
+ MAC_PARM
); /* Make a formal marker */
328 *wp
= wp
[-4]; /* Add on closing quote */
329 workp
= wp
+ 1; /* Reset string end */
331 *wp
++ = MAC_PARM
+ PAR_MAC
; /* Stuff a magic marker */
332 *wp
++ = (i
+ MAC_PARM
); /* Make a formal marker */
333 *wp
= wp
[-3]; /* Add on closing quote */
334 workp
= wp
+ 1; /* Reset string end */
339 workp
[-1] = wp
[-1]; /* Nope, reset end quote. */
345 * Remove the symbol from the defined list.
346 * Called from the #control processor.
351 if (type
[(c
= skipws())] != LET
)
352 cerror("Illegal #undef argument", NULLST
);
354 scanid(c
); /* Get name to token[] */
355 if (defendel(token
, TRUE
) == NULL
) {
357 cwarn("Symbol \"%s\" not defined in #undef", token
);
363 void textput(char* text
)
365 * Put the string in the parm[] buffer.
370 size
= strlen(text
) + 1;
371 if ((parmp
+ size
) >= &parm
[NPARMWORK
])
372 cfatal("Macro work area overflow", NULLST
);
381 * Put the byte in the parm[] buffer.
384 if (parmp
>= &parm
[NPARMWORK
])
385 cfatal("Macro work area overflow", NULLST
);
392 * M a c r o E x p a n s i o n
395 static DEFBUF
*macro
; /* Catches start of infinite macro */
397 void expand(DEFBUF
* tokenp
)
399 * Expand a macro. Called from the cpp mainline routine (via subroutine
400 * macroid()) when a token is found in the symbol table. It calls
401 * expcollect() to parse actual parameters, checking for the correct number.
402 * It then creates a "file" containing a single line containing the
403 * macro with actual parameters inserted appropriately. This is
404 * "pushed back" onto the input stream. (When the get() routine runs
405 * off the end of the macro line, it will dismiss the macro itself.)
409 register FILEINFO
*file
;
411 extern FILEINFO
*getfile();
414 #if OSL_DEBUG_LEVEL > 1
416 dumpadef("expand entry", tokenp
);
419 * If no macro is pending, save the name of this macro
420 * for an eventual error message.
422 if (recursion
++ == 0)
424 else if (recursion
== RECURSION_LIMIT
) {
425 cerror("Recursive macro definition of \"%s\"", tokenp
->name
);
426 fprintf(stderr
, "(Defined by \"%s\")\n", macro
->name
);
430 } while (infile
!= NULL
&& infile
->fp
== NULL
);
437 * Here's a macro to expand.
439 nargs
= 0; /* Formals counter */
440 parmp
= parm
; /* Setup parm buffer */
441 switch (tokenp
->nargs
) {
442 case (-2): /* __LINE__ */
443 sprintf(work
, "%d", line
);
447 case (-3): /* __FILE__ */
448 for (file
= infile
; file
!= NULL
; file
= file
->parent
) {
449 if (file
->fp
!= NULL
) {
450 sprintf(work
, "\"%s\"", (file
->progname
!= NULL
)
451 ? file
->progname
: file
->filename
);
460 * Nothing funny about this macro.
462 if (tokenp
->nargs
< 0)
463 cfatal("Bug: Illegal __ macro \"%s\"", tokenp
->name
);
464 while ((c
= skipws()) == '\n') /* Look for (, skipping */
465 wrongline
= TRUE
; /* spaces and newlines */
468 * If the programmer writes
472 * just write foo to the output stream.
475 cwarn("Macro \"%s\" needs arguments", tokenp
->name
);
476 fputs(tokenp
->name
, pCppOut
);
479 else if (expcollect()) { /* Collect arguments */
480 if (tokenp
->nargs
!= nargs
) { /* Should be an error? */
481 cwarn("Wrong number of macro arguments for \"%s\"",
484 #if OSL_DEBUG_LEVEL > 1
488 } /* Collect arguments */
489 case DEF_NOARGS
: /* No parameters just stuffs */
490 expstuff(tokenp
); /* Do actual parameters */
497 * Collect the actual parameters for this macro. TRUE if ok.
501 register int paren
; /* For embedded ()'s */
503 paren
= 0; /* Collect next arg. */
504 while ((c
= skipws()) == '\n') /* Skip over whitespace */
505 wrongline
= TRUE
; /* and newlines. */
506 if (c
== ')') { /* At end of all args? */
508 * Note that there is a guard byte in parm[]
509 * so we don't have to check for overflow here.
511 *parmp
= EOS
; /* Make sure terminated */
512 break; /* Exit collection loop */
514 else if (nargs
>= LASTPARM
)
515 cfatal("Too many arguments in macro expansion", NULLST
);
516 parlist
[nargs
++] = parmp
; /* At start of new arg */
517 for (;; c
= cget()) { /* Collect arg's bytes */
519 cerror("end of file within macro argument", NULLST
);
520 return (FALSE
); /* Sorry. */
522 else if (c
== '\\') { /* Quote next character */
523 charput(c
); /* Save the \ for later */
524 charput(cget()); /* Save the next char. */
525 continue; /* And go get another */
527 else if (type
[c
] == QUO
) { /* Start of string? */
528 scanstring(c
, charput
); /* Scan it off */
529 continue; /* Go get next char */
531 else if (c
== '(') /* Worry about balance */
532 paren
++; /* To know about commas */
533 else if (c
== ')') { /* Other side too */
534 if (paren
== 0) { /* At the end? */
535 unget(); /* Look at it later */
536 break; /* Exit arg getter. */
538 paren
--; /* More to come. */
540 else if (c
== ',' && paren
== 0) /* Comma delimits args */
542 else if (c
== '\n') /* Newline inside arg? */
543 wrongline
= TRUE
; /* We'll need a #line */
544 charput(c
); /* Store this one */
545 } /* Collect an argument */
546 charput(EOS
); /* Terminate argument */
547 #if OSL_DEBUG_LEVEL > 1
549 fprintf( pCppOut
, "parm[%d] = \"%s\"\n", nargs
, parlist
[nargs
- 1]);
551 } /* Collect all args. */
552 return (TRUE
); /* Normal return */
556 void expstuff(DEFBUF
* tokenp
)
558 * Stuff the macro body, replacing formal parameters by actual parameters.
561 register int c
; /* Current character */
562 register char *inp
; /* -> repl string */
563 register char *defp
; /* -> macro output buff */
564 int size
; /* Actual parm. size */
565 char *defend
; /* -> output buff end */
566 int string_magic
; /* String formal hack */
567 FILEINFO
*file
; /* Funny #include */
569 extern FILEINFO
*getfile();
572 file
= getfile(NBUFF
, tokenp
->name
);
573 inp
= tokenp
->repl
; /* -> macro replacement */
574 defp
= file
->buffer
; /* -> output buffer */
575 defend
= defp
+ (NBUFF
- 1); /* Note its end */
577 while ((c
= (*inp
++ & 0xFF)) != EOS
) {
582 if (c
>= MAC_PARM
&& c
<= (MAC_PARM
+ PAR_MAC
)) {
584 string_magic
= (c
== (MAC_PARM
+ PAR_MAC
));
588 * Replace formal parameter by actual parameter string.
590 if ((c
-= MAC_PARM
) < nargs
) {
591 size
= strlen(parlist
[c
]);
592 if ((defp
+ size
) >= defend
)
595 * Erase the extra set of quotes.
597 if (string_magic
&& defp
[-1] == parlist
[c
][0]) {
598 strcpy(defp
-1, parlist
[c
]);
602 strcpy(defp
, parlist
[c
]);
607 else if (defp
>= defend
) {
608 nospace
: cfatal("Out of space in macro \"%s\" arg expansion",
617 #if OSL_DEBUG_LEVEL > 1
619 fprintf( pCppOut
, "macroline: \"%s\"\n", file
->buffer
);
623 #if OSL_DEBUG_LEVEL > 1
624 void dumpparm(char* why
)
626 * Dump parameter list.
631 fprintf( pCppOut
, "dump of %d parameters (%d bytes total) %s\n",
632 nargs
, parmp
- parm
, why
);
633 for (i
= 0; i
< nargs
; i
++) {
634 fprintf( pCppOut
, "parm[%d] (%d) = \"%s\"\n",
635 i
+ 1, strlen(parlist
[i
]), parlist
[i
]);