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(&macropp,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 */