1 /* ******************************** */
\r
2 /* PER UNA CORRETTA VISUALIZZAZIONE */
\r
4 /* ******************************** */
\r
6 /* - stati del preprocessore */
\r
10 /* - discard dei commenti / * ... * / */
\r
15 /* ************************************************************************* */
\r
21 /* ************************************************************************* */
\r
23 #define MAX_DEPTH 1000 /* numero massimo di annidamenti */
\r
25 #define ERR_EXIT 0 /* uscita ok */
\r
26 #define OK_EXIT 1 /* uscita errore */
\r
28 #define SEP '\n' /* separatore dei campi in output */
\r
30 #define EXP_OPT "-e" /* opzione di solo preprocessing */
\r
32 /* stringhe di errore */
\r
33 #define ERR_UNK "ScanError:UnknownToken"
\r
34 #define ERR_OPT "ScanError:UnknownOption"
\r
35 #define ERR_NL "ScanError:UnexptedNewline"
\r
36 #define ERR_STR "ScanError:EmptyString"
\r
37 #define ERR_CHR "ScanError:EmptyChar"
\r
38 #define ERR_ALR "ScanError:RepeatedDefine"
\r
39 #define ERR_MANYCHR "ScanError:TooManyChars"
\r
40 #define ERR_INC "ScanError:TooManyExpansionsOrNestings"
\r
41 #define ERR_MIS "ScanError:MissingIncludeFile"
\r
42 #define ERR_MEM "ScanError:OutOfMemory"
\r
43 #define ERR_ARG "ScanError:IncorrectArgumentNumber"
\r
44 #define ERR_OPEN "ScanError:FileNotFound"
\r
45 #define ERR_UNA "ScanError:UnallowedExpansion"
\r
46 #define ERR_UNE "ScanError:Unexpected(#endif)"
\r
47 #define ERR_UNS "ScanError:Unexpected(#switch)"
\r
48 #define ERR_END "ScanError:Missing(#endif)"
\r
49 #define ERR_LOP "ScanError:ExpansionLoopDetected"
\r
50 #define ERR_RES "ScanError:ReservedToken"
\r
52 /* ************************************************************************* */
\r
54 /* elemento lista dei token */
\r
55 typedef struct listElem
\r
58 struct listElem *next;
\r
61 /* elemento lista delle espansioni */
\r
62 typedef struct defElem
\r
66 struct defElem *next;
\r
69 /* ************************************************************************* */
\r
71 YY_BUFFER_STATE inStream[MAX_DEPTH]; /* buffer: input stream buffer */
\r
72 int inNesting=0; /* contatore: livello di annidamento */
\r
73 char inName[MAX_DEPTH][257]; /* buffer: nomi dei sorgenti */
\r
74 int inLine[MAX_DEPTH]; /* buffer: linea corrente */
\r
75 int inRow[MAX_DEPTH]; /* buffer: colonna corrente */
\r
77 listELEM *rootElem=NULL,*curElem=NULL; /* lista dei token */
\r
78 defELEM *rootDef=NULL,*curDef=NULL; /* lista delle espansioni */
\r
80 int stringFound; /* flag: stringa non vuota */
\r
81 int charFound; /* flag: carattere non vuoto */
\r
82 int expand=0; /* flag: espansione in corso */
\r
83 int startExpansion; /* variabile: espansione iniziale (per evitare loop) */
\r
84 int eatTrueEndif=0; /* contatore: #endif validi (a seguito di true) */
\r
85 int eatFalseEndif=0; /* contatore: #endif validi (a seguito di false) */
\r
86 int expOnly=0; /* flag: preprocessare senza generare token */
\r
88 char tempBuf[2000]; /* spazio temporaneo per formattare l'output/error */
\r
90 /* espansioni riservate */
\r
111 /* ************************************************************************* */
\r
113 void addOkBuf(char *token,char *ytext);
\r
114 void errExit(char *ytext);
\r
115 void addDefId(char *ytext);
\r
116 int checkDefId(char *ytext);
\r
117 void checkRsvd(char *ytext);
\r
118 void delDefId(char *ytext);
\r
119 void addDefTxt(char *ytext);
\r
120 void usage(char *name);
\r
122 /* ************************************************************************* */
\r
126 KEYWORD ("array"|"of"|"struct"|"if"|"elsif"|"else"|"while"|"const"|"b2w"|"b2dw"|"w2b"|"w2dw"|"dw2b"|"dw2w")
\r
127 TYPE ("byte"|"word"|"dword")
\r
128 BRACKET ("{"|"}"|"["|"]"|"("|")")
\r
130 DUALOP ("&"|"|"|"^"|"+"|"-"|"*"|"/"|"!="|"=="|"<"|">"|"<="|">="|"<<"|">>"|"=")
\r
131 SEPARATOR (";"|"."|",")
\r
133 IDWORD ("0x"[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9])
\r
134 IWORD ("0x"[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9])
\r
135 IBYTE ("0x"[a-fA-F0-9][a-fA-F0-9])
\r
137 ID ([_a-zA-Z][_a-zA-Z0-9]*)
\r
142 /* ************************************************************************* */
\r
146 <INITIAL>"#define" {
\r
147 /* ************** */
\r
148 /* DEFINIZIONE ID */
\r
149 /* ************** */
\r
152 { sprintf(tempBuf,"%s",ERR_UNA); errExit(tempBuf); exit(ERR_EXIT); }
\r
154 inRow[inNesting]+=yyleng;
\r
157 <defbegin>{BLANK}+ { inRow[inNesting]+=yyleng; }
\r
158 <defbegin>{ID} { checkRsvd(yytext); addDefId(yytext); inRow[inNesting]+=yyleng; BEGIN(defend); }
\r
159 <defbegin>{NL} { sprintf(tempBuf,"%s",ERR_NL); errExit(tempBuf); exit(ERR_EXIT); }
\r
160 <defbegin>. { sprintf(tempBuf,"%s(%s)",ERR_UNK,yytext); errExit(tempBuf); exit(ERR_EXIT); }
\r
161 <defend>[^\r\n]+ { addDefTxt(yytext); inRow[inNesting]+=yyleng; }
\r
162 <defend>{NL} { inLine[inNesting]++; inRow[inNesting]=1; BEGIN(INITIAL); }
\r
167 /* *************** */
\r
168 /* INIZIO COMMENTO */
\r
169 /* *************** */
\r
172 { inRow[inNesting]+=yyleng; }
\r
178 { sprintf(tempBuf,"%s",ERR_NL); errExit(tempBuf); exit(ERR_EXIT); }
\r
180 inLine[inNesting]++;
\r
181 inRow[inNesting]=1;
\r
183 <combegin>[^\r\n] {
\r
185 { inRow[inNesting]+=yyleng; }
\r
189 { inRow[inNesting]+=yyleng; }
\r
196 <INITIAL>{KEYWORD} {
\r
197 /* ******************** */
\r
198 /* TOKEN DEL LINGUAGGIO */
\r
199 /* ******************** */
\r
201 addOkBuf("KEW",yytext);
\r
204 { inRow[inNesting]+=yyleng; }
\r
207 addOkBuf("TYP",yytext);
\r
210 { inRow[inNesting]+=yyleng; }
\r
212 <INITIAL>{BRACKET} {
\r
213 addOkBuf("BRK",yytext);
\r
216 { inRow[inNesting]+=yyleng; }
\r
218 <INITIAL>{MONOOP} {
\r
219 addOkBuf("MOP",yytext);
\r
222 { inRow[inNesting]+=yyleng; }
\r
224 <INITIAL>{DUALOP} {
\r
225 addOkBuf("DOP",yytext);
\r
228 { inRow[inNesting]+=yyleng; }
\r
230 <INITIAL>{SEPARATOR} {
\r
231 addOkBuf("SEP",yytext);
\r
234 { inRow[inNesting]+=yyleng; }
\r
236 <INITIAL>{IDWORD} {
\r
237 addOkBuf("W32",yytext);
\r
240 { inRow[inNesting]+=yyleng; }
\r
243 addOkBuf("W16",yytext);
\r
246 { inRow[inNesting]+=yyleng; }
\r
249 addOkBuf("BY8",yytext);
\r
252 { inRow[inNesting]+=yyleng; }
\r
255 addOkBuf("INU",yytext);
\r
258 { inRow[inNesting]+=yyleng; }
\r
264 /* ********************* */
\r
265 /* TOKEN ID O ESPANSIONE */
\r
266 /* ********************* */
\r
272 for(index=0,tmp=rootDef;tmp;tmp=tmp->next,index++)
\r
274 if(!strcmp(tmp->defId,yytext))
\r
278 /* Prima espansione */
\r
281 startExpansion=index;
\r
284 /* Espansione dentro un'espansione */
\r
285 else if(startExpansion!=index)
\r
287 /* Loop detected */
\r
289 { sprintf(tempBuf,"%s",ERR_LOP); errExit(tempBuf); exit(ERR_EXIT); }
\r
298 if(inNesting>=MAX_DEPTH)
\r
299 { sprintf(tempBuf,"%s",ERR_INC); errExit(tempBuf); exit(ERR_EXIT); }
\r
301 inStream[inNesting++]=YY_CURRENT_BUFFER;
\r
302 inLine[inNesting]=inLine[inNesting-1];
\r
303 inRow[inNesting]=inRow[inNesting-1];
\r
305 { inRow[inNesting-1]+=yyleng; }
\r
306 strcpy(inName[inNesting],inName[inNesting-1]);
\r
308 /* cambio di input stream -> espansione */
\r
310 { yy_scan_string(tmp->defTxt); }
\r
312 { yy_scan_string(""); }
\r
317 addOkBuf("IID",yytext);
\r
320 { inRow[inNesting]+=yyleng; }
\r
326 <INITIAL>{BLANK}+ {
\r
327 /* **************** */
\r
328 /* NEW LINE E BLANK */
\r
329 /* **************** */
\r
332 { printf("%s",yytext); }
\r
334 { inRow[inNesting]+=yyleng; }
\r
338 { printf("%s",yytext); }
\r
340 { sprintf(tempBuf,"%s",ERR_NL); errExit(tempBuf); exit(ERR_EXIT); }
\r
342 inLine[inNesting]++;
\r
343 inRow[inNesting]=1;
\r
348 <INITIAL,defend><<EOF>> {
\r
349 /* **************************************** */
\r
350 /* EOF = FINE DI UN'ESPANSIONE O INCLUSIONE */
\r
351 /* **************************************** */
\r
353 if((--inNesting)<0)
\r
355 if(eatTrueEndif||eatFalseEndif)
\r
356 { ++inNesting; sprintf(tempBuf,"%s",ERR_END); errExit(tempBuf); exit(ERR_EXIT); }
\r
362 yy_delete_buffer(YY_CURRENT_BUFFER);
\r
363 yy_switch_to_buffer(inStream[inNesting]);
\r
373 /* ************************** */
\r
374 /* CARATTERE NON RICONOSCIUTO */
\r
375 /* ************************** */
\r
377 sprintf(tempBuf,"%s(%s)",ERR_UNK,yytext);
\r
384 /* ************************************************************************* */
\r
386 /* formattazione dell'errore ed uscita */
\r
387 void errExit(char *ytext)
\r
389 printf("%s:%d,%d\tERR\t%s\t%c",inName[inNesting],inLine[inNesting],inRow[inNesting],ytext,SEP);
\r
392 /* ************************************************************************* */
\r
394 /* controllo se ID e' gia' stato definito come espansione */
\r
395 int checkDefId(char *ytext)
\r
399 for(tmp=rootDef;tmp;tmp=tmp->next)
\r
401 if(!strcmp(tmp->defId,ytext))
\r
408 /* ************************************************************************* */
\r
410 /* controllo se ID corrisponde ad un elemento di reserved[] */
\r
411 void checkRsvd(char *ytext)
\r
415 for(index=0;reserved[index];index++)
\r
417 if(!strcmp(reserved[index],ytext))
\r
418 { sprintf(tempBuf,"%s(%s)",ERR_RES,yytext); errExit(tempBuf); exit(ERR_EXIT);}
\r
424 /* ************************************************************************* */
\r
426 /* allocazione di ID come nuova espansione */
\r
427 void addDefId(char *ytext)
\r
431 if(!(curDef=rootDef=(defELEM *) malloc(sizeof(defELEM))))
\r
432 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
438 for(tmp=rootDef;tmp;tmp=tmp->next)
\r
440 if(!strcmp(tmp->defId,ytext))
\r
441 { sprintf(tempBuf,"%s",ERR_ALR); errExit(tempBuf); exit(ERR_EXIT); }
\r
444 if(!(curDef->next=(defELEM *) malloc(sizeof(defELEM))))
\r
445 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
447 curDef=curDef->next;
\r
451 curDef->defTxt=NULL;
\r
453 if(!(curDef->defId=(char *) malloc(strlen(ytext)+1)))
\r
454 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
456 strcpy(curDef->defId,ytext);
\r
461 /* ************************************************************************* */
\r
463 /* rimozione di ID come espansione */
\r
464 void delDefId(char *ytext)
\r
466 defELEM *tmp,*prevTmp;
\r
468 for(prevTmp=NULL,tmp=rootDef;tmp;prevTmp=tmp,tmp=tmp->next)
\r
470 if(!strcmp(tmp->defId,ytext))
\r
474 prevTmp->next=tmp->next;
\r
478 { free(tmp->defTxt); }
\r
487 { free(tmp->defTxt); }
\r
498 /* ************************************************************************* */
\r
500 /* definizione del testo dell'espansione di ID */
\r
501 void addDefTxt(char *ytext)
\r
503 if(!(curDef->defTxt=(char *) malloc(strlen(ytext)+1)))
\r
504 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
506 strcpy(curDef->defTxt,ytext);
\r
511 /* ************************************************************************* */
\r
513 /* formattazione e aggiunta di yytext alla lista dei token */
\r
514 void addOkBuf(char *token,char *ytext)
\r
517 { printf("%s",ytext); }
\r
520 sprintf(tempBuf,"%s:%d,%d\t%s\t%s\t%c",inName[inNesting],inLine[inNesting],inRow[inNesting],token,ytext,SEP);
\r
524 if(!(curElem=rootElem=(listELEM *) malloc(sizeof(listELEM))))
\r
525 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
529 if(!(curElem->next=(listELEM *) malloc(sizeof(listELEM))))
\r
530 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
532 curElem=curElem->next;
\r
535 curElem->next=NULL;
\r
537 if(!(curElem->scanTxt=(char *) malloc(strlen(tempBuf)+1)))
\r
538 { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }
\r
540 strcpy(curElem->scanTxt,tempBuf);
\r
546 /* ************************************************************************* */
\r
548 void usage(char *name)
\r
550 printf("\nC Scanner - Cosimo Oliboni\n\n");
\r
551 printf("\"%s -e source\" preprocessing di un sorgente\n",name);
\r
552 printf("\"%s source\" scanning di un sorgente\n",name);
\r
553 printf("\"%s\" scanning da stdin\n\n",name);
\r
558 /* ************************************************************************* */
\r
560 int main(int argc, char **argv)
\r
562 inLine[inNesting]=0;
\r
563 inRow[inNesting]=0;
\r
567 /* "scanner -e sorgente" */
\r
570 if(strcmp(argv[1],EXP_OPT))
\r
571 { sprintf(tempBuf,"%s",ERR_OPT); errExit(tempBuf); usage(argv[0]); exit(ERR_EXIT); }
\r
575 strcpy(inName[inNesting],argv[2]);
\r
577 /* "scanner sorgente" */
\r
579 { strcpy(inName[inNesting],argv[1]); }
\r
581 { sprintf(tempBuf,"%s",ERR_ARG); errExit(tempBuf); usage(argv[0]); exit(ERR_EXIT); }
\r
583 if(!(yyin=fopen(inName[inNesting],"r")))
\r
584 { sprintf(tempBuf,"%s(%s)",ERR_OPEN,inName[inNesting]); errExit(tempBuf); usage(argv[0]); exit(ERR_EXIT); }
\r
586 /* "scanner <stdin>" */
\r
588 { strcpy(inName[inNesting],"stdin"); }
\r
590 inLine[inNesting]=1;
\r
591 inRow[inNesting]=1;
\r
596 /* se non ci sono stati errori && se non si effettua solo preprocessing */
\r
597 /* output della lista di token creata */
\r
598 /* preceduta da OK && seguita da EOF */
\r
604 addOkBuf("EOF","EOF");
\r
606 printf("%s:0,0\tOK\tOK\t%c",inName[0],SEP);
\r
608 for(curElem=rootElem;curElem;curElem=curElem->next)
\r
609 { printf("%s",curElem->scanTxt); }
\r