Mercurial > hg > CbC > old > device
diff mc-macro.c @ 327:da2e3f2d127d
macro/codegen reorganization
author | kono |
---|---|
date | Mon, 21 Jun 2004 23:50:34 +0900 |
parents | |
children | 11f8f2e6bb72 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mc-macro.c Mon Jun 21 23:50:34 2004 +0900 @@ -0,0 +1,672 @@ +/* Micro-C Preprocessor Part */ /* $Id$ */ + +#include <stdio.h> +#include "mc.h" +#include "mc-parse.h" +#include "mc-macro.h" +#include "mc-code.h" + +extern struct {int fd,ln;char *name0;int inc;FILE *fcb;} *filep,filestack[FILES]; + +int in_macro_if = 0; +char *chinput; + +static char *macropp,macro_buf[MACROSIZE]; +static int mconcat=0; + +static void macro_define0(); +static int macro_args(char **pcheapp,char *maxcheap,char **pchptr); +static int macro_function(int macrop,char **pchptr,NMTBL *nptr,int history); +static void local_define(char *macro,char *value); +static void local_undef(char *macro); +static int macro_eval(int macrop,char *body0,int history); +static char * mappend(int lists); +static int macro_processing(); + +static void +gen_source(char *s) +{ + printf("%s",s); +} + +extern void +macro_expansion(NMTBL *nptrm) +{ + int i = mode; + int macrop = 0; + int slfree = lfree; + mode = STAT; + + macropp = macro_buf; + if (nptrm->sc == FMACRO) { + macrop=macro_function(macrop,&chptr,nptrm,0); + } else { + macrop=macro_eval(macrop,(char *)car(nptrm->dsp),0); + } + macropp = macro_buf; + mappend(reverse0(macrop)); + macropp[-1] ='\n'; + *macropp =0; + while (mconcat) { + // ## re-eval macro + printf("## %s",macro_buf); + mconcat = 0; + macrop = 0; + macropp = macro_buf; + macrop=macro_eval(macrop,macro_buf,0); + macropp = macro_buf; + mappend(reverse0(macrop)); + macropp[-1] ='\n'; + *macropp =0; + } + mconcat = 0; + lfree = slfree; + if (lsrc && !asmf && nptrm->sc==FMACRO) gen_comment(macro_buf); + macropp[-1] =0; + if (macro_buf[0]==0) { + mode = i; + return; + } + chptrsave = glist2((int)chptr,chptrsave); + chsave = glist2(ch,chsave); + chptr = macro_buf; + ch = *chptr++; + mode = i; +} + +/* file inclusion */ + +static char * +expand_file_name(char *path,char *name,int pos,int lbufsize) +{ + char *p = name+pos; + int i,j; + j = 0; + for(i=0;path[i];i++,j++); for(i=0;name[i];i++,j++); + if (pos+j+1>lbufsize) { error(FILERR); return ""; } + while((name[pos++] = *path++)); + pos--; + if (name[pos]!='/') name[pos]='/'; + for(i = 0; ((name[pos++] = name[i++]));); + return p; +} + +static FILE * +getfname(void) +{ + int i,end='"',err=0; + char *s,*p,**pp,name[LBUFSIZE]; + FILE *fp; + + getch(); + if(skipspc()=='"') { end = '"'; + } else if (ch=='<') { end = '>'; + } else { error(INCERR); err=1; + } + for(i=0;(getch()!=end && ch!='\n');) { + if(i<LBUFSIZE-1) name[i++]=ch; + } + if(ch=='\n') error(INCERR); + if (err) return filep->fcb; + name[i]=0; + fp = fopen(name,"r") ; + if (fp) { + p = name; + } else { + for(pp=(end=='>'||filep->inc=='>') + ?l_include_path:include_path;*pp;pp++) { + p = expand_file_name(*pp,name,i+1,LBUFSIZE); + if ((fp = fopen(p,"r"))) break ; + } + } + if(!fp) { error(FILERR); return filep->fcb; } + copy_current_file_dir(s=p); + (filep+1)->name0 = cheapp; + (filep+1)->inc = end; + while((*cheapp++ = *s++)); + return ( (filep+1)->fcb = fp ); +} + +/* line input and conversion */ + +static int macro_if_depth ; +static int macro_if_current ; +static int macro_if_skip ; + +static int +skip_rest_of_line() +{ + getch(); + do { + while(ch!='\n'&&ch!='\r') { + if (!in_comment) { + if (ch=='/') { + getch(); + if (ch=='/') in_comment=2; + else if (ch=='*') { + in_comment=1; + } else continue; + } + } else if (ch=='*') { + getch(); + if (ch=='/') { + in_comment=0; + return macro_if_skip?0:1; + } + else continue; + } + getch(); + } + if (in_comment==1) { getline(); getch(); } + } while(in_comment==1); + in_comment=0; + return 0; +} + +extern void +getline(void) +{ + int i; + int c; + + do { + if (chinput) { + if (! *chinput) { + chinput=0; + continue; + } + chptr=linebuf; + i=0; + while((*chptr++=c=*chinput++)&&(c!='\n')) { + if (++i > LBUFSIZE-2) error(LNERR); + } + } else { + lineno++; + glineno++; + chptr=linebuf; + i=0; + while ((*chptr++ = c = getc(filep->fcb)) != '\n') { + if (++i > LBUFSIZE-2) error(LNERR); + if (c==EOF) { + error(EOFERR); + --chptr; + } + } + } + *chptr = '\0'; + if (lsrc && !asmf && !macro_if_skip) gen_comment(linebuf); + if (*(chptr = linebuf) == '#' && !in_comment && !in_quote) { + if (macro_processing()) return; + } + } while(!in_quote && (macro_if_skip || linebuf[0] == '#')); +} + +/* preprocessor directive */ + +/* line continuation \\ */ + +extern void +check_macro_eof() +{ + int c; + for(c=0;c<LBUFSIZE-3&&chptr[c];c++); + if (c>0&&chptr[c-1]=='\\') { + return; + } else if (c>0&&chptr[c-1]=='\n') { + if (c>0&&chptr[c-2]=='\\') { + return; + } else { + c--; + } + } + chptr[c] = ';'; + chptr[c+1] = '\n'; + chptr[c+2] = 0; +} + +static void +macro_if() +{ + int i; + ch= *chptr; + in_macro_if = 1; + check_macro_eof(); + getsym(0); + /* i=cexpr(expr(1)); #if allow undefined symbols.. */ + i=expr(1); + in_macro_if = 0; + if (car(i)==CONST) i=cadr(i); + else i=0; + if (ch) { + if (chptr[-1]==ch) { + /* we are fall into getch(), which lost the last ch */ + /* chptr[-1]==ch check is fanatic, but ... */ + chptr--; + } else error(-1); + } + macro_if_depth = macro_if_current; + macro_if_skip = !i; +} + +static int +macro_processing() +{ + int i; + int c; + int mode_save; + + ++chptr; + while (*chptr==' '||*chptr=='\t') ++chptr; + if (macroeq("ifdef") || macroeq("ifndef")) { + c = (chptr[-4]=='n'); + macro_if_current++; + if (!macro_if_skip) { + mode_save = mode; mode = IFDEF; + ch= *chptr; + i = getsym(0); + mode = mode_save; + macro_if_depth = macro_if_current; + macro_if_skip = (!i)^c; + } + return 0; + } else if (macroeq("elif")) { + if (macro_if_current==0) { + error(MCERR); /* extra #else */ + return 0; + } + if (macro_if_current == macro_if_depth) { + if (!macro_if_skip || macro_if_skip==2) { + macro_if_skip=2; + return 0; + } + macro_if(); + } + return 0; + } else if (macroeq("if")) { + macro_if_current++; + if (!macro_if_skip) { + macro_if(); + } + return 0; + } else if (macroeq("else")) { + if (macro_if_current==0) { + error(MCERR); /* extra #else */ + return 0; + } + if (macro_if_current == macro_if_depth) { + if (macro_if_skip==2) ; + else if (macro_if_skip) macro_if_skip=0; + else macro_if_skip=1; + } + return skip_rest_of_line(); + } else if (macroeq("endif")) { + if (macro_if_current == macro_if_depth) { + macro_if_skip = 0; + macro_if_depth = --macro_if_current; + } else { + if (macro_if_current<=0) { + error(MCERR); /* extra #if */ + return 0; + } + macro_if_current--; + } + return skip_rest_of_line(); + } + if (macro_if_skip) return 0; + if (macroeq("define")) { + ch= *chptr; + macro_define0(); + *(chptr = linebuf) = '\0'; + } else if (macroeq("undef")) { + i=mode; + mode=IFDEF; + ch= *chptr; + if (getsym(0)) { + if (nptr->sc == MACRO) { + nptr->sc = EMPTY; + } else if (nptr->sc == FMACRO) { + nptr->sc = EMPTY; + /* we cannot reclaim it's arg */ + } else error(MCERR); + } + mode=i; + } else if (macroeq("include")) { + if(filep+1 >= filestack + FILES) error(FILERR); + if ( ((filep+1)->fcb=getfname()) == NULL) error(FILERR); + (filep+1)->ln=lineno; + lineno=0; + ++filep; + *(chptr = linebuf) = '\0'; +#if ASM_CODE + } else if (macroeq("asm")) { + if (asmf) error(MCERR); + asmf = 1; + getline(); + while (asmf) { + gen_source(linebuf); + getline(); + } + } else if (macroeq("endasm")) { + if (!asmf) error(MCERR); + asmf = 0; +#endif + } else if (macroeq(" ")) + getline(); + else error(MCERR); + return 0; +} + +extern int +macroeq(char *s) +{ + char *p; + + for (p = chptr; *s;) if (*s++ != *p++) return 0; + chptr = p; + return 1; +} + +/* macro interpreter */ + +extern void +macro_define(char *macro) +{ + char *chptr_save; + int chsave; + + chptr_save = chptr; + chsave = ch; + chptr = macro; + ch= *chptr++; + macro_define0(); + chptr = chptr_save; + ch = chsave; +} + +static void +macro_define0() +{ + int i,args,c; + char *scheapp; + + i=mode; + mode=MDECL; + // ch= *chptr; ?? +// fprintf(stderr,"macro def: ch %c *chptr %c\n",ch,*chptr); + getsym(0); +// fprintf(stderr,"macro def: %s =>",name); + if (nptr->sc != EMPTY) { /* override existing macro */ + } + args = 0; + if (ch=='(') { + nptr->sc = FMACRO; + args = macro_args(&cheapp,cheap+CHEAPSIZE,&chptr); + } else { + nptr->sc = MACRO; + nptr->ty = -1; + } + // equal is allowed for -Dhoge=aho option + if (ch=='=') chptr++; + while((c=*chptr)==' '||c=='\t') chptr++; + nptr->dsp = list2((int)cheapp,args); /* macro body */ + scheapp = cheapp; + while ((*cheapp++ = c = *chptr++) + && c != '\n') { + if (c=='/'&&chptr[0]=='/') { + cheapp--; while(*chptr++); break; + } else if (c=='/'&&chptr[0]=='*') { + cheapp--; chptr++; + while((c = *chptr++)) { + if (c=='*'&&chptr[0]=='/') { + c = *chptr++; break; + } + } + if (!c) break; + } else if (c=='\\' && (*chptr=='\n'||*chptr==0)) { + chptr++; + cheapp--; + getline(); + } + } + *cheapp++ = '\0'; + while(cheapp>scheapp&&(*cheapp=='\n'||*cheapp==0)) cheapp--; + *++cheapp = '\0'; cheapp++; + if (cheapp >= cheap+CHEAPSIZE) /* too late? */ + error(STRERR); +// fprintf(stderr,"%s\n",(char *)car(nptr->dsp)); + mode=i; +} + +// create function macro argument list +// return list2((char*)arg,next) + +static int +macro_args(char **pcheapp,char *maxcheap,char **pchptr) +{ + int c; + int in_quote = 0; + int in_wquote = 0; + int plevel = 0; + char *cheapp = *pcheapp; + char *chptr = *pchptr; + int args = list2((int)cheapp,0); + for(;;) { + *cheapp++ = c = *chptr++; + if (cheapp >= maxcheap) error(MCERR); + if (!c) { + chptr--; + error(MCERR); + *pchptr = chptr; + *pcheapp = cheapp; + return reverse0(args); + } + if (in_quote) { + if (c=='\\') { + if (*chptr != '\n') { + *cheapp++ = *chptr++; + } else { + getline(); + } + } else if (c=='\'') { + in_quote = 0; + } + } else if (in_wquote) { + if (c=='\\') { + if (*chptr !='\n') { + *cheapp++ = *chptr++; + } else { + *cheapp = '\n'; + getline(); + } + } else if (c=='"') { + in_wquote = 0; + } + } else if (c=='"') { + in_wquote = 1; + } else if (c=='\'') { + in_quote = 1; + } if (plevel==0) { + if (c==',') { + cheapp[-1] = 0; + args = list2((int)cheapp,args); + } else if (c==')') { + cheapp[-1] = 0; + break; + } else if (c=='(') { + plevel++; + } else if (c=='\\') { + if (*chptr=='\n') { + cheapp--; + getline(); + } +// } else if (c==' '||c=='\t') { +// cheapp--; + } else if (c=='\n') { + cheapp--; + getline(); + chptr = *pchptr; + } + } else if (c==')') { + plevel--; + } else if (c=='(') { + plevel++; + } else if (c=='\n') { + cheapp--; + getline(); + chptr = *pchptr; + } + } + *pchptr = chptr; + *pcheapp = cheapp; + return reverse0(args); +} + +/* output macro expansion result into macrobuf (macropp) */ + +static int +macro_function(int macrop,char **pchptr,NMTBL *nptr,int history) +{ + int args,sargs,values,evalues; + char *macro; + + sargs = args = cadr(nptr->dsp); + values = macro_args(¯opp,macro_buf+MACROSIZE,pchptr); + if (pchptr==&chptr) { + ch = *chptr++; + } + evalues = 0; + while(values) { + evalues = list2(macro_eval(0,(char *)car(values),history),evalues); + values = cadr(values); + } + evalues = reverse0(evalues); + while(args) { + local_define((char *)car(args),mappend(reverse0(car(evalues)))); +/* fprintf(stderr,"%s: %s => %s\n",nptr->nm,(char *)car(args),(char *)car(msearch0((char *)car(args))->dsp)); */ + args = cadr(args); + evalues = cadr(evalues); + } + macro = (char *)car(nptr->dsp); + macrop = macro_eval(macrop,macro,list2((int)macro,history)); +/* fprintf(stderr,"%s: result %s => %s\n",nptr->nm,macro,(char *)car(macrop)); */ + args = sargs; + while(args) { + local_undef((char *)car(args)); + args = cadr(args); + } + return macrop; +} + +static void +local_define(char *macro,char *value) +{ + NMTBL *nptr0; + while(*macro==' '||*macro=='\t') macro++; + nptr0 = msearch0(macro); + /* save nptr previous contents in a list */ + nptr0->ty=list3(nptr0->sc,nptr0->ty,nptr0->dsp); + /* set new value */ + nptr0->sc=LMACRO; + nptr0->dsp=list2((int)value,0); +} + +static void +local_undef(char *macro) +{ + NMTBL *nptr0; + int save; + nptr0 = msearch0(macro); + save = nptr0->ty; + nptr0->sc=car(save); + nptr0->dsp=caddr(save); + nptr0->ty=cadr(save); +} + +static int +macro_eval(int macrop,char *body0,int history) +{ + int c; + int in_quote = 0; + int in_wquote = 0; + char *macro; + char *body = body0; + int i; + NMTBL *nptrm; + macrop = list2((int)macropp,macrop); + for(; (c = *body++) ;) { + if (macropp+1>macro_buf+MACROSIZE) error(STRERR); + if (in_quote) { + if (c=='\\') { + *macropp++ = c; c = *body++; + } else if (c=='\'') { + in_quote = 0; + } + } else if (in_wquote) { + if (c=='\\') { + *macropp++ = c; c = *body++; + } else if (c=='"') { + in_wquote = 0; + } + } else if (c=='"') { + in_wquote = 1; + } else if (c=='\'') { + in_quote = 1; + } else if (c=='#' && *body=='#') { + // name concatenation. skip ## and re-eval macro line. + mconcat = 1; body++; continue; + } else if (alpha(c)) { + i = 0; + do { namebuf[i++] = c; c=*body++;} while (alpha(c)||digit(c)); + body--; // ungetc + namebuf[i]=0; + nptrm = msearch0(namebuf); + macro = (char *)car(nptrm->dsp); + if (nptrm->sc==LMACRO) { + while((*macropp++ = *macro++)); + macropp--; + } else if (nptrm->sc==MACRO && neqname(namebuf,macro)) { + if (macro[0]==0) continue; + *macropp++=0; + macrop=macro_eval(macrop,macro,list2((int)macro,history)); + macrop = list2((int)macropp,macrop); + } else if (nptrm->sc==FMACRO) { + if (c==' '||c=='\t') { + while (c==' '||c=='\t') c=*body++; + body--; + } + if(c!='(') error(MCERR); + *macropp++=0; body++; + macrop = macro_function(macrop,&body,nptrm, + list2((int)macro,history)); + macrop = list2((int)macropp,macrop); + } else { + macro = namebuf; + while((*macropp++ = *macro++)); + macropp--; + } + continue; + } + *macropp++ = c; + } + *macropp++=0; + return macrop; +} + + +static char * +mappend(int lists) +{ + char *p; + char *result = macropp; + while(lists) { + if (macropp>macro_buf+MACROSIZE) error(STRERR); + p = (char *)car(lists); + while((*macropp++=*p++)) if (p[-1]=='\n') macropp[-1]=' '; + macropp--; + lists = cadr(lists); + } + macropp++; + return result; +} + +/* end */