Mercurial > hg > CbC > old > device
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(¯opp,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 */ |