#include #include #include #include #include #include "lexc.h" extern int filesrc_noline; #define MAX_ARG 250 /* Copie le texte jusqu'a la prochaine virgule ou ) ANSI : macro ne se font pas sur deux ligne ?? */ static char *near copyarg ( char *buffer, /* contiendra le paramètre */ int &lenbuf, // Contiendra le nombre de byte placé dans buffer char *line, /* tampon de lecture */ char *ptl, /* position de lecture dans le tampon */ char mrk1, /* terminateur possible */ char mrk2) /* autre terminateur possible */ { char *debbuf_loc = buffer; static char *debbuf; static int recur=0; static int errlen; if (recur == 0){ debbuf = buffer; errlen = 0; } recur++; while (*ptl != mrk1 && *ptl != mrk2){ int len = (int)(buffer - debbuf); if (len >= MAX_ARG){ errlen = 1; break; }else if (*ptl == MACRO_ACTIVE_CAR || *ptl == MACRO_DESACTIVE_CAR){ // #voir: macro / recursion / stratégie 2 memcpy (buffer,ptl,1+sizeof(DEF_SYM*)); ptl += 1 + sizeof(DEF_SYM*); buffer += 1 + sizeof(DEF_SYM*); }else if (!comment_skip(line,&ptl,0,0)){ if (*ptl == '\0'){ ptl = line; if (filesrc_fill (line)==-1){ lexcerr_bprintf ( "Fin de fichier rencontrée durant expansion macro\n" ,"End of file while expanding macro\n"); break; } }else if (*ptl == '"'){ ptl = token_copystring (buffer,ptl,MAX_ARG - len); buffer += strlen(buffer); }else if (*ptl == '\''){ ptl = token_copyquote (buffer,ptl,MAX_ARG - len); buffer += strlen(buffer); }else if (*ptl == '('){ *buffer++ = *ptl++; int len; ptl = copyarg (buffer,len,line,ptl,')',')'); buffer += len; if (*ptl == ')') *buffer++ = *ptl++; }else if (*ptl == '{'){ *buffer++ = *ptl++; int len; ptl = copyarg (buffer,len,line,ptl,'}','}'); buffer += len; if (*ptl == '}') *buffer++ = *ptl++; }else{ *buffer++ = *ptl++; } } } recur--; *buffer = '\0'; if (errlen && recur == 0){ lexcerr_bprintf ("Paramètre de macro trop long\n" ,"Macro parameter too long\n"); } lenbuf = (int)(buffer-debbuf_loc); return ptl; } #if 0 static void preproc_dump (const char *repl2) { while (*repl2 != '\0'){ if (*repl2 == MACRO_ACTIVE_CAR){ DEF_SYM *ptsym; repl2++; memcpy (&ptsym,repl2,sizeof(ptsym)); printf ("",ptsym->nomdef); repl2 += sizeof(ptsym); }else if (*repl2 == MACRO_DESACTIVE_CAR){ DEF_SYM *ptsym; repl2++; memcpy (&ptsym,repl2,sizeof(ptsym)); printf ("",ptsym->nomdef); repl2 += sizeof(ptsym); }else{ printf ("%c",*repl2++); } } } #endif /* Fait le remplacement des paramètres formels par les arguments La chaine de remplacement transformée avec les arguments est placé dans repl2 (static) et retourné. Retourne NULL si trouve pas de remplacement et signale erreur. */ char *preproc_expand ( char *line, // buffer de lecture char **pptl, // pointeur dans le buffer DEF_SYM *ptsym, // Definition de la macro int &lenrepl) // Contriendra la longueur de la chaine retourné // Cette chaine peut contenir des 0 parce qu'on // y met carrément des pointeur (activation de macro) { lenrepl = 0; char *ret = NULL; char **tbprm =ptsym->tbprm; /* paramètres formels */ int nbprm =ptsym->nbprm; /* nombre de paramètres */ char *repl =ptsym->repl; /* chaine de remplacement à expandre */ char *ptl = token_skipwhite(*pptl,line); if (*ptl == '('){ /* Retrouve les arguments actuel */ int nbarg = 0; struct { char *pt; int len; }tbarg[20]; char buffer[400]; char *ptbuf = buffer; /*#Specification: macro / argument vide Un argument vide est possible #define mac(a,b,c) ... mac(1,,2) est ok */ do { int len; tbarg[nbarg].pt = ptbuf; ptl++; /* saute ( ou , */ ptl = token_skipwhite (ptl,line); ptl = copyarg (ptbuf,len,line,ptl,',',')'); if (len == 0){ #if 1 if (nbarg == 0 && nbprm == 0 && *ptl == ')') break; #else if (*ptl == ')' && nbarg != 0){ lexcerr_bprintf ("Argument manquant\n","Missing argument\n"); nbarg = -1; } break; #endif } tbarg[nbarg].len = len; ptbuf += len+1; nbarg++; }while (*ptl == ','); /* Normalement *ptl == ')': sinon c'est la fin de fichier */ if (nbarg != nbprm){ lexcerr_bprintf ( "Macro %s utilisé avec nombre invalide de paramètre\n" ,"Invalid macro usage: %s\n",ptsym->nomdef); }else if (*ptl == ')'){ /* recherche les paramètres formels de la macro et remplace par arguments */ static char *repl2=NULL; char *ptrepl,*lastnonspace; if (repl2 == NULL) repl2 = (char*)malloc_err (10000,1); //printf ("repl = :%s:\n",repl); ptrepl = repl2; lastnonspace = repl2; ptl++; /* Elimine la parenthese */ while (*repl != '\0'){ int modestring = 0; if (*repl == '#'){ repl++; if (*repl == '#'){ /* Token paster */ repl++; *ptrepl = '\0'; #if 0 printf ("paster repl = :%s: repl2 = :",repl); preproc_dump(repl2); printf (":\n"); #endif while (isspace(*repl)) repl++; ptrepl = lastnonspace; #if 0 while (ptrepl > repl2 && isspace(ptrepl[-1])){ ptrepl--; } #endif *ptrepl = '\0'; #if 0 printf ("paster suite = :%s: repl2 :",repl); preproc_dump(repl2); printf (":\n"); #endif }else{ modestring = 1; } } if (isalpha(*repl) || *repl == '_'){ /* Identificateur trouvé, c'est peut-être un paramètre Il sera copié dans repl2, ou si son remplacement */ char prm[100]; repl = token_copyid(repl,prm); char *pt = NULL; int ptlen=0; int trouve=0; for (int i=0; inomdef); printf ("line :%s:\n",line); printf ("repl :%s:\n",ptsym->repl); printf ("lenrepl %d\n",ptsym->lenrepl); printf ("nbprm %d\n",ptsym->nbprm); exit (-1); } *pptl = ptl; return ret; }