327
|
1 /* Micro-C Preprocessor Part */ /* $Id$ */
|
|
2
|
|
3 #include <stdio.h>
|
|
4 #include "mc.h"
|
|
5 #include "mc-parse.h"
|
|
6 #include "mc-macro.h"
|
|
7 #include "mc-code.h"
|
|
8
|
|
9 extern struct {int fd,ln;char *name0;int inc;FILE *fcb;} *filep,filestack[FILES];
|
|
10
|
|
11 int in_macro_if = 0;
|
|
12 char *chinput;
|
|
13
|
|
14 static int mconcat=0;
|
|
15
|
|
16 static void macro_define0();
|
346
|
17 static int macro_args(char **pchptr);
|
327
|
18 static int macro_function(int macrop,char **pchptr,NMTBL *nptr,int history);
|
|
19 static void local_define(char *macro,char *value);
|
|
20 static int macro_eval(int macrop,char *body0,int history);
|
346
|
21 static char * mappend(int lists,char **result);
|
327
|
22 static int macro_processing();
|
|
23
|
|
24 static void
|
|
25 gen_source(char *s)
|
|
26 {
|
|
27 printf("%s",s);
|
|
28 }
|
|
29
|
363
|
30 /*
|
|
31 replace macro term into cheap.
|
|
32 ## concatenation requires repeated replace.
|
|
33 */
|
|
34
|
327
|
35 extern void
|
|
36 macro_expansion(NMTBL *nptrm)
|
|
37 {
|
|
38 int i = mode;
|
|
39 int macrop = 0;
|
|
40 int slfree = lfree;
|
346
|
41 char *macropp;
|
|
42 struct cheap scheap;
|
327
|
43 mode = STAT;
|
|
44
|
346
|
45 save_cheap(&scheap,cheap);
|
|
46
|
327
|
47 if (nptrm->sc == FMACRO) {
|
|
48 macrop=macro_function(macrop,&chptr,nptrm,0);
|
|
49 } else {
|
|
50 macrop=macro_eval(macrop,(char *)car(nptrm->dsp),0);
|
|
51 }
|
347
|
52 cheap = reset_cheap(&scheap);
|
346
|
53 macropp = cheap->ptr;
|
347
|
54 // we can reset cheap, no page wrap in this case
|
346
|
55 mappend(reverse0(macrop),¯opp);
|
|
56 cheap->ptr[-1] ='\n';
|
|
57 cheap->ptr[0] =0;
|
327
|
58 while (mconcat) {
|
|
59 // ## re-eval macro
|
346
|
60 printf("## %s",macropp);
|
327
|
61 mconcat = 0;
|
|
62 macrop = 0;
|
346
|
63 macrop=macro_eval(macrop,macropp,0);
|
347
|
64 cheap = reset_cheap(&scheap);
|
346
|
65 macropp = cheap->ptr;
|
347
|
66 // will not override evaled list
|
346
|
67 mappend(reverse0(macrop),¯opp);
|
|
68 cheap->ptr[-1] ='\n';
|
|
69 cheap->ptr[0] =0;
|
327
|
70 }
|
346
|
71 cheap = reset_cheap(&scheap);
|
327
|
72 mconcat = 0;
|
447
|
73 set_lfree(slfree);
|
346
|
74 if (lsrc && !asmf && nptrm->sc==FMACRO) gen_comment(macropp);
|
327
|
75 chptrsave = glist2((int)chptr,chptrsave);
|
|
76 chsave = glist2(ch,chsave);
|
346
|
77 chptr = macropp;
|
327
|
78 ch = *chptr++;
|
|
79 mode = i;
|
|
80 }
|
|
81
|
|
82 /* file inclusion */
|
|
83
|
363
|
84 /*
|
|
85 file name concatenation
|
|
86 */
|
|
87
|
327
|
88 static char *
|
346
|
89 expand_file_name(char *path,char *name)
|
327
|
90 {
|
346
|
91 char *p = cheap->ptr;
|
|
92 if (! *path) return name;
|
|
93 while(( *cheap->ptr = *path++ )) cheap = increment_cheap(cheap,&p);
|
|
94 if (cheap->ptr[-1]!='/') {
|
|
95 *cheap->ptr = '/'; cheap = increment_cheap(cheap,&p);
|
|
96 }
|
|
97 while(( *cheap->ptr = *name++ )) cheap = increment_cheap(cheap,&p);
|
351
|
98 *cheap->ptr = 0;
|
|
99 cheap = increment_cheap(cheap,&p);
|
327
|
100 return p;
|
|
101 }
|
|
102
|
363
|
103 /*
|
|
104 get file name
|
|
105 <name> => name
|
|
106 current_file_name_dir / name
|
|
107 libdir / name
|
|
108 "name" => name
|
|
109 current_file_name_dir / name
|
|
110 include_path / name
|
|
111 */
|
|
112
|
327
|
113 static FILE *
|
|
114 getfname(void)
|
|
115 {
|
|
116 int i,end='"',err=0;
|
346
|
117 char *s,*p,**pp,*name;
|
327
|
118 FILE *fp;
|
346
|
119 struct cheap scheap;
|
|
120 name = cheap->ptr;
|
327
|
121
|
|
122 getch();
|
|
123 if(skipspc()=='"') { end = '"';
|
|
124 } else if (ch=='<') { end = '>';
|
|
125 } else { error(INCERR); err=1;
|
|
126 }
|
|
127 for(i=0;(getch()!=end && ch!='\n');) {
|
346
|
128 *cheap->ptr = ch;
|
|
129 cheap = increment_cheap(cheap,&name);
|
327
|
130 }
|
|
131 if(ch=='\n') error(INCERR);
|
|
132 if (err) return filep->fcb;
|
351
|
133 *cheap->ptr = 0;
|
|
134 cheap = increment_cheap(cheap,&name);
|
|
135 save_cheap(&scheap,cheap);
|
327
|
136 fp = fopen(name,"r") ;
|
|
137 if (fp) {
|
|
138 p = name;
|
|
139 } else {
|
346
|
140 for(pp=(end=='>'||filep->inc=='>') ?l_include_path:include_path;
|
|
141 *pp;pp++) {
|
|
142 p = expand_file_name(*pp,name);
|
327
|
143 if ((fp = fopen(p,"r"))) break ;
|
|
144 }
|
|
145 }
|
|
146 if(!fp) { error(FILERR); return filep->fcb; }
|
|
147 copy_current_file_dir(s=p);
|
351
|
148 // File name determined. Dispose extra copies.
|
|
149 cheap = reset_cheap(&scheap);
|
346
|
150 if (p!=name) {
|
|
151 name = cheap->ptr;
|
|
152 while((*cheap->ptr = *s++)) cheap = increment_cheap(cheap,&name);
|
351
|
153 *cheap->ptr = 0;
|
|
154 cheap = increment_cheap(cheap,&name);
|
346
|
155 }
|
327
|
156 (filep+1)->inc = end;
|
346
|
157 (filep+1)->name0 = name;
|
327
|
158 return ( (filep+1)->fcb = fp );
|
|
159 }
|
|
160
|
|
161 /* line input and conversion */
|
|
162
|
|
163 static int macro_if_depth ;
|
|
164 static int macro_if_current ;
|
|
165 static int macro_if_skip ;
|
|
166
|
363
|
167 /* there may extra non-terminate comment after #if/#else directive */
|
364
|
168 /* #endif / * hoge */
|
363
|
169 /* */
|
|
170 /* */
|
|
171
|
327
|
172 static int
|
|
173 skip_rest_of_line()
|
|
174 {
|
|
175 getch();
|
|
176 do {
|
|
177 while(ch!='\n'&&ch!='\r') {
|
|
178 if (!in_comment) {
|
|
179 if (ch=='/') {
|
|
180 getch();
|
|
181 if (ch=='/') in_comment=2;
|
|
182 else if (ch=='*') {
|
|
183 in_comment=1;
|
|
184 } else continue;
|
|
185 }
|
|
186 } else if (ch=='*') {
|
|
187 getch();
|
|
188 if (ch=='/') {
|
|
189 in_comment=0;
|
|
190 return macro_if_skip?0:1;
|
|
191 }
|
|
192 else continue;
|
|
193 }
|
|
194 getch();
|
|
195 }
|
|
196 if (in_comment==1) { getline(); getch(); }
|
|
197 } while(in_comment==1);
|
|
198 in_comment=0;
|
|
199 return 0;
|
|
200 }
|
|
201
|
363
|
202 /*
|
|
203 getline from chptr or chinput (for internal source)
|
|
204 with macro processing
|
|
205 */
|
|
206
|
343
|
207 static int next_eof;
|
|
208
|
327
|
209 extern void
|
|
210 getline(void)
|
|
211 {
|
|
212 int i;
|
|
213 int c;
|
|
214
|
343
|
215 if (next_eof) {
|
|
216 next_eof=0;
|
|
217 error(EOFERR);
|
|
218 }
|
327
|
219 do {
|
|
220 if (chinput) {
|
|
221 if (! *chinput) {
|
|
222 chinput=0;
|
|
223 continue;
|
|
224 }
|
|
225 chptr=linebuf;
|
|
226 i=0;
|
|
227 while((*chptr++=c=*chinput++)&&(c!='\n')) {
|
|
228 if (++i > LBUFSIZE-2) error(LNERR);
|
|
229 }
|
|
230 } else {
|
|
231 lineno++;
|
|
232 glineno++;
|
|
233 chptr=linebuf;
|
|
234 i=0;
|
|
235 while ((*chptr++ = c = getc(filep->fcb)) != '\n') {
|
|
236 if (++i > LBUFSIZE-2) error(LNERR);
|
|
237 if (c==EOF) {
|
343
|
238 next_eof=1;
|
|
239 --chptr;
|
|
240 break;
|
327
|
241 }
|
|
242 }
|
|
243 }
|
|
244 *chptr = '\0';
|
343
|
245 if (lsrc && !asmf && !macro_if_skip && linebuf[0]) gen_comment(linebuf);
|
327
|
246 if (*(chptr = linebuf) == '#' && !in_comment && !in_quote) {
|
|
247 if (macro_processing()) return;
|
|
248 }
|
|
249 } while(!in_quote && (macro_if_skip || linebuf[0] == '#'));
|
|
250 }
|
|
251
|
|
252 /* preprocessor directive */
|
|
253
|
|
254 /* line continuation \\ */
|
|
255
|
|
256 extern void
|
|
257 check_macro_eof()
|
|
258 {
|
|
259 int c;
|
346
|
260 // can't be in macro expansion
|
327
|
261 for(c=0;c<LBUFSIZE-3&&chptr[c];c++);
|
|
262 if (c>0&&chptr[c-1]=='\\') {
|
|
263 return;
|
|
264 } else if (c>0&&chptr[c-1]=='\n') {
|
|
265 if (c>0&&chptr[c-2]=='\\') {
|
|
266 return;
|
|
267 } else {
|
|
268 c--;
|
|
269 }
|
|
270 }
|
|
271 chptr[c] = ';';
|
|
272 chptr[c+1] = '\n';
|
|
273 chptr[c+2] = 0;
|
|
274 }
|
|
275
|
363
|
276 /* #if hoge case */
|
|
277
|
327
|
278 static void
|
|
279 macro_if()
|
|
280 {
|
|
281 int i;
|
|
282 ch= *chptr;
|
|
283 in_macro_if = 1;
|
|
284 check_macro_eof();
|
|
285 getsym(0);
|
|
286 /* i=cexpr(expr(1)); #if allow undefined symbols.. */
|
|
287 i=expr(1);
|
|
288 in_macro_if = 0;
|
|
289 if (car(i)==CONST) i=cadr(i);
|
|
290 else i=0;
|
|
291 if (ch) {
|
|
292 if (chptr[-1]==ch) {
|
|
293 /* we are fall into getch(), which lost the last ch */
|
|
294 /* chptr[-1]==ch check is fanatic, but ... */
|
|
295 chptr--;
|
|
296 } else error(-1);
|
|
297 }
|
|
298 macro_if_depth = macro_if_current;
|
|
299 macro_if_skip = !i;
|
|
300 }
|
|
301
|
|
302 static int
|
|
303 macro_processing()
|
|
304 {
|
|
305 int i;
|
|
306 int c;
|
|
307 int mode_save;
|
|
308
|
|
309 ++chptr;
|
|
310 while (*chptr==' '||*chptr=='\t') ++chptr;
|
361
|
311 switch(chptr[0]*chptr[1]) {
|
|
312 case 'i'*'f':
|
|
313 if ((macroeq("ifdef") || macroeq("ifndef"))) {
|
|
314 c = (chptr[-4]=='n');
|
|
315 macro_if_current++;
|
|
316 if (!macro_if_skip) {
|
|
317 mode_save = mode; mode = IFDEF;
|
|
318 ch= *chptr;
|
|
319 i = getsym(0);
|
|
320 mode = mode_save;
|
|
321 macro_if_depth = macro_if_current;
|
|
322 macro_if_skip = (!i)^c;
|
|
323 }
|
327
|
324 return 0;
|
361
|
325 } else if (macroeq("if")) {
|
|
326 macro_if_current++;
|
|
327 if (!macro_if_skip) {
|
|
328 macro_if();
|
327
|
329 }
|
|
330 return 0;
|
|
331 }
|
361
|
332 break;
|
|
333 case 'e'*'l':
|
|
334 if (macroeq("elif")) {
|
|
335 if (macro_if_current==0) {
|
|
336 error(MCERR); /* extra #else */
|
|
337 return 0;
|
|
338 }
|
|
339 if (macro_if_current == macro_if_depth) {
|
|
340 if (!macro_if_skip || macro_if_skip==2) {
|
|
341 macro_if_skip=2;
|
|
342 return 0;
|
|
343 }
|
|
344 macro_if();
|
|
345 }
|
|
346 return 0;
|
|
347 } else if (macroeq("else")) {
|
|
348 if (macro_if_current==0) {
|
|
349 error(MCERR); /* extra #else */
|
327
|
350 return 0;
|
|
351 }
|
361
|
352 if (macro_if_current == macro_if_depth) {
|
|
353 if (macro_if_skip==2) ;
|
|
354 else if (macro_if_skip) macro_if_skip=0;
|
|
355 else macro_if_skip=1;
|
|
356 }
|
|
357 return skip_rest_of_line();
|
327
|
358 }
|
361
|
359 break;
|
|
360 case 'e'*'n':
|
|
361 if (macroeq("endif")) {
|
|
362 if (macro_if_current == macro_if_depth) {
|
|
363 macro_if_skip = 0;
|
|
364 macro_if_depth = --macro_if_current;
|
|
365 } else {
|
|
366 if (macro_if_current<=0) {
|
|
367 error(MCERR); /* extra #if */
|
|
368 return 0;
|
|
369 }
|
|
370 macro_if_current--;
|
|
371 }
|
|
372 return skip_rest_of_line();
|
|
373 }
|
327
|
374 }
|
|
375 if (macro_if_skip) return 0;
|
361
|
376 switch(chptr[0]) {
|
|
377 case 'd':
|
|
378 if (macroeq("define")) {
|
|
379 ch= *chptr;
|
|
380 macro_define0();
|
|
381 *(chptr = linebuf) = '\0';
|
|
382 return 0;
|
|
383 }
|
|
384 break;
|
|
385 case 'u':
|
|
386 if (macroeq("undef")) {
|
|
387 i=mode;
|
|
388 mode=IFDEF;
|
|
389 ch= *chptr;
|
|
390 if (getsym(0)) {
|
|
391 if (nptr->sc == MACRO) {
|
|
392 nptr->sc = EMPTY;
|
|
393 } else if (nptr->sc == FMACRO) {
|
|
394 nptr->sc = EMPTY;
|
|
395 /* we cannot reclaim it's arg */
|
|
396 } else error(MCERR);
|
|
397 }
|
|
398 mode=i;
|
|
399 return 0;
|
327
|
400 }
|
361
|
401 break;
|
|
402 case 'i':
|
|
403 if (macroeq("include")) {
|
|
404 if(filep+1 >= filestack + FILES) error(FILERR);
|
|
405 if ( ((filep+1)->fcb=getfname()) == NULL) error(FILERR);
|
|
406 (filep+1)->ln=lineno;
|
|
407 lineno=0;
|
|
408 ++filep;
|
|
409 *(chptr = linebuf) = '\0';
|
|
410 return 0;
|
|
411 }
|
|
412 break;
|
327
|
413 #if ASM_CODE
|
361
|
414 case 'a':
|
|
415 if (c=='a'&¯oeq("asm")) {
|
|
416 if (asmf) error(MCERR);
|
|
417 asmf = 1;
|
327
|
418 getline();
|
361
|
419 while (asmf) {
|
|
420 gen_source(linebuf);
|
|
421 getline();
|
|
422 }
|
|
423 return 0;
|
327
|
424 }
|
361
|
425 break;
|
|
426 case 'e':
|
|
427 if (macroeq("endasm")) {
|
|
428 if (!asmf) error(MCERR);
|
|
429 asmf = 0;
|
|
430 return 0;
|
|
431 }
|
|
432 break;
|
327
|
433 #endif
|
361
|
434 case ' ': case '\t':
|
327
|
435 getline();
|
361
|
436 return 0;
|
|
437 }
|
|
438 error(MCERR);
|
327
|
439 return 0;
|
|
440 }
|
|
441
|
|
442 extern int
|
|
443 macroeq(char *s)
|
|
444 {
|
|
445 char *p;
|
|
446
|
|
447 for (p = chptr; *s;) if (*s++ != *p++) return 0;
|
|
448 chptr = p;
|
|
449 return 1;
|
|
450 }
|
|
451
|
|
452 /* macro interpreter */
|
|
453
|
|
454 extern void
|
|
455 macro_define(char *macro)
|
|
456 {
|
|
457 char *chptr_save;
|
|
458 int chsave;
|
|
459
|
|
460 chptr_save = chptr;
|
|
461 chsave = ch;
|
|
462 chptr = macro;
|
|
463 ch= *chptr++;
|
|
464 macro_define0();
|
|
465 chptr = chptr_save;
|
|
466 ch = chsave;
|
|
467 }
|
|
468
|
363
|
469 /* macro define from chptr */
|
|
470
|
327
|
471 static void
|
|
472 macro_define0()
|
|
473 {
|
|
474 int i,args,c;
|
346
|
475 char **body;
|
327
|
476
|
|
477 i=mode;
|
|
478 mode=MDECL;
|
|
479 // ch= *chptr; ??
|
|
480 // fprintf(stderr,"macro def: ch %c *chptr %c\n",ch,*chptr);
|
|
481 getsym(0);
|
|
482 // fprintf(stderr,"macro def: %s =>",name);
|
|
483 if (nptr->sc != EMPTY) { /* override existing macro */
|
|
484 }
|
|
485 args = 0;
|
|
486 if (ch=='(') {
|
|
487 nptr->sc = FMACRO;
|
346
|
488 args = macro_args(&chptr);
|
327
|
489 } else {
|
|
490 nptr->sc = MACRO;
|
|
491 nptr->ty = -1;
|
|
492 }
|
|
493 // equal is allowed for -Dhoge=aho option
|
|
494 if (ch=='=') chptr++;
|
|
495 while((c=*chptr)==' '||c=='\t') chptr++;
|
346
|
496 nptr->dsp = list2((int)cheap->ptr,args); /* macro body */
|
|
497 body = (char **)&car(nptr->dsp);
|
|
498 while ((*cheap->ptr = c = *chptr++)
|
327
|
499 && c != '\n') {
|
346
|
500 cheap = increment_cheap(cheap,body);
|
327
|
501 if (c=='/'&&chptr[0]=='/') {
|
351
|
502 cheap->ptr--;
|
|
503 *cheap->ptr = '\0';
|
|
504 while(*chptr++); break;
|
327
|
505 } else if (c=='/'&&chptr[0]=='*') {
|
346
|
506 cheap->ptr--; chptr++;
|
327
|
507 while((c = *chptr++)) {
|
|
508 if (c=='*'&&chptr[0]=='/') {
|
|
509 c = *chptr++; break;
|
|
510 }
|
|
511 }
|
|
512 if (!c) break;
|
|
513 } else if (c=='\\' && (*chptr=='\n'||*chptr==0)) {
|
|
514 chptr++;
|
346
|
515 cheap->ptr--;
|
327
|
516 getline();
|
|
517 }
|
|
518 }
|
346
|
519 if (c=='\n') {
|
|
520 *cheap->ptr = '\0';
|
|
521 }
|
|
522 cheap = increment_cheap(cheap,body);
|
327
|
523 // fprintf(stderr,"%s\n",(char *)car(nptr->dsp));
|
|
524 mode=i;
|
|
525 }
|
|
526
|
|
527 // create function macro argument list
|
|
528 // return list2((char*)arg,next)
|
|
529
|
|
530 static int
|
346
|
531 macro_args(char **pchptr)
|
327
|
532 {
|
|
533 int c;
|
|
534 int in_quote = 0;
|
|
535 int in_wquote = 0;
|
|
536 int plevel = 0;
|
346
|
537 char **body;
|
327
|
538 char *chptr = *pchptr;
|
346
|
539 int args = list2((int)cheap->ptr,0);
|
|
540 body = (char **)&car(args);
|
327
|
541 for(;;) {
|
346
|
542 *cheap->ptr = c = *chptr++;
|
|
543 cheap = increment_cheap(cheap,body);
|
327
|
544 if (!c) {
|
|
545 chptr--;
|
|
546 error(MCERR);
|
|
547 *pchptr = chptr;
|
|
548 return reverse0(args);
|
|
549 }
|
|
550 if (in_quote) {
|
|
551 if (c=='\\') {
|
|
552 if (*chptr != '\n') {
|
346
|
553 *cheap->ptr = *chptr++;
|
|
554 cheap = increment_cheap(cheap,body);
|
327
|
555 } else {
|
|
556 getline();
|
|
557 }
|
|
558 } else if (c=='\'') {
|
|
559 in_quote = 0;
|
|
560 }
|
|
561 } else if (in_wquote) {
|
|
562 if (c=='\\') {
|
|
563 if (*chptr !='\n') {
|
346
|
564 *cheap->ptr = *chptr++;
|
|
565 cheap = increment_cheap(cheap,body);
|
327
|
566 } else {
|
346
|
567 *cheap->ptr = '\n';
|
327
|
568 getline();
|
|
569 }
|
|
570 } else if (c=='"') {
|
|
571 in_wquote = 0;
|
|
572 }
|
|
573 } else if (c=='"') {
|
|
574 in_wquote = 1;
|
|
575 } else if (c=='\'') {
|
|
576 in_quote = 1;
|
|
577 } if (plevel==0) {
|
|
578 if (c==',') {
|
346
|
579 cheap->ptr[-1] = 0;
|
|
580 args = list2((int)cheap->ptr,args);
|
|
581 body = (char **)&car(args);
|
327
|
582 } else if (c==')') {
|
346
|
583 cheap->ptr[-1] = 0;
|
327
|
584 break;
|
|
585 } else if (c=='(') {
|
|
586 plevel++;
|
|
587 } else if (c=='\\') {
|
|
588 if (*chptr=='\n') {
|
346
|
589 cheap->ptr--;
|
327
|
590 getline();
|
|
591 }
|
|
592 // } else if (c==' '||c=='\t') {
|
346
|
593 // cheap->ptr--;
|
327
|
594 } else if (c=='\n') {
|
346
|
595 cheap->ptr--;
|
327
|
596 getline();
|
|
597 chptr = *pchptr;
|
|
598 }
|
|
599 } else if (c==')') {
|
|
600 plevel--;
|
|
601 } else if (c=='(') {
|
|
602 plevel++;
|
|
603 } else if (c=='\n') {
|
346
|
604 cheap->ptr--;
|
327
|
605 getline();
|
|
606 chptr = *pchptr;
|
|
607 }
|
|
608 }
|
|
609 *pchptr = chptr;
|
|
610 return reverse0(args);
|
|
611 }
|
|
612
|
|
613 /* output macro expansion result into macrobuf (macropp) */
|
|
614
|
|
615 static int
|
|
616 macro_function(int macrop,char **pchptr,NMTBL *nptr,int history)
|
|
617 {
|
|
618 int args,sargs,values,evalues;
|
|
619 char *macro;
|
|
620
|
|
621 sargs = args = cadr(nptr->dsp);
|
346
|
622 values = macro_args(pchptr);
|
327
|
623 if (pchptr==&chptr) {
|
|
624 ch = *chptr++;
|
|
625 }
|
|
626 evalues = 0;
|
|
627 while(values) {
|
|
628 evalues = list2(macro_eval(0,(char *)car(values),history),evalues);
|
|
629 values = cadr(values);
|
|
630 }
|
|
631 evalues = reverse0(evalues);
|
359
|
632 enter_scope();
|
327
|
633 while(args) {
|
346
|
634 mappend(reverse0(car(evalues)),¯o);
|
|
635 local_define((char *)car(args),macro);
|
327
|
636 args = cadr(args);
|
|
637 evalues = cadr(evalues);
|
|
638 }
|
|
639 macro = (char *)car(nptr->dsp);
|
|
640 macrop = macro_eval(macrop,macro,list2((int)macro,history));
|
|
641 args = sargs;
|
359
|
642 leave_scope();
|
327
|
643 return macrop;
|
|
644 }
|
|
645
|
|
646 static void
|
|
647 local_define(char *macro,char *value)
|
|
648 {
|
359
|
649 NMTBL *nptr0,*nlist;
|
327
|
650 while(*macro==' '||*macro=='\t') macro++;
|
359
|
651 nptr0 = name_space_search(nlist=get_name(macro,0,DEF),MACRO);
|
|
652 nptr0 = make_local_scope(nlist,nptr0,MACRO);
|
|
653 nptr0->nm = value;
|
327
|
654 }
|
|
655
|
363
|
656 /*
|
|
657 Evaluate macro string.
|
|
658 reuslt: list2("replaced string",next)
|
|
659 */
|
|
660
|
327
|
661 static int
|
|
662 macro_eval(int macrop,char *body0,int history)
|
|
663 {
|
350
|
664 int c,len;
|
327
|
665 int in_quote = 0;
|
|
666 int in_wquote = 0;
|
|
667 char *macro;
|
|
668 char *body = body0;
|
346
|
669 char **expand;
|
327
|
670 NMTBL *nptrm;
|
346
|
671 macrop = list2((int)cheap->ptr,macrop);
|
|
672 expand = (char **)&car(macrop);
|
327
|
673 for(; (c = *body++) ;) {
|
|
674 if (in_quote) {
|
|
675 if (c=='\\') {
|
346
|
676 *cheap->ptr = c; c = *body++;
|
|
677 cheap = increment_cheap(cheap,expand);
|
327
|
678 } else if (c=='\'') {
|
|
679 in_quote = 0;
|
|
680 }
|
|
681 } else if (in_wquote) {
|
|
682 if (c=='\\') {
|
346
|
683 *cheap->ptr = c; c = *body++;
|
|
684 cheap = increment_cheap(cheap,expand);
|
327
|
685 } else if (c=='"') {
|
|
686 in_wquote = 0;
|
|
687 }
|
|
688 } else if (c=='"') {
|
|
689 in_wquote = 1;
|
|
690 } else if (c=='\'') {
|
|
691 in_quote = 1;
|
|
692 } else if (c=='#' && *body=='#') {
|
|
693 // name concatenation. skip ## and re-eval macro line.
|
|
694 mconcat = 1; body++; continue;
|
|
695 } else if (alpha(c)) {
|
349
|
696 body--; // ungetc
|
350
|
697 nptrm = get_name(body,&len,NONDEF);
|
|
698 if (!nptrm) {
|
|
699 while((*cheap->ptr = *body++) && len--)
|
|
700 cheap = increment_cheap(cheap,expand);
|
|
701 body--;
|
|
702 continue;
|
|
703 }
|
|
704 body += len;
|
349
|
705 c = *body;
|
347
|
706 nptrm = name_space_search(nptrm,MACRO);
|
327
|
707 macro = (char *)car(nptrm->dsp);
|
347
|
708 switch(nptrm->sc) {
|
|
709 case FMACRO:
|
327
|
710 if (c==' '||c=='\t') {
|
|
711 while (c==' '||c=='\t') c=*body++;
|
|
712 body--;
|
|
713 }
|
|
714 if(c!='(') error(MCERR);
|
349
|
715 *cheap->ptr = 0;
|
346
|
716 cheap = increment_cheap(cheap,expand);
|
|
717 body++;
|
327
|
718 macrop = macro_function(macrop,&body,nptrm,
|
|
719 list2((int)macro,history));
|
346
|
720 macrop = list2((int)cheap->ptr,macrop);
|
|
721 expand = (char **)&(car(macrop));
|
347
|
722 break;
|
|
723 case MACRO:
|
|
724 if (neqname(nptrm->nm,macro)) {
|
|
725 if (macro[0]==0) continue;
|
|
726 *cheap->ptr = 0;
|
|
727 cheap = increment_cheap(cheap,expand);
|
|
728 macrop=macro_eval(macrop,macro,list2((int)macro,history));
|
|
729 macrop = list2((int)cheap->ptr,macrop);
|
|
730 expand = (char **)&(car(macrop));
|
|
731 break;
|
|
732 }
|
|
733 default:
|
346
|
734 macro = nptrm->nm;
|
347
|
735 case LMACRO:
|
349
|
736 while((*cheap->ptr = *macro++)/* && len-- */)
|
346
|
737 cheap = increment_cheap(cheap,expand);
|
327
|
738 }
|
|
739 continue;
|
|
740 }
|
346
|
741 *cheap->ptr = c;
|
|
742 cheap = increment_cheap(cheap,expand);
|
327
|
743 }
|
346
|
744 *cheap->ptr = 0;
|
|
745 cheap = increment_cheap(cheap,expand);
|
327
|
746 return macrop;
|
|
747 }
|
|
748
|
363
|
749 /*
|
|
750 cancat list2("string",next) into cheap.
|
|
751 result overwrited by next cheap allocation
|
|
752 */
|
327
|
753
|
|
754 static char *
|
346
|
755 mappend(int lists,char **result)
|
327
|
756 {
|
|
757 char *p;
|
346
|
758 *result = cheap->ptr;
|
348
|
759 for(;lists;lists = cadr(lists)) {
|
327
|
760 p = (char *)car(lists);
|
347
|
761 for(;(*cheap->ptr=*p++);cheap = increment_cheap(cheap,0)) {
|
346
|
762 // in_quote + \n case ? should be \n.
|
350
|
763 if (p[-1]=='\n') cheap->ptr[0]=' ';
|
346
|
764 }
|
327
|
765 }
|
347
|
766 cheap = increment_cheap(cheap,0);
|
346
|
767 return *result;
|
327
|
768 }
|
|
769
|
|
770 /* end */
|