comparison mc-macro.c @ 327:da2e3f2d127d

macro/codegen reorganization
author kono
date Mon, 21 Jun 2004 23:50:34 +0900
parents
children 11f8f2e6bb72
comparison
equal deleted inserted replaced
326:e5d40f8c4cce 327:da2e3f2d127d
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 char *macropp,macro_buf[MACROSIZE];
15 static int mconcat=0;
16
17 static void macro_define0();
18 static int macro_args(char **pcheapp,char *maxcheap,char **pchptr);
19 static int macro_function(int macrop,char **pchptr,NMTBL *nptr,int history);
20 static void local_define(char *macro,char *value);
21 static void local_undef(char *macro);
22 static int macro_eval(int macrop,char *body0,int history);
23 static char * mappend(int lists);
24 static int macro_processing();
25
26 static void
27 gen_source(char *s)
28 {
29 printf("%s",s);
30 }
31
32 extern void
33 macro_expansion(NMTBL *nptrm)
34 {
35 int i = mode;
36 int macrop = 0;
37 int slfree = lfree;
38 mode = STAT;
39
40 macropp = macro_buf;
41 if (nptrm->sc == FMACRO) {
42 macrop=macro_function(macrop,&chptr,nptrm,0);
43 } else {
44 macrop=macro_eval(macrop,(char *)car(nptrm->dsp),0);
45 }
46 macropp = macro_buf;
47 mappend(reverse0(macrop));
48 macropp[-1] ='\n';
49 *macropp =0;
50 while (mconcat) {
51 // ## re-eval macro
52 printf("## %s",macro_buf);
53 mconcat = 0;
54 macrop = 0;
55 macropp = macro_buf;
56 macrop=macro_eval(macrop,macro_buf,0);
57 macropp = macro_buf;
58 mappend(reverse0(macrop));
59 macropp[-1] ='\n';
60 *macropp =0;
61 }
62 mconcat = 0;
63 lfree = slfree;
64 if (lsrc && !asmf && nptrm->sc==FMACRO) gen_comment(macro_buf);
65 macropp[-1] =0;
66 if (macro_buf[0]==0) {
67 mode = i;
68 return;
69 }
70 chptrsave = glist2((int)chptr,chptrsave);
71 chsave = glist2(ch,chsave);
72 chptr = macro_buf;
73 ch = *chptr++;
74 mode = i;
75 }
76
77 /* file inclusion */
78
79 static char *
80 expand_file_name(char *path,char *name,int pos,int lbufsize)
81 {
82 char *p = name+pos;
83 int i,j;
84 j = 0;
85 for(i=0;path[i];i++,j++); for(i=0;name[i];i++,j++);
86 if (pos+j+1>lbufsize) { error(FILERR); return ""; }
87 while((name[pos++] = *path++));
88 pos--;
89 if (name[pos]!='/') name[pos]='/';
90 for(i = 0; ((name[pos++] = name[i++])););
91 return p;
92 }
93
94 static FILE *
95 getfname(void)
96 {
97 int i,end='"',err=0;
98 char *s,*p,**pp,name[LBUFSIZE];
99 FILE *fp;
100
101 getch();
102 if(skipspc()=='"') { end = '"';
103 } else if (ch=='<') { end = '>';
104 } else { error(INCERR); err=1;
105 }
106 for(i=0;(getch()!=end && ch!='\n');) {
107 if(i<LBUFSIZE-1) name[i++]=ch;
108 }
109 if(ch=='\n') error(INCERR);
110 if (err) return filep->fcb;
111 name[i]=0;
112 fp = fopen(name,"r") ;
113 if (fp) {
114 p = name;
115 } else {
116 for(pp=(end=='>'||filep->inc=='>')
117 ?l_include_path:include_path;*pp;pp++) {
118 p = expand_file_name(*pp,name,i+1,LBUFSIZE);
119 if ((fp = fopen(p,"r"))) break ;
120 }
121 }
122 if(!fp) { error(FILERR); return filep->fcb; }
123 copy_current_file_dir(s=p);
124 (filep+1)->name0 = cheapp;
125 (filep+1)->inc = end;
126 while((*cheapp++ = *s++));
127 return ( (filep+1)->fcb = fp );
128 }
129
130 /* line input and conversion */
131
132 static int macro_if_depth ;
133 static int macro_if_current ;
134 static int macro_if_skip ;
135
136 static int
137 skip_rest_of_line()
138 {
139 getch();
140 do {
141 while(ch!='\n'&&ch!='\r') {
142 if (!in_comment) {
143 if (ch=='/') {
144 getch();
145 if (ch=='/') in_comment=2;
146 else if (ch=='*') {
147 in_comment=1;
148 } else continue;
149 }
150 } else if (ch=='*') {
151 getch();
152 if (ch=='/') {
153 in_comment=0;
154 return macro_if_skip?0:1;
155 }
156 else continue;
157 }
158 getch();
159 }
160 if (in_comment==1) { getline(); getch(); }
161 } while(in_comment==1);
162 in_comment=0;
163 return 0;
164 }
165
166 extern void
167 getline(void)
168 {
169 int i;
170 int c;
171
172 do {
173 if (chinput) {
174 if (! *chinput) {
175 chinput=0;
176 continue;
177 }
178 chptr=linebuf;
179 i=0;
180 while((*chptr++=c=*chinput++)&&(c!='\n')) {
181 if (++i > LBUFSIZE-2) error(LNERR);
182 }
183 } else {
184 lineno++;
185 glineno++;
186 chptr=linebuf;
187 i=0;
188 while ((*chptr++ = c = getc(filep->fcb)) != '\n') {
189 if (++i > LBUFSIZE-2) error(LNERR);
190 if (c==EOF) {
191 error(EOFERR);
192 --chptr;
193 }
194 }
195 }
196 *chptr = '\0';
197 if (lsrc && !asmf && !macro_if_skip) gen_comment(linebuf);
198 if (*(chptr = linebuf) == '#' && !in_comment && !in_quote) {
199 if (macro_processing()) return;
200 }
201 } while(!in_quote && (macro_if_skip || linebuf[0] == '#'));
202 }
203
204 /* preprocessor directive */
205
206 /* line continuation \\ */
207
208 extern void
209 check_macro_eof()
210 {
211 int c;
212 for(c=0;c<LBUFSIZE-3&&chptr[c];c++);
213 if (c>0&&chptr[c-1]=='\\') {
214 return;
215 } else if (c>0&&chptr[c-1]=='\n') {
216 if (c>0&&chptr[c-2]=='\\') {
217 return;
218 } else {
219 c--;
220 }
221 }
222 chptr[c] = ';';
223 chptr[c+1] = '\n';
224 chptr[c+2] = 0;
225 }
226
227 static void
228 macro_if()
229 {
230 int i;
231 ch= *chptr;
232 in_macro_if = 1;
233 check_macro_eof();
234 getsym(0);
235 /* i=cexpr(expr(1)); #if allow undefined symbols.. */
236 i=expr(1);
237 in_macro_if = 0;
238 if (car(i)==CONST) i=cadr(i);
239 else i=0;
240 if (ch) {
241 if (chptr[-1]==ch) {
242 /* we are fall into getch(), which lost the last ch */
243 /* chptr[-1]==ch check is fanatic, but ... */
244 chptr--;
245 } else error(-1);
246 }
247 macro_if_depth = macro_if_current;
248 macro_if_skip = !i;
249 }
250
251 static int
252 macro_processing()
253 {
254 int i;
255 int c;
256 int mode_save;
257
258 ++chptr;
259 while (*chptr==' '||*chptr=='\t') ++chptr;
260 if (macroeq("ifdef") || macroeq("ifndef")) {
261 c = (chptr[-4]=='n');
262 macro_if_current++;
263 if (!macro_if_skip) {
264 mode_save = mode; mode = IFDEF;
265 ch= *chptr;
266 i = getsym(0);
267 mode = mode_save;
268 macro_if_depth = macro_if_current;
269 macro_if_skip = (!i)^c;
270 }
271 return 0;
272 } else if (macroeq("elif")) {
273 if (macro_if_current==0) {
274 error(MCERR); /* extra #else */
275 return 0;
276 }
277 if (macro_if_current == macro_if_depth) {
278 if (!macro_if_skip || macro_if_skip==2) {
279 macro_if_skip=2;
280 return 0;
281 }
282 macro_if();
283 }
284 return 0;
285 } else if (macroeq("if")) {
286 macro_if_current++;
287 if (!macro_if_skip) {
288 macro_if();
289 }
290 return 0;
291 } else if (macroeq("else")) {
292 if (macro_if_current==0) {
293 error(MCERR); /* extra #else */
294 return 0;
295 }
296 if (macro_if_current == macro_if_depth) {
297 if (macro_if_skip==2) ;
298 else if (macro_if_skip) macro_if_skip=0;
299 else macro_if_skip=1;
300 }
301 return skip_rest_of_line();
302 } else if (macroeq("endif")) {
303 if (macro_if_current == macro_if_depth) {
304 macro_if_skip = 0;
305 macro_if_depth = --macro_if_current;
306 } else {
307 if (macro_if_current<=0) {
308 error(MCERR); /* extra #if */
309 return 0;
310 }
311 macro_if_current--;
312 }
313 return skip_rest_of_line();
314 }
315 if (macro_if_skip) return 0;
316 if (macroeq("define")) {
317 ch= *chptr;
318 macro_define0();
319 *(chptr = linebuf) = '\0';
320 } else if (macroeq("undef")) {
321 i=mode;
322 mode=IFDEF;
323 ch= *chptr;
324 if (getsym(0)) {
325 if (nptr->sc == MACRO) {
326 nptr->sc = EMPTY;
327 } else if (nptr->sc == FMACRO) {
328 nptr->sc = EMPTY;
329 /* we cannot reclaim it's arg */
330 } else error(MCERR);
331 }
332 mode=i;
333 } else if (macroeq("include")) {
334 if(filep+1 >= filestack + FILES) error(FILERR);
335 if ( ((filep+1)->fcb=getfname()) == NULL) error(FILERR);
336 (filep+1)->ln=lineno;
337 lineno=0;
338 ++filep;
339 *(chptr = linebuf) = '\0';
340 #if ASM_CODE
341 } else if (macroeq("asm")) {
342 if (asmf) error(MCERR);
343 asmf = 1;
344 getline();
345 while (asmf) {
346 gen_source(linebuf);
347 getline();
348 }
349 } else if (macroeq("endasm")) {
350 if (!asmf) error(MCERR);
351 asmf = 0;
352 #endif
353 } else if (macroeq(" "))
354 getline();
355 else error(MCERR);
356 return 0;
357 }
358
359 extern int
360 macroeq(char *s)
361 {
362 char *p;
363
364 for (p = chptr; *s;) if (*s++ != *p++) return 0;
365 chptr = p;
366 return 1;
367 }
368
369 /* macro interpreter */
370
371 extern void
372 macro_define(char *macro)
373 {
374 char *chptr_save;
375 int chsave;
376
377 chptr_save = chptr;
378 chsave = ch;
379 chptr = macro;
380 ch= *chptr++;
381 macro_define0();
382 chptr = chptr_save;
383 ch = chsave;
384 }
385
386 static void
387 macro_define0()
388 {
389 int i,args,c;
390 char *scheapp;
391
392 i=mode;
393 mode=MDECL;
394 // ch= *chptr; ??
395 // fprintf(stderr,"macro def: ch %c *chptr %c\n",ch,*chptr);
396 getsym(0);
397 // fprintf(stderr,"macro def: %s =>",name);
398 if (nptr->sc != EMPTY) { /* override existing macro */
399 }
400 args = 0;
401 if (ch=='(') {
402 nptr->sc = FMACRO;
403 args = macro_args(&cheapp,cheap+CHEAPSIZE,&chptr);
404 } else {
405 nptr->sc = MACRO;
406 nptr->ty = -1;
407 }
408 // equal is allowed for -Dhoge=aho option
409 if (ch=='=') chptr++;
410 while((c=*chptr)==' '||c=='\t') chptr++;
411 nptr->dsp = list2((int)cheapp,args); /* macro body */
412 scheapp = cheapp;
413 while ((*cheapp++ = c = *chptr++)
414 && c != '\n') {
415 if (c=='/'&&chptr[0]=='/') {
416 cheapp--; while(*chptr++); break;
417 } else if (c=='/'&&chptr[0]=='*') {
418 cheapp--; chptr++;
419 while((c = *chptr++)) {
420 if (c=='*'&&chptr[0]=='/') {
421 c = *chptr++; break;
422 }
423 }
424 if (!c) break;
425 } else if (c=='\\' && (*chptr=='\n'||*chptr==0)) {
426 chptr++;
427 cheapp--;
428 getline();
429 }
430 }
431 *cheapp++ = '\0';
432 while(cheapp>scheapp&&(*cheapp=='\n'||*cheapp==0)) cheapp--;
433 *++cheapp = '\0'; cheapp++;
434 if (cheapp >= cheap+CHEAPSIZE) /* too late? */
435 error(STRERR);
436 // fprintf(stderr,"%s\n",(char *)car(nptr->dsp));
437 mode=i;
438 }
439
440 // create function macro argument list
441 // return list2((char*)arg,next)
442
443 static int
444 macro_args(char **pcheapp,char *maxcheap,char **pchptr)
445 {
446 int c;
447 int in_quote = 0;
448 int in_wquote = 0;
449 int plevel = 0;
450 char *cheapp = *pcheapp;
451 char *chptr = *pchptr;
452 int args = list2((int)cheapp,0);
453 for(;;) {
454 *cheapp++ = c = *chptr++;
455 if (cheapp >= maxcheap) error(MCERR);
456 if (!c) {
457 chptr--;
458 error(MCERR);
459 *pchptr = chptr;
460 *pcheapp = cheapp;
461 return reverse0(args);
462 }
463 if (in_quote) {
464 if (c=='\\') {
465 if (*chptr != '\n') {
466 *cheapp++ = *chptr++;
467 } else {
468 getline();
469 }
470 } else if (c=='\'') {
471 in_quote = 0;
472 }
473 } else if (in_wquote) {
474 if (c=='\\') {
475 if (*chptr !='\n') {
476 *cheapp++ = *chptr++;
477 } else {
478 *cheapp = '\n';
479 getline();
480 }
481 } else if (c=='"') {
482 in_wquote = 0;
483 }
484 } else if (c=='"') {
485 in_wquote = 1;
486 } else if (c=='\'') {
487 in_quote = 1;
488 } if (plevel==0) {
489 if (c==',') {
490 cheapp[-1] = 0;
491 args = list2((int)cheapp,args);
492 } else if (c==')') {
493 cheapp[-1] = 0;
494 break;
495 } else if (c=='(') {
496 plevel++;
497 } else if (c=='\\') {
498 if (*chptr=='\n') {
499 cheapp--;
500 getline();
501 }
502 // } else if (c==' '||c=='\t') {
503 // cheapp--;
504 } else if (c=='\n') {
505 cheapp--;
506 getline();
507 chptr = *pchptr;
508 }
509 } else if (c==')') {
510 plevel--;
511 } else if (c=='(') {
512 plevel++;
513 } else if (c=='\n') {
514 cheapp--;
515 getline();
516 chptr = *pchptr;
517 }
518 }
519 *pchptr = chptr;
520 *pcheapp = cheapp;
521 return reverse0(args);
522 }
523
524 /* output macro expansion result into macrobuf (macropp) */
525
526 static int
527 macro_function(int macrop,char **pchptr,NMTBL *nptr,int history)
528 {
529 int args,sargs,values,evalues;
530 char *macro;
531
532 sargs = args = cadr(nptr->dsp);
533 values = macro_args(&macropp,macro_buf+MACROSIZE,pchptr);
534 if (pchptr==&chptr) {
535 ch = *chptr++;
536 }
537 evalues = 0;
538 while(values) {
539 evalues = list2(macro_eval(0,(char *)car(values),history),evalues);
540 values = cadr(values);
541 }
542 evalues = reverse0(evalues);
543 while(args) {
544 local_define((char *)car(args),mappend(reverse0(car(evalues))));
545 /* fprintf(stderr,"%s: %s => %s\n",nptr->nm,(char *)car(args),(char *)car(msearch0((char *)car(args))->dsp)); */
546 args = cadr(args);
547 evalues = cadr(evalues);
548 }
549 macro = (char *)car(nptr->dsp);
550 macrop = macro_eval(macrop,macro,list2((int)macro,history));
551 /* fprintf(stderr,"%s: result %s => %s\n",nptr->nm,macro,(char *)car(macrop)); */
552 args = sargs;
553 while(args) {
554 local_undef((char *)car(args));
555 args = cadr(args);
556 }
557 return macrop;
558 }
559
560 static void
561 local_define(char *macro,char *value)
562 {
563 NMTBL *nptr0;
564 while(*macro==' '||*macro=='\t') macro++;
565 nptr0 = msearch0(macro);
566 /* save nptr previous contents in a list */
567 nptr0->ty=list3(nptr0->sc,nptr0->ty,nptr0->dsp);
568 /* set new value */
569 nptr0->sc=LMACRO;
570 nptr0->dsp=list2((int)value,0);
571 }
572
573 static void
574 local_undef(char *macro)
575 {
576 NMTBL *nptr0;
577 int save;
578 nptr0 = msearch0(macro);
579 save = nptr0->ty;
580 nptr0->sc=car(save);
581 nptr0->dsp=caddr(save);
582 nptr0->ty=cadr(save);
583 }
584
585 static int
586 macro_eval(int macrop,char *body0,int history)
587 {
588 int c;
589 int in_quote = 0;
590 int in_wquote = 0;
591 char *macro;
592 char *body = body0;
593 int i;
594 NMTBL *nptrm;
595 macrop = list2((int)macropp,macrop);
596 for(; (c = *body++) ;) {
597 if (macropp+1>macro_buf+MACROSIZE) error(STRERR);
598 if (in_quote) {
599 if (c=='\\') {
600 *macropp++ = c; c = *body++;
601 } else if (c=='\'') {
602 in_quote = 0;
603 }
604 } else if (in_wquote) {
605 if (c=='\\') {
606 *macropp++ = c; c = *body++;
607 } else if (c=='"') {
608 in_wquote = 0;
609 }
610 } else if (c=='"') {
611 in_wquote = 1;
612 } else if (c=='\'') {
613 in_quote = 1;
614 } else if (c=='#' && *body=='#') {
615 // name concatenation. skip ## and re-eval macro line.
616 mconcat = 1; body++; continue;
617 } else if (alpha(c)) {
618 i = 0;
619 do { namebuf[i++] = c; c=*body++;} while (alpha(c)||digit(c));
620 body--; // ungetc
621 namebuf[i]=0;
622 nptrm = msearch0(namebuf);
623 macro = (char *)car(nptrm->dsp);
624 if (nptrm->sc==LMACRO) {
625 while((*macropp++ = *macro++));
626 macropp--;
627 } else if (nptrm->sc==MACRO && neqname(namebuf,macro)) {
628 if (macro[0]==0) continue;
629 *macropp++=0;
630 macrop=macro_eval(macrop,macro,list2((int)macro,history));
631 macrop = list2((int)macropp,macrop);
632 } else if (nptrm->sc==FMACRO) {
633 if (c==' '||c=='\t') {
634 while (c==' '||c=='\t') c=*body++;
635 body--;
636 }
637 if(c!='(') error(MCERR);
638 *macropp++=0; body++;
639 macrop = macro_function(macrop,&body,nptrm,
640 list2((int)macro,history));
641 macrop = list2((int)macropp,macrop);
642 } else {
643 macro = namebuf;
644 while((*macropp++ = *macro++));
645 macropp--;
646 }
647 continue;
648 }
649 *macropp++ = c;
650 }
651 *macropp++=0;
652 return macrop;
653 }
654
655
656 static char *
657 mappend(int lists)
658 {
659 char *p;
660 char *result = macropp;
661 while(lists) {
662 if (macropp>macro_buf+MACROSIZE) error(STRERR);
663 p = (char *)car(lists);
664 while((*macropp++=*p++)) if (p[-1]=='\n') macropp[-1]=' ';
665 macropp--;
666 lists = cadr(lists);
667 }
668 macropp++;
669 return result;
670 }
671
672 /* end */