1 /* $Id: replace.c,v 1.18 1994/06/24 10:18:57 ceriel Exp $ */
3 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4 * See the copyright notice in the ACK home directory, in the file "Copyright".
6 /* PREPROCESSOR: MACRO-TEXT REPLACEMENT ROUTINES */
8 #include "debug.h" /* UF */
9 #include "pathlength.h" /* UF */
10 #include "textsize.h" /* UF */
19 #include "interface.h"
21 char *strcpy(), *strcat();
23 extern int InputLevel;
25 PRIVATE struct mlist *ReplList; /* list of currently active macros */
29 register struct idf *idef;
31 /* replace() is called by the lexical analyzer to perform
32 macro replacement. "idef" is the description of the
33 identifier which leads to the replacement. If the
34 optional actual parameters of the macro are OK, the text
35 of the macro is prepared to serve as an input buffer,
36 which is pushed onto the input stack.
37 replace() returns 1 if the replacement succeeded and 0 if
38 some error has occurred.
40 register struct macro *mac = idef->id_macro;
42 char **actpars, **getactuals();
43 char *reptext, *macro2buffer();
44 register struct mlist *repl;
47 if (mac->mc_flag & NOREPLACE) {
48 warning("macro %s is recursive", idef->id_text);
51 if (mac->mc_nps != -1) { /* with parameter list */
52 if (mac->mc_flag & FUNC) {
54 Unfortunately, the next assertion
56 assert( ! strcmp("defined", idef->id_text));
61 if (++mac->mc_count > 100) {
62 /* 100 must be some number in Parameters */
63 warning("macro %s is assumed recursive",
68 c = skipspaces(c,! (mac->mc_flag & FUNC));
69 if (c != '(') { /* no replacement if no () */
71 if (! (mac->mc_flag & FUNC)) {
72 warning("macro %s needs arguments",
77 if (mac->mc_flag & FUNC) {
80 extern char *GetIdentifier();
83 nam = GetIdentifier();
92 if (c != ')') error(") missing");
95 error("identifier missing");
98 if (param && param->id_macro)
102 InsertText(reptext, 2);
104 repl->m_level = InputLevel;
106 repl->next = ReplList;
112 actpars = getactuals(idef); /* get act.param. list */
117 if (mac->mc_flag & FUNC) /* this macro leads to special action */
119 if (mac->mc_nps <= 0) {
120 reptext = mac->mc_text;
121 size = mac->mc_length;
122 mac->mc_flag |= NOREPLACE; /* a file called __FILE__ ??? */
125 reptext = macro2buffer(idef, actpars, &size); /* create input buffer */
126 repl->m_repl = reptext;
128 InsertText(reptext, size);
130 repl->m_level = InputLevel;
131 repl->next = ReplList;
136 char FilNamBuf[PATHLENGTH];
140 register struct idf *idef;
142 /* macro_func() performs the special actions needed with some
143 macros. These macros are __FILE__ and __LINE__ which
144 replacement texts must be evaluated at the time they are
147 register struct macro *mac = idef->id_macro;
149 switch (idef->id_text[2]) { /* This switch is very blunt... */
150 case 'F' : /* __FILE__ */
151 mac->mc_length = strlen(FileName) + 2;
152 mac->mc_text = FilNamBuf;
153 mac->mc_text[0] = '"';
154 strcpy(&(mac->mc_text[1]), FileName);
155 strcat(mac->mc_text, "\"");
157 case 'L' : /* __LINE__ */
159 mac->mc_text = long2str((long) LineNumber, 10);
160 mac->mc_length = strlen(mac->mc_text);
164 crash("(macro_func)");
169 macro2buffer(idef, actpars, siztext)
174 /* Macro2buffer() turns the macro replacement text, as it is
175 stored, into an input buffer, while each occurrence of the
176 non-ascii formal parameter mark is replaced by its
177 corresponding actual parameter specified in the actual
178 parameter list actpars. A pointer to the beginning of the
179 constructed text is returned, while *siztext is filled
181 If there are no parameters, this function behaves
182 the same as strcpy().
184 register unsigned int size = idef->id_macro->mc_length + ITEXTSIZE;
185 register char *text = Malloc(size);
186 register int pos = 0;
187 register char *ptr = idef->id_macro->mc_text;
190 if (*ptr & FORMALP) { /* non-asc formal param. mark */
191 register int n = *ptr++ & 0177;
195 /* copy the text of the actual parameter
196 into the replacement text
198 for (p = actpars[n - 1]; *p; p++) {
201 text = Realloc(text, size <<= 1);
205 text[pos++] = *ptr++;
207 text = Realloc(text, size <<= 1);
212 return Realloc(text, pos+1);
224 register struct mlist *p = ReplList, *prev = 0;
226 assert(Unstacked > 0);
228 struct mlist *nxt = p->next;
230 if (p->m_level > InputLevel) {
231 p->m_mac->mc_flag &= ~NOREPLACE;
232 if (p->m_mac->mc_count) p->m_mac->mc_count--;
233 if (p->m_repl) free(p->m_repl);
234 if (! prev) ReplList = nxt;
235 else prev->next = nxt;