--- /dev/null
+/* ******************************** */\r
+/* PER UNA CORRETTA VISUALIZZAZIONE */\r
+/* tab size=4 */\r
+/* ******************************** */\r
+\r
+/* - stati del preprocessore */\r
+%x defbegin\r
+%x defend\r
+\r
+/* - discard dei commenti / * ... * / */\r
+%x combegin\r
+\r
+%{\r
+\r
+/* ************************************************************************* */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+/* ************************************************************************* */\r
+\r
+#define MAX_DEPTH 1000 /* numero massimo di annidamenti */\r
+\r
+#define ERR_EXIT 0 /* uscita ok */\r
+#define OK_EXIT 1 /* uscita errore */\r
+\r
+#define SEP '\n' /* separatore dei campi in output */\r
+\r
+#define EXP_OPT "-e" /* opzione di solo preprocessing */\r
+\r
+/* stringhe di errore */\r
+#define ERR_UNK "ScanError:UnknownToken"\r
+#define ERR_OPT "ScanError:UnknownOption"\r
+#define ERR_NL "ScanError:UnexptedNewline"\r
+#define ERR_STR "ScanError:EmptyString"\r
+#define ERR_CHR "ScanError:EmptyChar"\r
+#define ERR_ALR "ScanError:RepeatedDefine"\r
+#define ERR_MANYCHR "ScanError:TooManyChars"\r
+#define ERR_INC "ScanError:TooManyExpansionsOrNestings"\r
+#define ERR_MIS "ScanError:MissingIncludeFile"\r
+#define ERR_MEM "ScanError:OutOfMemory"\r
+#define ERR_ARG "ScanError:IncorrectArgumentNumber"\r
+#define ERR_OPEN "ScanError:FileNotFound"\r
+#define ERR_UNA "ScanError:UnallowedExpansion"\r
+#define ERR_UNE "ScanError:Unexpected(#endif)"\r
+#define ERR_UNS "ScanError:Unexpected(#switch)"\r
+#define ERR_END "ScanError:Missing(#endif)"\r
+#define ERR_LOP "ScanError:ExpansionLoopDetected"\r
+#define ERR_RES "ScanError:ReservedToken"\r
+\r
+/* ************************************************************************* */\r
+\r
+/* elemento lista dei token */\r
+typedef struct listElem\r
+ {\r
+ char *scanTxt;\r
+ struct listElem *next;\r
+ } listELEM;\r
+\r
+/* elemento lista delle espansioni */\r
+typedef struct defElem\r
+ {\r
+ char *defId;\r
+ char *defTxt;\r
+ struct defElem *next;\r
+ } defELEM;\r
+\r
+/* ************************************************************************* */\r
+\r
+YY_BUFFER_STATE inStream[MAX_DEPTH]; /* buffer: input stream buffer */\r
+int inNesting=0; /* contatore: livello di annidamento */\r
+char inName[MAX_DEPTH][257]; /* buffer: nomi dei sorgenti */\r
+int inLine[MAX_DEPTH]; /* buffer: linea corrente */\r
+int inRow[MAX_DEPTH]; /* buffer: colonna corrente */\r
+\r
+listELEM *rootElem=NULL,*curElem=NULL; /* lista dei token */\r
+defELEM *rootDef=NULL,*curDef=NULL; /* lista delle espansioni */\r
+\r
+int stringFound; /* flag: stringa non vuota */\r
+int charFound; /* flag: carattere non vuoto */\r
+int expand=0; /* flag: espansione in corso */\r
+int startExpansion; /* variabile: espansione iniziale (per evitare loop) */\r
+int eatTrueEndif=0; /* contatore: #endif validi (a seguito di true) */\r
+int eatFalseEndif=0; /* contatore: #endif validi (a seguito di false) */\r
+int expOnly=0; /* flag: preprocessare senza generare token */\r
+\r
+char tempBuf[2000]; /* spazio temporaneo per formattare l'output/error */\r
+\r
+/* espansioni riservate */\r
+char *reserved[]={\r
+ "array",\r
+ "of",\r
+ "struct",\r
+ "if",\r
+ "elsif",\r
+ "else",\r
+ "while",\r
+ "const",\r
+ "b2w",\r
+ "b2dw",\r
+ "w2b",\r
+ "w2dw",\r
+ "dw2b",\r
+ "dw2w",\r
+ "byte",\r
+ "word",\r
+ "dword",\r
+ NULL };\r
+\r
+/* ************************************************************************* */\r
+\r
+void addOkBuf(char *token,char *ytext);\r
+void errExit(char *ytext);\r
+void addDefId(char *ytext);\r
+int checkDefId(char *ytext);\r
+void checkRsvd(char *ytext);\r
+void delDefId(char *ytext);\r
+void addDefTxt(char *ytext);\r
+void usage(char *name);\r
+\r
+/* ************************************************************************* */\r
+\r
+%}\r
+\r
+KEYWORD ("array"|"of"|"struct"|"if"|"elsif"|"else"|"while"|"const"|"b2w"|"b2dw"|"w2b"|"w2dw"|"dw2b"|"dw2w")\r
+TYPE ("byte"|"word"|"dword")\r
+BRACKET ("{"|"}"|"["|"]"|"("|")")\r
+MONOOP ("!"|"~")\r
+DUALOP ("&"|"|"|"^"|"+"|"-"|"*"|"/"|"!="|"=="|"<"|">"|"<="|">="|"<<"|">>"|"=")\r
+SEPARATOR (";"|"."|",")\r
+\r
+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
+IWORD ("0x"[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9])\r
+IBYTE ("0x"[a-fA-F0-9][a-fA-F0-9])\r
+INUM ([0-9]+)\r
+ID ([_a-zA-Z][_a-zA-Z0-9]*)\r
+\r
+BLANK ([ \t])\r
+NL (\n|\r\n)\r
+\r
+/* ************************************************************************* */\r
+\r
+%%\r
+\r
+<INITIAL>"#define" {\r
+ /* ************** */\r
+ /* DEFINIZIONE ID */\r
+ /* ************** */\r
+\r
+ if(expand)\r
+ { sprintf(tempBuf,"%s",ERR_UNA); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ inRow[inNesting]+=yyleng;\r
+ BEGIN(defbegin);\r
+ }\r
+<defbegin>{BLANK}+ { inRow[inNesting]+=yyleng; }\r
+<defbegin>{ID} { checkRsvd(yytext); addDefId(yytext); inRow[inNesting]+=yyleng; BEGIN(defend); }\r
+<defbegin>{NL} { sprintf(tempBuf,"%s",ERR_NL); errExit(tempBuf); exit(ERR_EXIT); }\r
+<defbegin>. { sprintf(tempBuf,"%s(%s)",ERR_UNK,yytext); errExit(tempBuf); exit(ERR_EXIT); } \r
+<defend>[^\r\n]+ { addDefTxt(yytext); inRow[inNesting]+=yyleng; }\r
+<defend>{NL} { inLine[inNesting]++; inRow[inNesting]=1; BEGIN(INITIAL); }\r
+\r
+\r
+\r
+<INITIAL>"/*" {\r
+ /* *************** */\r
+ /* INIZIO COMMENTO */\r
+ /* *************** */\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ \r
+ BEGIN(combegin);\r
+ }\r
+<combegin>{NL} {\r
+ if(expand)\r
+ { sprintf(tempBuf,"%s",ERR_NL); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ inLine[inNesting]++;\r
+ inRow[inNesting]=1;\r
+ }\r
+<combegin>[^\r\n] {\r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<combegin>"*/" {\r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ \r
+ BEGIN(INITIAL);\r
+ }\r
+\r
+\r
+\r
+<INITIAL>{KEYWORD} {\r
+ /* ******************** */\r
+ /* TOKEN DEL LINGUAGGIO */\r
+ /* ******************** */\r
+\r
+ addOkBuf("KEW",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{TYPE} {\r
+ addOkBuf("TYP",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{BRACKET} {\r
+ addOkBuf("BRK",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{MONOOP} {\r
+ addOkBuf("MOP",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{DUALOP} {\r
+ addOkBuf("DOP",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{SEPARATOR} {\r
+ addOkBuf("SEP",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{IDWORD} {\r
+ addOkBuf("W32",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{IWORD} {\r
+ addOkBuf("W16",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{IBYTE} {\r
+ addOkBuf("BY8",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{INUM} {\r
+ addOkBuf("INU",yytext);\r
+ \r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+\r
+\r
+\r
+<INITIAL>{ID} {\r
+ /* ********************* */\r
+ /* TOKEN ID O ESPANSIONE */\r
+ /* ********************* */\r
+\r
+ defELEM *tmp;\r
+ int found=0;\r
+ int index;\r
+\r
+ for(index=0,tmp=rootDef;tmp;tmp=tmp->next,index++)\r
+ {\r
+ if(!strcmp(tmp->defId,yytext))\r
+ {\r
+ found=1;\r
+\r
+ /* Prima espansione */\r
+ if(!expand)\r
+ {\r
+ startExpansion=index;\r
+ break;\r
+ }\r
+ /* Espansione dentro un'espansione */\r
+ else if(startExpansion!=index)\r
+ { break; }\r
+ /* Loop detected */\r
+ else\r
+ { sprintf(tempBuf,"%s",ERR_LOP); errExit(tempBuf); exit(ERR_EXIT); }\r
+ }\r
+ }\r
+\r
+ /* espandi */\r
+ if(found)\r
+ {\r
+ expand++;\r
+\r
+ if(inNesting>=MAX_DEPTH)\r
+ { sprintf(tempBuf,"%s",ERR_INC); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ inStream[inNesting++]=YY_CURRENT_BUFFER;\r
+ inLine[inNesting]=inLine[inNesting-1];\r
+ inRow[inNesting]=inRow[inNesting-1];\r
+ if(expand<2)\r
+ { inRow[inNesting-1]+=yyleng; }\r
+ strcpy(inName[inNesting],inName[inNesting-1]);\r
+ \r
+ /* cambio di input stream -> espansione */\r
+ if(tmp->defTxt)\r
+ { yy_scan_string(tmp->defTxt); }\r
+ else\r
+ { yy_scan_string(""); }\r
+ }\r
+ /* genera token */\r
+ else\r
+ {\r
+ addOkBuf("IID",yytext);\r
+\r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+ }\r
+\r
+\r
+\r
+<INITIAL>{BLANK}+ {\r
+ /* **************** */\r
+ /* NEW LINE E BLANK */\r
+ /* **************** */\r
+\r
+ if(expOnly)\r
+ { printf("%s",yytext); }\r
+ if(!expand)\r
+ { inRow[inNesting]+=yyleng; }\r
+ }\r
+<INITIAL>{NL} {\r
+ if(expOnly)\r
+ { printf("%s",yytext); }\r
+ if(expand)\r
+ { sprintf(tempBuf,"%s",ERR_NL); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ inLine[inNesting]++;\r
+ inRow[inNesting]=1;\r
+ }\r
+\r
+\r
+\r
+<INITIAL,defend><<EOF>> {\r
+ /* **************************************** */\r
+ /* EOF = FINE DI UN'ESPANSIONE O INCLUSIONE */\r
+ /* **************************************** */\r
+\r
+ if((--inNesting)<0)\r
+ {\r
+ if(eatTrueEndif||eatFalseEndif)\r
+ { ++inNesting; sprintf(tempBuf,"%s",ERR_END); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ yyterminate();\r
+ }\r
+ else\r
+ {\r
+ yy_delete_buffer(YY_CURRENT_BUFFER);\r
+ yy_switch_to_buffer(inStream[inNesting]);\r
+ }\r
+\r
+ if(expand)\r
+ { expand--; }\r
+ }\r
+\r
+\r
+\r
+<INITIAL>. {\r
+ /* ************************** */\r
+ /* CARATTERE NON RICONOSCIUTO */\r
+ /* ************************** */\r
+ \r
+ sprintf(tempBuf,"%s(%s)",ERR_UNK,yytext);\r
+ errExit(tempBuf);\r
+ exit(ERR_EXIT);\r
+ } \r
+\r
+%%\r
+\r
+/* ************************************************************************* */\r
+\r
+/* formattazione dell'errore ed uscita */\r
+void errExit(char *ytext)\r
+{\r
+ printf("%s:%d,%d\tERR\t%s\t%c",inName[inNesting],inLine[inNesting],inRow[inNesting],ytext,SEP);\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+/* controllo se ID e' gia' stato definito come espansione */\r
+int checkDefId(char *ytext)\r
+{\r
+ defELEM *tmp;\r
+\r
+ for(tmp=rootDef;tmp;tmp=tmp->next)\r
+ {\r
+ if(!strcmp(tmp->defId,ytext))\r
+ { return(1); }\r
+ }\r
+\r
+ return(0);\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+/* controllo se ID corrisponde ad un elemento di reserved[] */\r
+void checkRsvd(char *ytext)\r
+{\r
+ int index;\r
+\r
+ for(index=0;reserved[index];index++)\r
+ {\r
+ if(!strcmp(reserved[index],ytext))\r
+ { sprintf(tempBuf,"%s(%s)",ERR_RES,yytext); errExit(tempBuf); exit(ERR_EXIT);}\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+/* allocazione di ID come nuova espansione */\r
+void addDefId(char *ytext)\r
+{\r
+ if(!rootDef)\r
+ { \r
+ if(!(curDef=rootDef=(defELEM *) malloc(sizeof(defELEM))))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+ }\r
+ else\r
+ {\r
+ defELEM *tmp;\r
+\r
+ for(tmp=rootDef;tmp;tmp=tmp->next)\r
+ {\r
+ if(!strcmp(tmp->defId,ytext))\r
+ { sprintf(tempBuf,"%s",ERR_ALR); errExit(tempBuf); exit(ERR_EXIT); }\r
+ }\r
+\r
+ if(!(curDef->next=(defELEM *) malloc(sizeof(defELEM))))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ curDef=curDef->next;\r
+ }\r
+\r
+ curDef->next=NULL;\r
+ curDef->defTxt=NULL;\r
+\r
+ if(!(curDef->defId=(char *) malloc(strlen(ytext)+1)))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ strcpy(curDef->defId,ytext);\r
+\r
+ return;\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+/* rimozione di ID come espansione */\r
+void delDefId(char *ytext)\r
+{\r
+ defELEM *tmp,*prevTmp;\r
+\r
+ for(prevTmp=NULL,tmp=rootDef;tmp;prevTmp=tmp,tmp=tmp->next)\r
+ {\r
+ if(!strcmp(tmp->defId,ytext))\r
+ {\r
+ if(prevTmp)\r
+ {\r
+ prevTmp->next=tmp->next;\r
+\r
+ free(tmp->defId);\r
+ if(tmp->defTxt)\r
+ { free(tmp->defTxt); }\r
+ free(tmp);\r
+ }\r
+ else\r
+ {\r
+ rootDef=tmp->next;\r
+\r
+ free(tmp->defId);\r
+ if(tmp->defTxt)\r
+ { free(tmp->defTxt); }\r
+ free(tmp);\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+/* definizione del testo dell'espansione di ID */\r
+void addDefTxt(char *ytext)\r
+{\r
+ if(!(curDef->defTxt=(char *) malloc(strlen(ytext)+1)))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ strcpy(curDef->defTxt,ytext);\r
+\r
+ return;\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+/* formattazione e aggiunta di yytext alla lista dei token */\r
+void addOkBuf(char *token,char *ytext)\r
+{\r
+ if(expOnly)\r
+ { printf("%s",ytext); }\r
+ else\r
+ {\r
+ sprintf(tempBuf,"%s:%d,%d\t%s\t%s\t%c",inName[inNesting],inLine[inNesting],inRow[inNesting],token,ytext,SEP);\r
+\r
+ if(!rootElem)\r
+ {\r
+ if(!(curElem=rootElem=(listELEM *) malloc(sizeof(listELEM))))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+ }\r
+ else\r
+ {\r
+ if(!(curElem->next=(listELEM *) malloc(sizeof(listELEM))))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ curElem=curElem->next;\r
+ }\r
+\r
+ curElem->next=NULL;\r
+\r
+ if(!(curElem->scanTxt=(char *) malloc(strlen(tempBuf)+1)))\r
+ { sprintf(tempBuf,"%s",ERR_MEM); errExit(tempBuf); exit(ERR_EXIT); }\r
+\r
+ strcpy(curElem->scanTxt,tempBuf);\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+void usage(char *name)\r
+{\r
+ printf("\nC Scanner - Cosimo Oliboni\n\n");\r
+ printf("\"%s -e source\" preprocessing di un sorgente\n",name);\r
+ printf("\"%s source\" scanning di un sorgente\n",name);\r
+ printf("\"%s\" scanning da stdin\n\n",name);\r
+\r
+ return;\r
+}\r
+\r
+/* ************************************************************************* */\r
+\r
+int main(int argc, char **argv)\r
+{\r
+ inLine[inNesting]=0;\r
+ inRow[inNesting]=0;\r
+\r
+ if(argc>1)\r
+ {\r
+ /* "scanner -e sorgente" */\r
+ if(argc==3)\r
+ {\r
+ if(strcmp(argv[1],EXP_OPT))\r
+ { sprintf(tempBuf,"%s",ERR_OPT); errExit(tempBuf); usage(argv[0]); exit(ERR_EXIT); }\r
+\r
+ expOnly=1;\r
+\r
+ strcpy(inName[inNesting],argv[2]);\r
+ }\r
+ /* "scanner sorgente" */\r
+ else if(argc==2)\r
+ { strcpy(inName[inNesting],argv[1]); }\r
+ else\r
+ { sprintf(tempBuf,"%s",ERR_ARG); errExit(tempBuf); usage(argv[0]); exit(ERR_EXIT); }\r
+\r
+ if(!(yyin=fopen(inName[inNesting],"r")))\r
+ { sprintf(tempBuf,"%s(%s)",ERR_OPEN,inName[inNesting]); errExit(tempBuf); usage(argv[0]); exit(ERR_EXIT); }\r
+ }\r
+ /* "scanner <stdin>" */\r
+ else\r
+ { strcpy(inName[inNesting],"stdin"); }\r
+\r
+ inLine[inNesting]=1;\r
+ inRow[inNesting]=1;\r
+\r
+ /* scanning */\r
+ yylex();\r
+\r
+ /* se non ci sono stati errori && se non si effettua solo preprocessing */\r
+ /* output della lista di token creata */\r
+ /* preceduta da OK && seguita da EOF */\r
+\r
+ if(!expOnly)\r
+ {\r
+ inNesting++;\r
+\r
+ addOkBuf("EOF","EOF");\r
+\r
+ printf("%s:0,0\tOK\tOK\t%c",inName[0],SEP);\r
+\r
+ for(curElem=rootElem;curElem;curElem=curElem->next)\r
+ { printf("%s",curElem->scanTxt); }\r
+ }\r
+\r
+ return(OK_EXIT);\r
+}\r
+\r
+yywrap()\r
+{\r
+ return(1);\r
+}\r