#include #include #include #include #include #include "lexc.h" #ifdef MSDOS #define COMMENT_BUFSIZ 20000 /* Taille de bufcom */ #else #define COMMENT_BUFSIZ 100000 /* Taille de bufcom */ #endif static char *bufcom=NULL; /* buffer pour accumulation de commentaire */ static char *acccom=NULL; /* pointeur d'accumulation */ static TOKCOM *lastcom=NULL;/* dernier commentaire reconnue */ /* Initialise ou réinitialise la collecte des commentaire. Les commentaires sont accumulés dans un tampon. Le contenu du tampon est oublié. */ export void comment_init(void) { acccom = bufcom; lastcom = NULL; } static int subcom = 1; /* Controle si les commentaires imbriquées sont permis ou pas imbriq != 0, permis, == 0, ignorés Pas défaut, il sont permis */ export void comment_setmode (int imbriq) { subcom = imbriq; } static char do_accum = 1; /* Controle l'enregistrement des commentaires. Retourne le mode courant. */ export int comment_setaccum (int mode) { int ret = do_accum; do_accum = (char)mode; return ret; } /* Saute un commentaire en le copiant Retourne la position de traitement après le commentaire */ static char * near comment_accum ( char *line, char *ptl) { *acccom++ = *ptl++; if (*ptl == '/'){ acccom = stpcpy (acccom,ptl); ptl += strlen(ptl); }else{ *acccom++ = *ptl++; while (1){ if (*ptl == '\0'){ assert ((int)(acccom-bufcom) < COMMENT_BUFSIZ); if (filesrc_fill(line)==-1){ lexcerr_bprintf ( "Fin de source rencontrée dans un commentaire\n" ,"End of file : Open comment\n"); break; } ptl = line; *acccom++ = '\n'; }else{ char carac = *ptl++; if (carac == '/' && *ptl == '*' && subcom){ ptl = comment_accum (line,ptl-1); }else if (carac == '*' && *ptl == '/'){ ptl++; break; }else{ *acccom++ = carac; } } } *acccom++ = '*'; *acccom++ = '/'; assert ((int)(acccom-bufcom) < COMMENT_BUFSIZ); } return ptl; } /* Saute un commentaire en le copiant Retourne la position de traitement après le commentaire */ static char * near comment_skip ( char *line, char *ptl) { ptl++; if (*ptl == '/'){ ptl += strlen(ptl); }else{ ptl++; while (1){ if (*ptl == '\0'){ if (filesrc_fill(line)==-1){ lexcerr_bprintf ( "Fin de source rencontrée dans un commentaire\n" ,"End of file : Open comment\n"); break; } ptl = line; }else{ char carac = *ptl++; if (carac == '/' && *ptl == '*' && subcom){ ptl = comment_skip (line,ptl-1); }else if (carac == '*' && *ptl == '/'){ ptl++; break; } } } } return ptl; } /* Les commentaires sont sautee, mais accumule. Le prochain token valide obtiendra le nouveau commentaire La routine tente de reconnaitre comme un seul commentaire les commentaires qui se suivent Si ptl ne pointe pas au début d'un commentaire, retourne sans rien faire Donc on peut appeler cette fonction sans vérifier qu'il y a un commentaire Supporte commentaire C++ Retourne 1 si un commentaire a été vue, 0 sinon */ int comment_skip ( char *line, char **pptl, int noline, int nocar) { int ret = 0; char *ptl = *pptl; if (ptl[0] == '/' && (ptl[1] == '*' || ptl[1] == '/')){ if (do_accum){ if (bufcom == NULL){ bufcom = (char*)malloc_err (COMMENT_BUFSIZ,1); acccom = bufcom; } assert (lastcom==NULL); { /* Alloue le TOKCOM dans le bufcom */ /* Assure l'alignement */ int offset = (int)(acccom-bufcom); size_align (offset,offset); lastcom = (TOKCOM*) (bufcom + offset); acccom = (char*) (lastcom + 1); } lastcom->noline = noline; lastcom->nocar = nocar; lastcom->texte = acccom; do{ ptl = comment_accum(line,ptl); *acccom++ = '\n'; /* saute les blancs a la recherche d'un autre commentaire */ ptl = token_skipwhite (ptl,line); }while (*ptl == '/' && (ptl[1] == '*' || ptl[1] == '/')); if (*(acccom-1) == '\n') acccom--; *acccom++ = '\0'; }else{ do{ ptl = comment_skip(line,ptl); /* saute les blancs a la recherche d'un autre commentaire */ ptl = token_skipwhite (ptl,line); }while (*ptl == '/' && (ptl[1] == '*' || ptl[1] == '/')); } *pptl = ptl; ret = 1; } return ret; } /* Retourne le dernier commentaire qui a été accumulé (oublie ensuite) */ TOKCOM *comment_getlast(void) { TOKCOM *tmp = lastcom; lastcom = NULL; return tmp; }