#include #include #include #include "lexc.h" extern int filesrc_noline; static int nbcond=0; static struct { char welse; /* 1 == else acceptable, 0 seulement endif */ char welif; /* 1 == elif acceptable */ char kill; /* a déjà été actif, ne peut plus l'être */ } tbcond[50]; int precond_actif=1; /* indique si génération des tokens actif */ static int precond_level=0; /* a quel niveau d'imbrication, la génération */ /* sera réactivé */ /* initialise les traitements des constructions conditionnelles #if,#else,... */ void precond_init (void) { nbcond = 0; precond_actif = 1; precond_level = 0; } /* Enregistre l'état d'un if : ce qu'il doit attendre et ce qu'il doit faire La valeur de welse et welif est: 0 : Il ne peut pas y avoir de else 1 : il peut y en avoir */ static void precond_setwait ( char welse, /* Attend pour un else */ char welif, /* attend pour un elif */ int repl, /* 0 : imbrique, 1 remplace etat courant */ int stop) /* Détermine si output doit arreter */ { if (!repl){ nbcond++; tbcond[nbcond].kill = 0; } tbcond[nbcond].welse = welse; tbcond[nbcond].welif = welif; if (stop){ if (precond_actif){ precond_actif = 0; precond_level = nbcond; } }else if (!precond_actif && precond_level == nbcond){ precond_actif = 1; } } /* Termine un imbrication et détermine si l'output doit etre reactivé */ static void near precond_endwait (void) { if (precond_level == nbcond){ precond_actif = 1; } nbcond--; } /* Traitement de la directive else Saute les énoncé jusqu'au endif */ char *precond_else (char *line, char *ptl) /* buffer */ { if (nbcond == 0 || !tbcond[nbcond].welse){ lexcerr_bprintf ("#else sans #if\n","#else without #if\n"); }else{ precond_setwait (0,0,1,tbcond[nbcond].kill || precond_actif); } precond_skipline(&ptl,line); return (ptl); } /* Enregistre un #endif, vérifie s'il est acceptable */ char *precond_endif (char *line, char *ptl) { if (nbcond == 0){ lexcerr_bprintf ("#endif sans #if\n","#endif without #if\n"); }else{ precond_endwait (); } precond_skipline (&ptl,line); return (ptl); } /* Saute les blancs et les commentaire dans une ligne Retourne != 0 si encore dans la meme ligne, 0 si sur une ligne suivante */ int precond_skipcom (char **ppt, char *line) { char *pt = str_skip (*ppt); int curlin = filesrc_noline; while (comment_skip(line,&pt,filesrc_noline,(int)(pt-line))){ /* Un ou plusieurs commentaires ont été sauté. Elimine ce commentaire s'il finissait sur la ligne courante. De cette façon, il ne sera pas associé au token suivant. */ if (filesrc_noline == curlin) comment_getlast(); pt = str_skip (pt); } *ppt = pt; return (filesrc_noline == curlin); } /* Saute la fin d'une ligne en tenant compte des commentaires Les commentaires peuvent continuer sur plusieurs lignes Retourne ptr sur dernier commentaire de la ligne ou sur '\0' */ char *precond_skipline (char **pptl, char *line) { char *ptl = *pptl; char *ret = ptl; int curlin = filesrc_noline; while (precond_skipcom(&ptl,line) && *ptl != '\0' && curlin == filesrc_noline){ if (*ptl == '"'){ ptl = token_skipstring(ptl); if (*ptl == '"') ptl++; }else if (*ptl == '\''){ ptl = token_skipquote(ptl); if (*ptl == '\'') ptl++; }else{ ptl++; } ret = ptl; } *pptl = ptl; return ret; } /* Evalue un ifdef ou un ifndef Retourne position de traitement dans la ligne */ char *precond_ifdef ( char *line, char *ptl, int mode) /* 0 : ifdef, 1 : ifndef */ { char txt[100]; int err = 1; if (precond_skipcom (&ptl,line)){ ptl = token_copyid (ptl,txt); if (txt[0] != '\0'){ DEF_SYM *pt = preproc_locate(txt); int stop=0; if ((pt == NULL && mode == 0) || (pt != NULL && mode == 1)){ /* condition fausse, on saute le contenu Note : Pas de elif pour ifdef ou ifndef */ stop = 1; } /* #Spécification: ifdef / elif A la demande générale, le préprocesseur accepte les #elif après un #ifdef. */ precond_setwait (1,1,0,stop); err = 0; } precond_skipline(&ptl,line); } if (err) lexcerr_bprintf ("directive #ifdef invalide\n%s\n" ,"Invalid #ifdef command\n%s\n",line); return (ptl); } /* Evalue un #if Retourne position de traitement dans la ligne après l'expression */ char *precond_if (char *line, char *ptl) { int stop = 1; if (precond_eval(&ptl,line)){ /* condition vrai */ stop = 0; } precond_setwait (1,1,0,stop); return (ptl); } /* Evalue un #elif Retourne position de traitement dans la ligne après l'expression */ char *precond_elif (char *line, char *ptl) { if (nbcond == 0 || !tbcond[nbcond].welif){ lexcerr_bprintf ("#elif sans #if\n","#elif without #if\n"); }else if (precond_actif || tbcond[nbcond].kill){ /* Désactive output jusqu'a la fin */ tbcond[nbcond].kill = 1; precond_setwait (1,1,1,1); precond_skipline(&ptl,line); }else{ int stop = 1; if (precond_eval(&ptl,line)){ /* condition vrai */ stop = 0; } precond_setwait (1,1,1,stop); } return (ptl); }