| /* TODO: |
| |
| ---- HIGHEST PRIORITY ---- |
| |
| * #ifndef |
| |
| * #if/#elif - Bearbeitung |
| |
| * leere argument-/tokenlists erlauben |
| |
| * Anzahl der Argumente checken (auch zuviele ergeben einen Error) |
| |
| * bei REDEFINING und allowredefinition=0 tokenlist genau ueberpruefen |
| |
| * Aufteilen in mehrere Sourcen main.c pplists.c etc. |
| * Einige Variablen umbenennen (x,y,i,j,l,n etc =8) |
| |
| ----------------------------------------------------------------- |
| |
| * Verbesserungen: |
| * - Nach malloc()/vor free() ueberpruefen ob NULL-Pointer |
| * - Statt per dlen per Ptr2EOL abfragen.. |
| |
| * Fragen an Volker: |
| * - _ alleine ein Identifier ? Ja |
| |
| ---- LOWEST PRIORITY ---- |
| |
| * - Token loeschen, wenn nur noch TokenList benutzt wird. |
| |
| * - ParseIdent.. optimieren |
| |
| * - Rest optimieren =8) |
| |
| * - PreParsing umschreiben.. __LINE__ muss mit der echten |
| * Zeilennummer uebereinstimmen (die LFs drinlassen) |
| */ |
| |
| /* |
| * PreProcessor |
| * $VER: VBPP V0.00 (19 Sep 1995) |
| * (w) 1995 by Thorsten Schaaps |
| */ |
| |
| #include <time.h> |
| |
| #include "vbc.h" |
| #include "vbpp.h" |
| |
| /*vb: */ |
| static char FILE_[]=__FILE__; |
| |
| /*vb: */ |
| char pp_version[] = "vbpp V0.00 (w) 1995 by Thorsten Schaaps"; |
| |
| /* #define MAXIFNESTING 1024 *//*vb: ifnesting==incnesting */ |
| |
| FILE *in[MAXINCNESTING]; /* Sourcefiles */ |
| int zn[MAXINCNESTING]; /* Zeilennummern */ |
| char *filenames[MAXINCNESTING]; /* Filenamen */ |
| int incnesting; /* aktuelle Verschachtelungstiefe */ |
| unsigned long linenr; /* Zeilennummer */ |
| |
| char *incpath[MAXINCPATHS] = |
| {"vinclude:"}; /* Includepfade */ |
| |
| int incpathc = 1; /* Anzahl der Includepfade */ |
| |
| char ppstring[MAXPPINPUT]; |
| |
| int cmtnesting = 0; /* aktuelle Kommentar-Versch.-Tiefe */ |
| |
| /*int ifnesting; *//*vb: *//* aktuelle IF-Tiefe */ |
| /*vb: ifnesting==incnesting */ |
| short ifstatus[MAXINCNESTING]; /* Array fuer Status-Verschachtelung */ |
| int if_cnt; /* Zaehler fuer #if's waehrend do_output=0 */ |
| int abs_if_cnt; /* zaehlt auch waehrend do_output */ |
| |
| int do_output = 1; /* Flag zur Erzeugung eines Outputs */ |
| |
| struct strnode *strlist; |
| |
| struct mnode *mlist; |
| |
| int did_expand; |
| |
| /* Temporaere Debugging-Routinen */ |
| void PrintSN(struct strnode *tl) |
| { |
| switch (tl->type) { |
| case NORMAL: |
| printf(" Normal........:"); |
| break; |
| case PP_IDENT: |
| printf(" Identifier....:"); |
| break; |
| case ARGUMENT: |
| printf(" Argument Nr.%2d:", tl->number); |
| break; |
| case NUMBER: |
| printf(" Number........:"); |
| break; |
| case PP_STR: |
| printf(" String........:"); |
| break; |
| case SPACE: |
| printf(" Space.........:"); |
| break; |
| case SPECIAL: |
| printf(" Special..Nr.%2d:", tl->flags); |
| break; |
| default: |
| printf(" unknown..Nr.%2d:", tl->type); |
| break; |
| } |
| printf(" %s\n", tl->str); |
| } |
| void PrintTL(struct strnode *tl) |
| { |
| |
| #ifdef bla |
| |
| if (tl) { |
| printf("TokenList:\n"); |
| while (tl) { |
| PrintSN(tl); |
| tl = tl->next; |
| } |
| } |
| #endif |
| |
| } |
| |
| |
| /* ******* Listen-Funktionen ******* */ |
| |
| /* AddMakroNode - Fuegt eine Node an den Anfang einer Liste ein */ |
| void AddMakroNode(struct mnode **list, struct mnode *node) |
| { |
| |
| if (DEBUG & 32) |
| puts("AddMakroNode"); |
| |
| if (node) { |
| node->prev = NULL; |
| node->next = *list; |
| *list = node; |
| if (node->next) |
| node->next->prev = node; |
| } |
| } |
| |
| |
| /* AddStrNode - Fuegt eine Node in die Liste ein */ |
| void AddStrNode(struct strnode **list, struct strnode *node, char *str) |
| { |
| |
| if (DEBUG & 32) |
| puts("AddStrNode"); |
| |
| |
| if (node || str) { |
| if (!node) |
| node = (struct strnode *) malloc(sizeof(struct strnode)); |
| /* HIER: Rueckgabewert wegen Fehler ! */ |
| if (!node) { |
| error(196); |
| } else { |
| node->prev = NULL; |
| node->next = *list; |
| if (str) |
| node->str = str; |
| *list = node; |
| if (node->next) |
| node->next->prev = node; |
| } |
| } |
| } |
| |
| |
| /* AddStrNodeBehind - Fuegt eine Node ans Ende der Liste ein */ |
| void AddStrNodeBehind(struct strnode **list, struct strnode *node, char *str) |
| { |
| struct strnode *listnode; |
| |
| if (DEBUG & 32) |
| puts("AddStrNodeBehind"); |
| |
| |
| if (node || str) { |
| if (!node) |
| node = (struct strnode *) malloc(sizeof(struct strnode)); |
| if (!node) { |
| error(196); |
| } else { |
| if (!*list) { |
| node->prev = NULL; |
| node->next = NULL; |
| *list = node; |
| } else { |
| listnode = *list; |
| while (listnode->next) { |
| listnode = listnode->next; |
| } |
| node->prev = listnode; |
| node->next = NULL; |
| listnode->next = node; |
| } |
| if (str) |
| node->str = str; |
| } |
| } |
| } |
| |
| |
| /* RemMakroNode - Entfernt eine Node aus der Liste ohne sie zu loeschen */ |
| void RemMakroNode(struct mnode **list, struct mnode *node) |
| { |
| |
| if (DEBUG & 32) |
| puts("RemMakroNode"); |
| |
| |
| if (node->prev) { |
| if (node->next) |
| node->next->prev = node->prev; |
| node->prev->next = node->next; |
| } else { |
| if (node->next) |
| node->next->prev = NULL; |
| *list = node->next; |
| } |
| node->next = node->prev = NULL; |
| } |
| |
| /* InsertMakroNode - Setzt eine Node hinter einer anderen ein */ |
| void InsertMakroNode(struct mnode **list, struct mnode *node, struct mnode *behind) |
| { |
| |
| if (DEBUG & 32) |
| puts("InsertMakroNode"); |
| |
| |
| if (behind) { |
| node->prev = behind; |
| node->next = behind->next; |
| behind->next = node; |
| if (node->next) |
| node->next->prev = node; |
| } else |
| AddMakroNode(list, node); |
| } |
| |
| /* RemStrNode - Entfernt eine Node aus der Liste ohne sie zu loeschen */ |
| void RemStrNode(struct strnode **list, struct strnode *node) |
| { |
| |
| if (DEBUG & 32) |
| puts("RemStrNode"); |
| |
| |
| if (node->prev) { |
| if (node->next) |
| node->next->prev = node->prev; |
| node->prev->next = node->next; |
| } else { |
| if (node->next) |
| node->next->prev = NULL; |
| *list = node->next; |
| } |
| node->next = node->prev = NULL; |
| } |
| |
| |
| /* FindMakroNode - sucht den passenden Eintrag in der Liste |
| * len=0 - der gesamte String muss uebereinstimmen |
| * len>0 - die ersten len Zeichen muessen stimmen |
| */ |
| struct mnode *FindMakroNode(struct mnode *list, char *str, int len) |
| { |
| |
| if (DEBUG & 32) |
| puts("FindMakroNode"); |
| |
| while (list) { |
| if (len) { |
| if ((strlen(list->name) == len) && (!strncmp(list->name, str, len))) |
| return (list); |
| } else { |
| if (!strcmp(list->name, str)) |
| return (list); |
| } |
| list = list->next; |
| } |
| return (0); |
| } |
| |
| |
| /* DelMakroNode - gibt den gesamten Speicher einer Node frei, ist list#NULL |
| * wird die Node vorher aus der Liste entfernt |
| */ |
| void DelMakroNode(struct mnode **list, struct mnode *node) |
| { |
| |
| if (DEBUG & 32) |
| puts("DelMakroNode"); |
| |
| |
| if (node) { |
| if (list && *list) |
| RemMakroNode(list, node); |
| if (node->name) |
| free(node->name); |
| if (node->args) |
| free(node->args); |
| if (node->token) |
| free(node->token); |
| if (node->tokenlist) |
| DelStrList(&node->tokenlist); |
| free(node); |
| } |
| } |
| |
| |
| /* DelStrNode - gibt den gesamten Speicher einer Node frei, ist list#NULL |
| * wird die Node vorher aus der Liste entfernt |
| */ |
| void DelStrNode(struct strnode **list, struct strnode *node) |
| { |
| |
| if (DEBUG & 32) |
| puts("DelStrNode"); |
| |
| |
| if (node) { |
| if (list && *list) |
| RemStrNode(list, node); |
| if (node->str) |
| free(node->str); |
| free(node); |
| } |
| } |
| |
| void MergeStrNodes(struct strnode *prev, struct strnode *next) |
| { |
| /* next will now be deleted and prev->str will be */ |
| /* the joined strings from prev&next */ |
| char *newstr; |
| /*vb: */ |
| char c, *s, *d; |
| |
| if (DEBUG & 32) |
| puts("MergeStrNodes"); |
| |
| |
| newstr = (char *) malloc(prev->len + next->len + 1); |
| /*vb: string-Routinen ersetzt (hoffentlich schneller) |
| strcpy(newstr,prev->str); |
| strcat(newstr,next->str); |
| */ |
| d = newstr; |
| s = prev->str; |
| do { |
| c = *s++; |
| *d++ = c; |
| } while (c); |
| d--; |
| s = next->str; |
| do { |
| c = *s++; |
| *d++ = c; |
| } while (c); |
| |
| if (prev->str) |
| free(prev->str); /*vb: wenn prev->str==0 knallts doch schon oben? */ |
| prev->str = newstr; |
| prev->len += next->len; |
| DelStrNode(NULL, next); |
| } |
| |
| /* DelMakroList - loescht eine gesamte Liste */ |
| void DelMakroList(struct mnode **list) |
| { |
| |
| if (DEBUG & 32) |
| puts("DelMakroList"); |
| |
| |
| while (*list) |
| DelMakroNode(list, *list); |
| /* *list=NULL; *//*vb: *list==0 */ |
| } |
| |
| |
| /* DelStrList - loescht eine gesamte Liste samt der Nodes/Strings */ |
| void DelStrList(struct strnode **list) |
| { |
| |
| if (DEBUG & 32) |
| puts("DelStrList"); |
| |
| |
| while (*list) |
| DelStrNode(list, *list); |
| /* *list=NULL; *//*vb: *list==0 */ |
| } |
| |
| /* AllocSpace - erzeugt eine StrNode vom Typ Space */ |
| struct strnode *AllocSpace() |
| { |
| struct strnode *newnode; |
| char *newstr; |
| |
| |
| if (DEBUG & 32) |
| puts("AllocSpace"); |
| |
| |
| newstr = (char *) malloc(2); |
| if (newstr) { |
| newstr[0] = ' '; |
| newstr[1] = 0; |
| newnode = (struct strnode *) malloc(sizeof(struct strnode)); |
| if (newnode) { |
| newnode->str = newstr; |
| newnode->type = SPACE; |
| newnode->len = 1; |
| newnode->next = newnode->prev = NULL; |
| newnode->flags = newnode->number = 0; |
| return (newnode); |
| } |
| } |
| return (NULL); |
| } |
| |
| |
| /* CloneStrList - erstellt eine exakte Kopie der Liste oder eines Ausschnittes */ |
| /* wenn listend#NULL */ |
| struct strnode *CloneStrList(struct strnode *list, struct strnode *listend) |
| { |
| struct strnode *prevnode = NULL, *newnode, *newlist = NULL; |
| char *newstr; |
| |
| if (DEBUG & 32) |
| puts("CloneStrList"); |
| |
| |
| while (list) { |
| newnode = (struct strnode *) malloc(sizeof(struct strnode)); |
| if (!newnode) { |
| DelStrList(&newlist); |
| return (NULL); |
| } |
| newstr = (char *) malloc(list->len + 1); |
| if (!newstr) { |
| free(newnode); |
| DelStrList(&newlist); |
| return (NULL); |
| } |
| strcpy(newstr, list->str); |
| newnode->str = newstr; |
| newnode->len = list->len; |
| newnode->flags = list->flags; |
| newnode->type = list->type; |
| newnode->number = list->number; |
| newnode->next = NULL; |
| newnode->prev = prevnode; |
| |
| if (prevnode) |
| prevnode->next = newnode; |
| else |
| newlist = newnode; |
| prevnode = newnode; |
| |
| if (listend && list == listend) |
| list = NULL; |
| else |
| list = list->next; |
| } |
| return (newlist); |
| } |
| |
| |
| /* DoMakroFunction - erstellt eine StrList entsprechend des Function-Makros */ |
| struct strnode *DoMakroFunction(struct mnode *makro) |
| { |
| struct strnode *result = NULL; |
| char *newstr = NULL, *timestr = NULL; |
| int len, type; |
| time_t timevalue; |
| |
| if (DEBUG & 32) |
| puts("DoMakroFunction"); |
| |
| |
| if (makro->flags & FUNCTION) { |
| switch (makro->funcnum) { |
| case FUNCLINE: |
| newstr = (char *) malloc(11); |
| if (!newstr) |
| return (NULL); |
| sprintf(newstr, "%lu", linenr); |
| len = strlen(newstr); |
| type = NUMBER; |
| break; |
| case FUNCFILE: |
| len = strlen(filenames[incnesting]); |
| newstr = (char *) malloc(len + 1 + 2); |
| if (!newstr) |
| return (NULL); |
| *newstr = '\"'; |
| strcpy((newstr + 1), filenames[incnesting]); |
| strcat(newstr, "\""); |
| type = PP_STR; |
| break; |
| case FUNCDATE: |
| type = PP_STR; |
| newstr = (char *) malloc(14); |
| if (!newstr) |
| return (NULL); |
| timevalue = time(0); |
| timestr = ctime(&timevalue); |
| newstr[0] = '\"'; |
| strncpy(newstr + 1, timestr + 4, 7); /* copy 'Mmm dd ' */ |
| strcpy(newstr + 8, timestr + 20); /* copy 'yyyy' */ |
| newstr[12] = '\"'; |
| newstr[13] = 0; |
| len = 13; |
| break; |
| case FUNCTIME: |
| type = PP_STR; |
| newstr = (char *) malloc(11); |
| if (!newstr) |
| return (NULL); |
| timevalue = time(0); |
| timestr = ctime(&timevalue); |
| newstr[0] = '\"'; |
| strncpy(newstr + 1, timestr + 11, 8); /* copy 'hh:mm:ss' */ |
| newstr[9] = '\"'; |
| newstr[10] = 0; |
| len = 10; |
| break; |
| default: |
| return (NULL); |
| break; |
| } |
| result = (struct strnode *) malloc(sizeof(struct strnode)); |
| if (!result) { |
| if (newstr) |
| free(newstr); |
| return (NULL); |
| } |
| result->prev = result->next = NULL; |
| result->str = newstr; |
| result->len = len; |
| result->number = result->flags = 0; |
| result->type = type; |
| } |
| return (result); |
| } |
| |
| |
| /* ******* String-Funktionen ****** */ |
| |
| /* Str2List - parsed einen String in eine StrList */ |
| struct strnode *Str2List(char *str) |
| { |
| struct strnode *newlist = NULL, *newnode = NULL; |
| char *temp, *string; |
| int length, type, flags; |
| |
| if (DEBUG & 32) |
| puts("Str2List"); |
| |
| while (*str) { |
| flags = 0; |
| /*vb: casts eingefuegt */ |
| if (isspace((unsigned char) *str)) { /* Spaces parsen */ |
| temp = str + 1; |
| length = 1; |
| while (*temp && isspace((unsigned char) *temp)) { |
| temp++; |
| length++; |
| } |
| type = SPACE; |
| } else if (*str == '\"') { /* String parsen */ |
| temp = str + 1; |
| length = 2; |
| while (*temp && *temp != '\"') |
| if (*temp == '\\') { |
| temp += 2; |
| length += 2; |
| } else { |
| temp++; |
| length++; |
| } |
| type = PP_STR; |
| } else if (*str == '\'') { /* String parsen */ |
| temp = str + 1; |
| length = 2; |
| while (*temp && *temp != '\'') |
| if (*temp == '\\') { |
| temp += 2; |
| length += 2; |
| } else { |
| temp++; |
| length++; |
| } |
| type = PP_STR; |
| } else if (isdigit((unsigned char) *str) || (*str == '.' && isdigit((unsigned char) *(str + 1)))) { |
| /* Zahlen parsen */ |
| temp = str; |
| length = 0; |
| while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) { |
| temp++; |
| length++; |
| } |
| if (*temp == '.') { |
| temp++; |
| length++; |
| if (isdigit((unsigned char) *temp) || *temp == 'e' || *temp == 'E') |
| while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) { |
| temp++; |
| length++; |
| } |
| } |
| if (*(temp - 1) == 'e' || *(temp - 1) == 'E') |
| if (isdigit((unsigned char) *temp) || *temp == '+' || *temp == '-') { |
| temp++; |
| length++; |
| while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) { |
| temp++; |
| length++; |
| } |
| } |
| type = NUMBER; |
| } else if (isalpha((unsigned char) *str) || *str == '_') { /* moegl. Identifier parsen */ |
| temp = str + 1; |
| length = 1; |
| while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) { |
| temp++; |
| length++; |
| } |
| type = PP_IDENT; |
| } else if (*str) { /* alles andere als einzelne Zeichen */ |
| length = 1; |
| type = NORMAL; |
| } |
| string = (char *) malloc(length + 1); |
| if (!string) { |
| error(196); |
| DelStrList(&newlist); |
| return (NULL); |
| } |
| strncpy(string, str, length); |
| string[length] = 0; |
| str += length; |
| |
| newnode = (struct strnode *) malloc(sizeof(struct strnode)); |
| if (!newnode) { |
| error(196); |
| if (string) |
| free(string); |
| return (NULL); |
| } |
| newnode->str = string; |
| newnode->len = length; |
| newnode->flags = flags; |
| newnode->type = type; |
| |
| AddStrNodeBehind(&newlist, newnode, NULL); |
| } |
| return (newlist); |
| } |
| |
| /* List2Str - schreibt eine Liste als String zurueck */ |
| int List2Str(struct strnode *list, char *str, int maxchars) |
| { |
| int len = 0; |
| char c, *p; |
| |
| if (DEBUG & 32) |
| puts("List2Str"); |
| |
| |
| *str = 0; |
| if (list) { |
| while (list) { |
| if ((len + (list->len)) > (maxchars - 1)) { |
| error(177); |
| return (0); |
| } else { |
| /*vb: */ |
| p = list->str; |
| do { |
| c = *p++; |
| *str++ = c; |
| } while (c); |
| str--; |
| /* strcat(str,list->str); */ |
| len += list->len; |
| } |
| list = list->next; |
| } |
| return (len + 1); |
| } else { |
| *str = 0; |
| return (1); |
| } |
| } |
| |
| /* ListLen - ermittelt die Laenge einer Str-Liste (in Zeichen) */ |
| int ListLen(struct strnode *list) |
| { |
| int len = 0; |
| while (list) { |
| len += list->len; |
| list = list->next; |
| } |
| return (len); |
| } |
| |
| /* ListStrLen - ermittelt die Laenge einer Str-List als String */ |
| /* d.h. mit " am Anfang und Ende, sowie einem \ vor */ |
| /* jedem \ und " */ |
| int ListStrLen(struct strnode *list) |
| { |
| int len = 2; |
| while (list) { |
| if (list->type == SPACE) |
| len++; |
| else { |
| len += list->len; |
| if (list->type == PP_STR && list->str[0] == '\"') |
| len += 2; |
| else if (list->type == NORMAL && list->str[0] == '\\') |
| len++; |
| } |
| list = list->next; |
| } |
| return (len); |
| } |
| |
| /* CopyList2StrStr - kopiert eine Str-List als String um */ |
| /* d.h. mit " am Anfang und Ende, sowie einem \ vor */ |
| /* jedem \ und " */ |
| CopyList2StrStr(struct strnode * list, char *str) |
| { |
| int len; |
| |
| if (DEBUG & 32) |
| puts("CopyList2StrStr"); |
| |
| |
| str[0] = 0; |
| if (list) { |
| strcpy(str, "\""); |
| len = 1; |
| while (list) { |
| if (list->type == SPACE) { |
| len++; |
| strcat(str, " "); |
| } else { |
| len += list->len; |
| if (list->type == PP_STR && list->str[0] == '\"') { |
| strcat(str, "\\"); |
| strncat(str, list->str, list->len - 1); |
| strcat(str, "\\\""); |
| } else if (list->type == NORMAL && list->str[0] == '\\') { |
| strcat(str, "\\"); |
| strcat(str, list->str); |
| } else |
| strcat(str, list->str); |
| } |
| list = list->next; |
| } |
| strcat(str, "\""); |
| len++; |
| } |
| return (len); |
| } |
| |
| /* NextToSpecial - checked, ob die StrNode neben einem # oder ## steht */ |
| int NextToSpecial(struct strnode *node) |
| { |
| struct strnode *search; |
| |
| if (DEBUG & 32) |
| puts("NextToSpecial"); |
| |
| |
| if (node->prev) { |
| search = node->prev; |
| while (search && search->type == SPACE) |
| search = search->prev; |
| if (search && search->type == SPECIAL) |
| return (search->flags); |
| } |
| if (node->next) { |
| search = node->next; |
| while (search && search->type == SPACE) |
| search = search->next; |
| /* Hinter der Node ist ein # (ToString) ohne Bedeutung */ |
| if (search && search->type == SPECIAL |
| && search->flags == KILLSPACES) |
| return (KILLSPACES); |
| } |
| return (NONE); |
| } |
| |
| /* FindBracket - sucht das passende Gegenstueck zu der (, auf die Node zeigt */ |
| /* dabei werden verschachtelte Klammern beachtet */ |
| struct strnode *FindBracket(struct strnode *node) |
| { |
| |
| if (DEBUG & 32) |
| puts("FindBracket"); |
| |
| |
| if (node && node->next && node->type == NORMAL && node->str[0] == '(') { |
| do { |
| node = node->next; |
| if (node && node->type == NORMAL) { |
| if (node->str[0] == ')') |
| return (node); |
| if (node->str[0] == '(') |
| node = FindBracket(node); |
| } |
| } while (node); |
| return (NULL); |
| } else |
| return (NULL); |
| } |
| |
| /* CloneArg - gibt eine Liste zurueck, die das n. Argument des Makros enthaelt */ |
| struct strnode *CloneArg(struct strnode *list, int n, int *error) |
| { |
| int argnum = 0; |
| struct strnode *start; |
| |
| if (error) |
| *error = OK; |
| |
| if (list) { |
| if (DEBUG & 32) |
| printf("CloneArg\n"); |
| if (list->type == PP_IDENT) |
| list = list->next; |
| while (list && list->type == SPACE) |
| list = list->next; |
| |
| if (list && list->type == NORMAL && list->str[0] == '(') { |
| list = list->next; /* Skip ( */ |
| |
| if (DEBUG & 32) |
| printf("- IDENT skipped, ( found\n"); |
| |
| while (list && (argnum < n)) { |
| if (list->type == NORMAL) { |
| if (list->str[0] == ')') |
| list = NULL; |
| if (list && list->str[0] == '(') |
| list = (FindBracket(list))->next; |
| if (list && list->str[0] == ',') |
| argnum++; |
| } |
| if (list) |
| list = list->next; |
| } |
| |
| while (list && list->type == SPACE) |
| list = list->next; |
| |
| if (list) { |
| if (list->type == NORMAL && (list->str[0] == ')' || list->str[0] == ',')) { /* HIER evtl. ein Space erzeugen */ |
| return (NULL); |
| } |
| start = list; |
| } else { |
| if (error) |
| *error = ARG_EXPECTED; |
| return (NULL); |
| } |
| |
| if (DEBUG & 32) |
| printf("- Okay, Arg-Start found: %s\n", start->str); |
| |
| while (list && (argnum == n)) { |
| if (list->type == NORMAL) { |
| switch (list->str[0]) { |
| case ')': |
| case ',': |
| argnum++; |
| list = list->prev; |
| break; |
| case '(': |
| list = FindBracket(list); |
| default: |
| if (list) |
| list = list->next; |
| break; |
| } |
| } else if (list) |
| list = list->next; |
| } |
| |
| while (list && list->type == SPACE) |
| list = list->prev; |
| |
| if (DEBUG & 32) |
| printf("- Okay, Arg-End found: %s\n", list->str); |
| return (CloneStrList(start, list)); |
| |
| } else { |
| if (error) |
| *error = ARG_EXPECTED; |
| return (NULL); |
| } |
| } else |
| return (NULL); |
| } |
| |
| /* ExpandArgMakro - ersetzt ein Makro mit Argumenten */ |
| int ExpandArgMakro(struct mnode *makro, struct strnode **list, |
| struct strnode **pos) |
| { |
| struct strnode *clone, *temp, *temp1, *arg, *new; |
| struct strnode *prev, *next; |
| struct mnode *prevmakro; |
| char *newstr; |
| int spec, len, x; |
| |
| clone = CloneStrList(makro->tokenlist, NULL); |
| if (!clone) |
| return (OUT_OF_MEM); |
| |
| if (DEBUG & 32) |
| printf("ExpandArgMakro - Clone build.\n"); |
| |
| temp = clone; |
| while (temp) { |
| if (temp->type == ARGUMENT) { |
| arg = CloneArg(*pos, temp->number, &x); |
| if (!arg) { |
| DelStrList(&clone); |
| return (x); |
| } |
| if (DEBUG & 32) { |
| printf("ARGUMENT:\n"); |
| PrintTL(arg); |
| printf("Argument found - "); |
| } |
| if (spec = NextToSpecial(temp)) { |
| /* nicht expandieren, nur einsetzen */ |
| if (spec == TOSTRING) { |
| |
| if (DEBUG & 32) |
| printf("next to #\n"); |
| /* als String einsetzen */ |
| new = (struct strnode *) malloc(sizeof(struct strnode)); |
| if (!new) { |
| DelStrList(&clone); |
| DelStrList(&arg); |
| return (OUT_OF_MEM); |
| } |
| len = ListStrLen(arg); |
| newstr = (char *) malloc(len + 1); |
| if (!newstr) { |
| DelStrList(&clone); |
| DelStrList(&arg); |
| if (new) |
| free(new); |
| return (OUT_OF_MEM); |
| } |
| CopyList2StrStr(arg, newstr); |
| DelStrList(&arg); |
| new->len = len + 2; |
| new->flags = new->number = 0; |
| new->type = PP_STR; |
| new->str = newstr; |
| |
| prev = temp->prev; |
| next = temp->next; |
| DelStrNode(NULL, temp); /* Argument */ |
| |
| while (prev && prev->type == SPACE) { |
| temp = prev->prev; |
| DelStrNode(&clone, prev); |
| prev = temp; |
| } |
| |
| if (prev && prev->type == SPECIAL && prev->flags == TOSTRING) { |
| temp = prev->prev; |
| DelStrNode(&clone, prev); |
| prev = temp; |
| } else |
| ierror(0); |
| |
| new->prev = prev; |
| if (prev) |
| prev->next = new; |
| else |
| clone = new; |
| new->next = next; |
| if (next) |
| next->prev = new; |
| temp = new; |
| } else { |
| /* Einfach nur einsetzen */ |
| if (DEBUG & 32) |
| printf("next to ##\n"); |
| prev = temp->prev; |
| next = temp->next; |
| DelStrNode(NULL, temp); |
| arg->prev = prev; |
| if (prev) |
| prev->next = arg; |
| else |
| clone = arg; |
| while (arg->next) |
| arg = arg->next; |
| arg->next = next; |
| if (next) |
| next->prev = arg; |
| temp = arg; |
| } |
| } else { |
| /* expandieren und einsetzen */ |
| if (DEBUG & 32) |
| printf("normal arg\n"); |
| if (x = ExpandList(&arg)) { |
| DelStrList(&clone); |
| DelStrList(&arg); |
| return (x); |
| } |
| if (DEBUG & 32) { |
| printf("expanded arg:\n"); |
| PrintTL(arg); |
| } |
| prev = temp->prev; |
| next = temp->next; |
| DelStrNode(NULL, temp); |
| arg->prev = prev; |
| if (prev) |
| prev->next = arg; |
| else |
| clone = arg; |
| while (arg->next) |
| arg = arg->next; |
| arg->next = next; |
| if (next) |
| next->prev = arg; |
| temp = arg; |
| } /* of N2Special */ |
| } |
| if (temp) |
| temp = temp->next; |
| } |
| |
| if (DEBUG & 32) |
| printf("Arguments expanded.\n"); |
| |
| temp = clone; |
| while (temp) { |
| if (temp->type == SPECIAL && temp->flags == KILLSPACES) { |
| prev = temp->prev; |
| next = temp->next; |
| if ((prev->type == PP_IDENT || prev->type == NUMBER)) { |
| switch (next->type) { |
| case NUMBER: /* merge -> ident */ |
| case PP_IDENT: |
| RemStrNode(&clone, next); |
| MergeStrNodes(prev, next); |
| next = temp->next; |
| /* next will now be deleted and prev->str will be */ |
| /* the joined strings from prev&next */ |
| default: /* no merge / del ## */ |
| DelStrNode(&clone, temp); |
| temp = next; |
| break; |
| } /* of switch */ |
| } else { |
| DelStrNode(&clone, temp); |
| temp = next; |
| } |
| } |
| if (temp) |
| temp = temp->next; |
| } |
| |
| /* 'makro' aus mlist ausklinken */ |
| prevmakro = makro->prev; |
| RemMakroNode(&mlist, makro); |
| |
| /* alles expandieren */ |
| if (!(x = ExpandList(&clone))) { |
| /* akt. StrNode durch clone-Liste ersetzen */ |
| |
| if (DEBUG & 32) { |
| printf("Complete Makro expanded\n"); |
| PrintTL(clone); |
| } |
| /* clone anstelle von pos in list einsetzen */ |
| prev = (*pos)->prev; |
| next = (*pos)->next; |
| |
| DelStrNode(NULL, *pos); |
| |
| #ifdef bla |
| while (next && next->type == SPACE) { |
| temp = next->next; |
| DelStrNode(NULL, next); /* SPACE zwischen Makro und Args loeschen */ |
| next = temp; |
| } |
| #endif |
| while (next && next->type == SPACE) |
| next = next->next; |
| /* SPACE hinter Makro ueberspringen */ |
| |
| if (next && next->type == NORMAL && next->str[0] == '(') { |
| temp = next; |
| next = FindBracket(temp); |
| if (next) |
| next = next->next; |
| do { |
| temp1 = temp->next; |
| DelStrNode(NULL, temp); /* ARG-List hinter Makro loeschen */ |
| temp = temp1; |
| } while (temp != next); |
| } else { |
| ierror(0); |
| } |
| |
| |
| /* vor clone ein SPACE einsetzen, wenn nicht PREV==SPACE */ |
| /*vb: hier !prev|| wegen Enforcerhit eingesetzt; waere prev&& besser? */ |
| if (!prev || prev->type != SPACE) { |
| if (temp = AllocSpace()) { |
| temp->next = clone; |
| if (clone) |
| clone->prev = temp; |
| clone = temp; |
| } |
| } |
| clone->prev = prev; |
| if (prev) |
| prev->next = clone; |
| else |
| *list = clone; |
| |
| while (clone->next) |
| clone = clone->next; |
| /* nach clone ein SPACE einsetzen, wenn nicht NEXT==SPACE */ |
| /*vb: hier !next|| wegen Enforcerhit eingesetzt; waere next&& besser? */ |
| if (!next || next->type != SPACE) { |
| if (temp = AllocSpace()) { |
| temp->prev = clone; |
| if (clone) |
| clone->next = temp; |
| clone = temp; |
| } |
| } |
| *pos = clone; |
| clone->next = next; |
| if (next) |
| next->prev = clone; |
| |
| /* 'makro' wieder einsetzen */ |
| InsertMakroNode(&mlist, makro, prevmakro); |
| return (OK); |
| } else { |
| InsertMakroNode(&mlist, makro, prevmakro); |
| return (x); |
| } |
| |
| } |
| |
| /* ExpandList - ersetzt alle Makros in der Liste */ |
| int ExpandList(struct strnode **list) |
| { |
| struct mnode *found, *before; |
| struct strnode *clone, *beforestr, *afterstr, *listtemp, *temp2, |
| *temp3; |
| int result = OK; |
| |
| if (DEBUG & 32) |
| puts("ExpandList"); |
| |
| |
| listtemp = *list; |
| while (listtemp) { |
| |
| if (listtemp->type == PP_IDENT) { |
| |
| found = FindMakroNode(mlist, listtemp->str, 0); |
| if (found) { |
| /*vb: merken, ob mind. ein Makro expandiert wurde */ |
| did_expand = 1; |
| if (found->flags & PARAMETER) { |
| /* Makro mit Argument(en) */ |
| if (DEBUG & 32) |
| printf("Makro with args\n"); |
| |
| temp2 = listtemp->next; |
| while (temp2 && temp2->type == SPACE) |
| temp2 = temp2->next; |
| |
| if (temp2 && temp2->type == NORMAL && temp2->str[0] == '(') |
| if (result = ExpandArgMakro(found, list, &listtemp)) |
| return (result); |
| |
| } else { |
| |
| /* Makro ohne Argument */ |
| |
| /* ExpandNormMakro - expandiert ein Makro ohne Argumente */ |
| /* Parameter: s.o. */ |
| |
| if (found->flags & FUNCTION) { |
| clone = DoMakroFunction(found); |
| } else { |
| clone = CloneStrList(found->tokenlist, NULL); |
| } |
| if (!clone) |
| return (OUT_OF_MEM); |
| /* akt. MakroNode ausklinken um rekursive Exp. zu verhindern */ |
| before = found->prev; |
| RemMakroNode(&mlist, found); |
| if (!(result = ExpandList(&clone))) { |
| /* akt. StrNode durch clone-Liste ersetzen */ |
| beforestr = listtemp->prev; |
| afterstr = listtemp->next; |
| DelStrNode(NULL, listtemp); |
| listtemp = afterstr; |
| clone->prev = beforestr; |
| if (beforestr) |
| beforestr->next = clone; |
| else |
| *list = clone; |
| while (clone->next) |
| clone = clone->next; |
| clone->next = afterstr; |
| if (afterstr) |
| afterstr->prev = clone; |
| /* akt. Makronode wieder einsetzen */ |
| InsertMakroNode(&mlist, found, before); |
| } else { |
| /* akt. Makronode wieder einsetzen */ |
| InsertMakroNode(&mlist, found, before); |
| return (result); |
| } |
| } |
| } |
| } |
| if (listtemp) |
| listtemp = listtemp->next; |
| } |
| |
| return (OK); |
| } |
| |
| |
| /* ParseIdentifier - parsed den Input-Define-String und haengt das Makro */ |
| /* in die Liste */ |
| |
| struct mnode *ParseIdentifier(char *str) |
| { |
| int x, numargs = 0, flags = 0, len = 0; |
| char *name = NULL, *args = NULL, *token = NULL, *temp, *temp2, *argtemp; |
| struct mnode *newmakro, *found; |
| struct strnode *tokenlist = NULL, *templist, *arglist = NULL, *templist2; |
| struct strnode *next, *prev; |
| |
| if (DEBUG & 32) |
| puts("ParseIdentifier"); |
| |
| /*vb: casts eingefuegt */ |
| while (isspace((unsigned char) *str)) { |
| str++; |
| } |
| if (!(isalpha((unsigned char) *str) || *str == '_')) { |
| error(178); |
| return (0); |
| } |
| temp = str; |
| while (isalnum((unsigned char) *temp) || (*temp == '_')) { |
| temp++; |
| len++; |
| } |
| |
| /* auf schon vorhandene (evtl. FESTE) Definition suchen */ |
| found = FindMakroNode(mlist, str, len); |
| if (found && (found->flags & NOREDEF)) { |
| error(179); |
| return (0); |
| } |
| /*vb: */ |
| if (1) { |
| /* Okay, ist egal, wie das alte Makro aussah */ |
| |
| /*vb: */ |
| if (found && !(c_flags[15] & USEDFLAG)) { |
| error(197); |
| } |
| temp = name = (char *) malloc(len + 1); /* Speicher fuer Name-String belegen */ |
| if (!name) { |
| error(196); |
| return (0); |
| } |
| for (x = 0; x < len; x++) { |
| *temp++ = *str++; |
| } /* Namen kopieren */ |
| *temp = 0; |
| |
| if (*str == '(') { |
| flags |= PARAMETER; |
| str++; /* jump over '(' */ |
| temp = str; |
| len = 0; |
| /*vb: casts eingefuegt */ |
| while (*temp && (*temp != ')')) |
| if (!(isspace((unsigned char) *temp))) { |
| len++; |
| temp++; |
| } else { |
| temp++; |
| } |
| if (*temp == 0) { |
| error(180); |
| if (name) |
| free(name); |
| return (0); |
| } |
| args = temp = (char *) malloc(len + 1); |
| if (!args) { |
| error(196); |
| if (name) |
| free(name); |
| return (0); |
| } |
| for (x = 0; x < len;) |
| if (!(isspace((unsigned char) *str))) { |
| x++; |
| *temp++ = *str++; |
| } else { |
| str++; |
| } |
| *temp = 0; |
| str++; /* jump over ')' */ |
| |
| /* Argumentliste parsen und auf Fehler pruefen */ |
| temp = args; |
| while (*temp && (isalpha((unsigned char) *temp) || *temp == '_')) { |
| temp++; |
| while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) { |
| temp++; |
| } |
| if (!(*temp) || *temp == ',') { |
| numargs++; |
| if ((*temp == ',') && (isalpha((unsigned char) *(temp + 1)) || *(temp + 1) == '_')) |
| temp++; |
| } |
| } |
| if (*temp) { |
| if (args) |
| free(args); |
| if (name) |
| free(name); |
| if (*temp == ',') { |
| error(181); |
| } else { |
| error(182); |
| } |
| return (0); |
| } |
| } |
| while (isspace((unsigned char) *str)) |
| str++; /* Skip Spaces */ |
| /* HIER: pruefen, ob tokenlist erstellt werden konnte (leere tokenlist->ok) */ |
| tokenlist = Str2List(str); |
| if (DEBUG & 32) |
| printf(" - build TokenList\n"); |
| templist = tokenlist; |
| while (templist) { |
| if ((templist->type == NORMAL) && (!strcmp(templist->str, "#"))) { |
| |
| if ((templist->next) && (templist->next->type == NORMAL) |
| && (!strcmp(templist->next->str, "#"))) { |
| /* ## KILLSPACES */ |
| if ((templist->prev) && (templist->next->next)) { |
| templist->type = SPECIAL; |
| templist->flags = KILLSPACES; |
| DelStrNode(&tokenlist, templist->next); |
| } else { |
| error(183); |
| if (name) |
| free(name); |
| if (args) |
| free(args); |
| if (tokenlist) |
| DelStrList(&tokenlist); |
| return (0); |
| } |
| } |
| } |
| templist = templist->next; |
| } |
| |
| /* Token parsen/kopieren */ |
| if ((flags & PARAMETER)) { /* Argumente parsen */ |
| arglist = NULL; |
| temp = temp2 = args; |
| while (*temp) { |
| len = 0; |
| while (*temp && *temp != ',') { |
| temp++; |
| len++; |
| } |
| if (*temp == ',') |
| temp++; |
| argtemp = (char *) malloc(len + 1); |
| if (!argtemp) { |
| error(196); |
| if (name) |
| free(name); |
| if (args) |
| free(args); |
| if (arglist) |
| DelStrList(&arglist); |
| if (tokenlist) |
| DelStrList(&tokenlist); |
| return (0); |
| } |
| strncpy(argtemp, temp2, len); |
| temp2 = temp; |
| *(argtemp + len) = 0; |
| AddStrNodeBehind(&arglist, NULL, argtemp); |
| } |
| templist = tokenlist; |
| while (templist) { |
| if (templist->type == PP_IDENT) { |
| x = 0; |
| templist2 = arglist; |
| while (templist2) { |
| if (!strcmp(templist->str, templist2->str)) { |
| templist->type = ARGUMENT; |
| templist->number = x; |
| } |
| x++; |
| templist2 = templist2->next; |
| } |
| } |
| templist = templist->next; |
| } |
| DelStrList(&arglist); |
| if (DEBUG & 32) |
| printf(" - Arguments found.\n"); |
| /* #-Specials korrigieren, nachdem die Argumente erkannt wurden */ |
| templist = tokenlist; |
| while (templist) { |
| if ((templist->type == NORMAL) && (!strcmp(templist->str, "#"))) { |
| if ((templist->next) && (templist->next->type == ARGUMENT)) { |
| templist->type = SPECIAL; |
| templist->flags = TOSTRING; |
| } else { |
| error(184); |
| if (name) |
| free(name); |
| if (args) |
| free(args); |
| if (arglist) |
| DelStrList(&arglist); |
| if (tokenlist) |
| DelStrList(&tokenlist); |
| return (0); |
| } |
| } |
| templist = templist->next; |
| } |
| if (DEBUG & 32) |
| printf(" - Special-# corrected.\n"); |
| } else { /* Token kopieren */ |
| temp = str; |
| len = 0; |
| while ((*temp) && (*temp != '\n')) { |
| temp++; |
| len++; |
| } |
| temp = token = (char *) malloc(len + 1); |
| if (!token) { |
| error(196); |
| if (name) |
| free(name); |
| if (args) |
| free(args); |
| if (tokenlist) |
| DelStrList(&tokenlist); |
| return (0); |
| } |
| for (x = 0; x < len; x++) { |
| *temp++ = *str++; |
| } |
| *temp = 0; |
| } |
| |
| |
| templist = tokenlist; |
| while (templist) { |
| if (templist->type == SPECIAL && templist->flags == KILLSPACES) { |
| next = templist->next; |
| prev = templist->prev; |
| |
| /* Kill Spaces before/after ## */ |
| while (prev && prev->type == SPACE) { |
| templist2 = prev->prev; |
| DelStrNode(&tokenlist, prev); |
| prev = templist2; |
| } |
| while (next && next->type == SPACE) { |
| templist2 = next->next; |
| DelStrNode(&tokenlist, next); |
| next = templist2; |
| } |
| if ((!next) || (!prev)) |
| ierror(0); |
| |
| if (next->type != ARGUMENT && prev->type != ARGUMENT) { |
| if ((prev->type == PP_IDENT || prev->type == NUMBER)) { |
| switch (next->type) { |
| case NUMBER: /* merge -> ident */ |
| case PP_IDENT: |
| RemStrNode(&tokenlist, next); |
| MergeStrNodes(prev, next); |
| next = templist->next; |
| /* next will now be deleted and prev->str will be */ |
| /* the joined strings from prev&next */ |
| default: /* no merge / del ## */ |
| DelStrNode(&tokenlist, templist); |
| templist = next; |
| break; |
| } /* of switch */ |
| } else { |
| DelStrNode(&tokenlist, templist); |
| templist = next; |
| } |
| } |
| } |
| if (templist) |
| templist = templist->next; |
| } |
| |
| |
| /* erst HIER bei allowredefinition=0 abfragen ?? */ |
| |
| if (newmakro = (struct mnode *) malloc(sizeof(struct mnode))) { |
| newmakro->name = name; |
| newmakro->args = args; |
| newmakro->token = token; |
| newmakro->tokenlist = tokenlist; |
| newmakro->flags = flags; |
| newmakro->funcnum = 0; |
| AddMakroNode(&mlist, newmakro); |
| } else { |
| error(196); |
| if (name) |
| free(name); |
| if (token) |
| free(token); |
| if (args) |
| free(args); |
| if (tokenlist) |
| DelStrList(&tokenlist); |
| } |
| return (newmakro); |
| |
| } else { |
| /*vb: das ist irgendwie Unsinn hier, glaube ich */ |
| ierror(0); |
| /* HIER: ueberpruefen, ob Macrodefinitionen uebereinstimmen, sonst Error */ |
| if (*temp == '(') { |
| if (found->flags & PARAMETER) { |
| temp++; /* skip ( */ |
| |
| |
| |
| } else { |
| error(185); |
| return (NULL); |
| } |
| } |
| /* HIER nur noch tokenlisten vergleichen */ |
| |
| } |
| if (DEBUG & 32) |
| printf("ParseIdent falls of\n"); |
| } |
| |
| |
| /* PreParse - 3-Zeichen-Folgen ersetzen, \+CR Zeilen anhaengen, usw.. */ |
| |
| int PreParse() |
| { |
| char *src, *dest, *dest2; |
| int slen, dlen = 0; |
| int cat = 0; /*vb: um zu merken, ob Zeilen mit \ verbunden werden */ |
| dest2 = string; |
| |
| if (DEBUG & 32) |
| puts("PreParse"); |
| |
| |
| if (!fgets(ppstring, MAXPPINPUT, in[incnesting])) { |
| if (cmtnesting) |
| error(186); |
| /*vb: */ |
| /* if(ifstatus[incnesting]) error(186); */ |
| /* ifnesting--; */ |
| if (DEBUG & 32) |
| printf("-- end of file ifnesting-1:%d\n\n", incnesting); |
| if (incnesting) { |
| fclose(in[incnesting]); |
| incnesting--; |
| return (pp_nextline()); |
| } else |
| return (0); |
| } else if (DEBUG & 32) |
| printf("gets1:%s\n", ppstring); /*vb: */ |
| |
| if ((strlen(ppstring) == (MAXPPINPUT - 1)) && (ppstring[MAXPPINPUT - 2] != '\n')) { |
| error(177); |
| return (0); |
| } |
| zn[incnesting]++; |
| linenr = zn[incnesting]; |
| |
| do { |
| /* Zeilen einlesen, bis kein Kommentar mehr */ |
| |
| /* Zeilen einlesen bis kein \ mehr am Ende */ |
| do { |
| /* Source-String an Dest-String anhaengen und ??x-Folgen ersetzen */ |
| /*vb: das killt sonst das angehaengte wieder */ |
| if (cat == 0) { |
| dest = src = ppstring; |
| slen = 0; |
| } |
| do { |
| if (*src != '\n') { |
| |
| if ((*src == '?') && (*(src + 1) == '?') && !(c_flags[16] & USEDFLAG)) { |
| switch (*(src + 2)) { |
| case '=': |
| *dest++ = '#'; |
| src += 2; |
| break; |
| case '/': |
| *dest++ = '\\'; |
| src += 2; |
| break; |
| case '\'': |
| *dest++ = '^'; |
| src += 2; |
| break; |
| case '(': |
| *dest++ = '['; |
| src += 2; |
| break; |
| case ')': |
| *dest++ = ']'; |
| src += 2; |
| break; |
| case '!': |
| *dest++ = '|'; |
| src += 2; |
| break; |
| case '<': |
| *dest++ = '{'; |
| src += 2; |
| break; |
| case '>': |
| *dest++ = '}'; |
| src += 2; |
| break; |
| case '-': |
| *dest++ = '~'; |
| src += 2; |
| break; |
| default: |
| *dest++ = *src; |
| break; |
| } /* of switch */ |
| } else { |
| *dest++ = *src; |
| } |
| |
| if (slen < MAXPPINPUT) { |
| slen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| } |
| } while (*src++); |
| |
| src = dest; |
| /* dest->lastchar+2/NULL+1 (dest-1)-> 0 (dest-2)->lastchar */ |
| if (*(dest - 2) == '\\') { |
| /*vb: sollte das slen statt dlen sein? */ |
| if (fgets(src, MAXPPINPUT - dlen, in[incnesting])) { |
| if (DEBUG & 32) |
| printf("gets2:%s\n", src); /*vb: */ |
| /* Hier auf LF+0 abfragen */ |
| dest -= 2; |
| zn[incnesting]++; |
| cat = 1; /*vb: merken, dass Zeilen verbunden wurden */ |
| } |
| } |
| } while (*dest == '\\'); |
| |
| src = ppstring; |
| while (*src) { |
| /* ' Strings ueberlesen */ |
| if ((*src == '\'') && (!cmtnesting)) { |
| if (dlen < MAXINPUT) { |
| *dest2++ = *src++; |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| while (*src && *src != '\'') { |
| if (*src == '\\') { |
| *dest2++ = *src++; |
| dlen++; |
| }; |
| if (dlen < MAXINPUT) { |
| *dest2++ = *src++; |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| } |
| if (dlen < MAXINPUT) { |
| *dest2++ = *src++; |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| } |
| /* " Strings ueberlesen */ |
| if ((*src == '\"') && (!cmtnesting)) { |
| *dest2++ = *src++; |
| dlen++; |
| while (*src && *src != '\"') { |
| if (*src == '\\') { |
| *dest2++ = *src++; |
| dlen++; |
| }; |
| if (dlen < MAXINPUT) { |
| *dest2++ = *src++; |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| } |
| if (dlen < MAXINPUT) { |
| *dest2++ = *src++; |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| } |
| /* Kommentare weglassen */ |
| if ((*src == '/') && (*(src + 1) == '*')) { |
| src += 2; |
| if (dlen < MAXINPUT) { |
| *dest2++ = ' '; |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| if ((cmtnesting && (c_flags[13] & USEDFLAG)) || (!cmtnesting)) |
| cmtnesting++; |
| else |
| error(198); |
| } else { |
| if ((*src == '*') && (*(src + 1) == '/') && cmtnesting) { |
| src += 2; |
| cmtnesting--; |
| } |
| } |
| |
| /* C++-Comment weglassen */ |
| if ((!cmtnesting) && (*src == '/') && (*(src + 1) == '/') && (c_flags[14] & USEDFLAG)) |
| *src = 0; |
| |
| if (!cmtnesting) { |
| if (*src) { |
| *dest2++ = *src++; |
| } |
| if (dlen < MAXINPUT) { |
| dlen++; |
| } else { |
| error(177); |
| return (0); |
| } |
| } else { |
| if (*src) |
| src++; |
| } |
| } |
| |
| if (cmtnesting) { |
| if (!fgets(ppstring, MAXPPINPUT, in[incnesting])) { |
| if (cmtnesting) |
| error(186); |
| if (incnesting) { |
| fclose(in[incnesting]); |
| incnesting--; |
| return (pp_nextline()); |
| } else |
| return (0); |
| } else if (DEBUG & 32) |
| printf("gets2:%s\n", ppstring); /*vb: */ |
| |
| if ((strlen(ppstring) == (MAXPPINPUT - 1)) && (ppstring[MAXPPINPUT - 2] != '\n')) { |
| error(177); |
| return (0); |
| } |
| zn[incnesting]++; |
| } |
| } while (cmtnesting); |
| |
| /*vb: das ueberschreibt den Speicher */ |
| #if 0 |
| *dest2-- = 0; |
| while (isspace(*dest2)) |
| *dest2-- = 0; /* Spaces killen */ |
| #endif |
| |
| /*vb: hoffe, das ist besser */ |
| *dest2 = 0; |
| while (dest2 > string && isspace((unsigned char) *--dest2)) |
| *dest2 = 0; |
| |
| |
| return (1); |
| } |
| |
| /* **************** PreProcessor ***************** */ |
| |
| int pp_init(void) |
| { |
| char *macroname; |
| struct mnode *macronode; |
| |
| if (!(c_flags[6] & USEDFLAG)) |
| printf("%s\n", pp_version); |
| |
| incnesting = /*ifnesting= */ -1; /*vb: */ |
| cmtnesting = if_cnt = abs_if_cnt = 0; |
| mlist = NULL; |
| strlist = NULL; |
| |
| macroname = (char *) malloc(9); |
| if (!macroname) |
| return (0); |
| strcpy(macroname, "__LINE__"); |
| macronode = (struct mnode *) malloc(sizeof(struct mnode)); |
| if (!macronode) { |
| if (macroname) |
| free(macroname); |
| return (0); |
| } |
| macronode->name = macroname; |
| macronode->args = macronode->token = NULL; |
| macronode->tokenlist = NULL; |
| macronode->flags = FUNCTION | NODELETE | NOREDEF; |
| macronode->funcnum = FUNCLINE; |
| AddMakroNode(&mlist, macronode); |
| |
| macroname = (char *) malloc(9); |
| if (!macroname) |
| return (0); |
| strcpy(macroname, "__FILE__"); |
| macronode = (struct mnode *) malloc(sizeof(struct mnode)); |
| if (!macronode) { |
| if (macroname) |
| free(macroname); |
| DelMakroList(&mlist); |
| return (0); |
| } |
| macronode->name = macroname; |
| macronode->args = macronode->token = NULL; |
| macronode->tokenlist = NULL; |
| macronode->flags = FUNCTION | NODELETE | NOREDEF; |
| macronode->funcnum = FUNCFILE; |
| AddMakroNode(&mlist, macronode); |
| |
| macroname = (char *) malloc(9); |
| if (!macroname) |
| return (0); |
| strcpy(macroname, "__DATE__"); |
| macronode = (struct mnode *) malloc(sizeof(struct mnode)); |
| if (!macronode) { |
| if (macroname) |
| free(macroname); |
| DelMakroList(&mlist); |
| return (0); |
| } |
| macronode->name = macroname; |
| macronode->args = macronode->token = NULL; |
| macronode->tokenlist = NULL; |
| macronode->flags = FUNCTION | NODELETE | NOREDEF; |
| macronode->funcnum = FUNCDATE; |
| AddMakroNode(&mlist, macronode); |
| |
| macroname = (char *) malloc(9); |
| if (!macroname) |
| return (0); |
| strcpy(macroname, "__TIME__"); |
| macronode = (struct mnode *) malloc(sizeof(struct mnode)); |
| if (!macronode) { |
| if (macroname) |
| free(macroname); |
| DelMakroList(&mlist); |
| return (0); |
| } |
| macronode->name = macroname; |
| macronode->args = macronode->token = NULL; |
| macronode->tokenlist = NULL; |
| macronode->flags = FUNCTION | NODELETE | NOREDEF; |
| macronode->funcnum = FUNCTIME; |
| AddMakroNode(&mlist, macronode); |
| |
| macroname = (char *) malloc(9); |
| if (!macroname) |
| return (0); |
| strcpy(macroname, "__STDC__"); |
| macronode = (struct mnode *) malloc(sizeof(struct mnode)); |
| if (!macronode) { |
| if (macroname) |
| free(macroname); |
| DelMakroList(&mlist); |
| return (0); |
| } |
| macronode->name = macroname; |
| macronode->args = NULL; |
| macroname = (char *) malloc(2); |
| if (!macroname) { |
| if (macronode->name) |
| free(macronode->name); |
| if (macronode) |
| free(macronode); |
| DelMakroList(&mlist); |
| return (0); |
| } |
| strcpy(macroname, "1"); |
| macronode->token = macroname; |
| macronode->tokenlist = Str2List(macroname); |
| if (!macronode->tokenlist) { |
| if (macronode->name) |
| free(macronode->name); |
| if (macronode->token) |
| free(macronode->token); |
| if (macronode) |
| free(macronode); |
| DelMakroList(&mlist); |
| return (0); |
| } |
| macronode->flags = NODELETE; |
| macronode->funcnum = 0; |
| AddMakroNode(&mlist, macronode); |
| |
| return (1); |
| } |
| |
| |
| void pp_free(void) |
| { |
| int i; |
| |
| if (DEBUG & 32) |
| puts("pp_free"); |
| |
| /*vb: Schleifenindex korrekt gesetzt */ |
| for (i = incnesting; i >= 0; i--) |
| if (in[i]) |
| fclose(in[i]); |
| DelMakroList(&mlist); |
| DelStrList(&strlist); |
| } |
| |
| int pp_include(char *f) |
| { |
| if (DEBUG & 32) |
| printf("trying to include %s\n", f); /*vb: */ |
| |
| if (incnesting >= MAXINCNESTING - 1) { |
| error(187); |
| return (0); |
| } |
| /*vb: */ |
| /* if(ifnesting>=MAXIFNESTING-1) {error("Too many nested #ifs or #includes",0);return(0);} */ |
| incnesting++; |
| /* ifnesting++; *//*vb: */ |
| ifstatus[incnesting] = 0; /*vb: */ |
| |
| if (DEBUG & 32) |
| printf("-- include: ifnesting:%d ifstatus:0 \n\n", incnesting); |
| |
| in[incnesting] = fopen(f, "r"); |
| if (!in[incnesting]) { |
| incnesting--; |
| return (0); |
| } |
| filenames[incnesting] = f; |
| zn[incnesting] = linenr = 0; |
| return (1); |
| } |
| |
| |
| |
| /* ********************** Main-Function ******************* */ |
| int pp_nextline(void) |
| { |
| char *src, *dest, *temp; |
| int complete_len, len, i, result; |
| struct mnode *makro; |
| struct strnode *linelist, *inclinelist; |
| |
| if (DEBUG & 32) |
| puts("pp_nextline"); |
| |
| dest = string; |
| dest[0] = 0; |
| |
| /* String vorbereiten, 3ZF ersetzen, \-Zeilen anhaengen, Kommentare loeschen */ |
| if (!PreParse()) |
| return (0); |
| |
| /* Ueberpruefung auf PreProcessor-Commands */ |
| src = string; |
| /*vb: casts eingefuegt */ |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } /* SkipSpaces */ |
| |
| if (*src == '#') { /* #-Direktive gefunden */ |
| src++; /* # ueberlesen */ |
| |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } /* SkipSpaces */ |
| |
| /*vb: Direktiven, die nichts mit #if etc. zu tun haben, nach hinten */ |
| |
| |
| /* IFDEF */ |
| if (!strncmp(src, "ifdef", 5)) { |
| src += 5; |
| abs_if_cnt++; /*vb: */ |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| /* identifier suchen */ |
| if (do_output) { |
| /*vb: */ |
| /* if(ifnesting>=MAXIFNESTING-1) {error("Too many nested #if's",0); return(0);} */ |
| /* ifnesting++; */ |
| temp = src; |
| len = 0; |
| while ((isalnum((unsigned char) *temp)) || (*temp == '_')) { |
| temp++; |
| len++; |
| } |
| makro = FindMakroNode(mlist, src, len); |
| if (DEBUG & 32) |
| printf("-- #ifdef found, "); |
| if (makro) { |
| /*vb: */ |
| ifstatus[incnesting] = 1; /* Bedingung == TRUE */ |
| if (DEBUG & 32) |
| printf(" condition '%s' found (TRUE)\n", makro->name); |
| } else { |
| /*vb: */ |
| ifstatus[incnesting] = 2; /* Bedingung == FALSE */ |
| do_output = 0; |
| if (DEBUG & 32) |
| printf(" condition not found (FALSE)\n\n"); |
| } |
| } else { |
| if_cnt++; |
| if (DEBUG & 32) |
| printf("-- #ifdef found and if_cnt increased\n\n"); |
| } |
| string[0] = 0; /*vb: yo */ |
| return (1); |
| } |
| } /* EO IFDEF */ |
| /* IFNDEF */ |
| if (!strncmp(src, "ifndef", 6)) { |
| src += 6; |
| abs_if_cnt++; /*vb: */ |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| |
| /* identifier suchen */ |
| if (do_output) { |
| /*vb: */ |
| /* if(ifnesting>=MAXIFNESTING-1) {error("Too many nested #if's",0); return(0);} */ |
| /* ifnesting++; */ |
| temp = src; |
| len = 0; |
| while ((isalnum((unsigned char) *temp)) || (*temp == '_')) { |
| temp++; |
| len++; |
| } |
| if (DEBUG & 32) |
| printf("-- FindMakroNode: len=%d temp=%p\n", len, (void*)temp); |
| makro = FindMakroNode(mlist, src, len); |
| if (DEBUG & 32) |
| printf("-- #ifndef found, "); |
| if (!makro) { |
| /*vb: */ |
| ifstatus[incnesting] = 1; /* Bedingung == TRUE (Makro not existing) */ |
| if (DEBUG & 32) |
| printf(" condition not found (TRUE)\n\n"); |
| } else { |
| /*vb: */ |
| ifstatus[incnesting] = 2; /* Bedingung == FALSE */ |
| do_output = 0; |
| if (DEBUG & 32) |
| printf(" condition '%s' found (FALSE)\n\n", makro->name); |
| } |
| /* HIER: string[0]=0; */ |
| } else { |
| if_cnt++; |
| if (DEBUG & 32) |
| printf("-- #ifndef found and if_cnt increased\n\n"); |
| } |
| string[0] = 0; /*vb: */ |
| return (1); |
| } |
| } /* EO IFNDEF */ |
| /* IF */ |
| if (!strncmp(src, "if", 2)) { |
| src += 2; |
| abs_if_cnt++; /*vb: */ |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| /* Bedingung auswerten */ |
| |
| |
| |
| printf("****** WARNING ******* #if is not yet implemented\n"); |
| |
| |
| string[0] = 0; /*vb: */ |
| return (1); |
| } |
| } /* EO IF */ |
| /* ELIF */ |
| if (!strncmp(src, "elif", 4)) { |
| src += 4; |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| /* Bedingung auswerten */ |
| |
| |
| |
| |
| |
| printf("****** WARNING ******* #elif is not yet implemented\n"); |
| |
| |
| |
| |
| string[0] = 0; /*vb: */ |
| return (1); |
| } |
| } /* EO ELIF */ |
| /* ELSE */ |
| if (!strncmp(src, "else", 4)) { |
| src += 4; |
| if (isspace((unsigned char) *src) || *src == 0) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| |
| if (!if_cnt) { |
| switch (ifstatus[incnesting]) { /*vb: */ |
| case 0: |
| error(188); |
| return (0); |
| break; |
| case 1: |
| do_output = 0; |
| /* HIER: auf #endif suchen SearchENDIF(); */ |
| /* HIER: ifnesting--; do_output=1; */ |
| break; |
| case 2: |
| ifstatus[incnesting] = 3; /*vb: */ |
| do_output = 1; |
| break; |
| case 3: |
| error(189); |
| return (0); |
| break; |
| } |
| } |
| string[0] = 0; /*vb: */ |
| return (1); |
| } |
| } /* EO ELSE */ |
| /* ENDIF */ |
| if (!strncmp(src, "endif", 5)) { |
| src += 5; |
| abs_if_cnt--; /*vb: */ |
| if (isspace((unsigned char) *src) || *src == 0) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| /* HIER: Auf Zeilenende testen */ |
| |
| if (DEBUG & 32) |
| printf("-- #endif found, "); |
| |
| if (if_cnt) { |
| if_cnt--; |
| if (DEBUG & 32) |
| printf("if_cnt decreased (to %d)\n", if_cnt); |
| } else { |
| if (DEBUG & 32) |
| printf("ifnesting: %d ifstatus: %d\n", incnesting, ifstatus[incnesting]); |
| if (abs_if_cnt < 0 /*(incnesting==-1)||ifstatus[incnesting]==0 */ ) { /*vb: */ |
| error(190); |
| return (0); |
| } |
| /* ifnesting--; *//*vb: */ |
| /* HIER: evtl. do_output entsprechend ifstatus[] setzen */ |
| /*vb: natuerlich */ |
| do_output = 1; |
| ifstatus[incnesting] = abs_if_cnt > 0; /*vb: 1 oder 0 */ |
| } |
| string[0] = 0; /*vb: ja */ |
| return (1); |
| } |
| } /* EO ENDIF */ |
| /*vb: andere Direktiven gegebenenfalls ueberspringen */ |
| if (!do_output) { |
| if (DEBUG & 32) |
| printf("do_output==0 => skipping: %s\n", src); |
| string[0] = 0; |
| return (1); |
| } |
| /* DEFINE */ |
| if ( /*(do_output)&& */ (!strncmp(src, "define", 6))) { /*vb: */ |
| if (DEBUG & 32) |
| printf("#define found\n"); |
| src += 6; |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| if (ParseIdentifier(src)) { |
| string[0] = 0; |
| return (1); |
| } else { |
| if (DEBUG & 32) |
| printf("ParseIdent returned 0\n"); |
| return (0); |
| } |
| } |
| } /* EO DEFINE */ |
| /* UNDEF */ |
| if ( /*(do_output)&& */ (!strncmp(src, "undef", 5))) { /*vb: */ |
| src += 5; |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| temp = src; |
| len = 0; |
| while ((isalnum((unsigned char) *temp)) || (*temp == '_')) { |
| temp++; |
| len++; |
| } |
| makro = FindMakroNode(mlist, src, len); |
| if (makro->flags & NODELETE) { |
| error(199); |
| } else { |
| DelMakroNode(&mlist, makro); |
| } |
| while (isspace((unsigned char) *temp)) { |
| temp++; |
| } |
| if (*temp != 0 && *temp != '\n') { |
| error(200); |
| } |
| string[0] = 0; |
| return (1); |
| } |
| } /* EO UNDEF */ |
| /* INCLUDE */ |
| if ( /*(do_output)&& */ (!strncmp(src, "include", 7))) { /*vb: */ |
| src += 7; |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| if (*src != '<' && *src != '\"') { |
| /* Versuchen den Rest zu expandieren */ |
| inclinelist = Str2List(src); |
| if (!ExpandList(&inclinelist)) { |
| if (List2Str(inclinelist, src, MAXINPUT - (src - string))) { |
| /* HIER exit ? */ |
| } |
| } else { |
| error(191); /* HIER exit ? */ |
| } |
| } |
| /*vb: geaendert, so dass #include "..." auch noch im Standardpfad sucht */ |
| if (DEBUG & 32) |
| printf("includename=%s\n", src); |
| if (*src == '<' || *src == '\"') { |
| char *m = src, c; |
| if (*src == '<') |
| c = '>'; |
| else |
| c = '\"'; |
| if (*src == '\"') { |
| /* im aktuellen Verzeichnis suchen und includen */ |
| src++; |
| temp = src; |
| len = 0; |
| while (*temp != '\"') { |
| temp++; |
| len++; |
| } |
| temp++; |
| while (isspace((unsigned char) *temp)) |
| temp++; |
| if (*temp) { |
| error(200); |
| } |
| temp = (char *) malloc(len + 1); |
| if (temp) { |
| strncpy(temp, src, len); |
| *(temp + len) = 0; |
| if (pp_include(temp)) { |
| AddStrNode(&strlist, NULL, temp); |
| string[0] = 0; |
| return (1); |
| } else { |
| if (temp) |
| free(temp); |
| /*vb: |
| error("pp: cannot open file to include",0); |
| return(0); */ |
| } |
| } else { |
| error(196); |
| } /* HIER: Exit? */ |
| } |
| /* in den Standard-Verzeichnissen suchen und includen */ |
| src = m; |
| src++; |
| temp = src; |
| len = 0; |
| while (*temp != c && *temp != 0) { |
| temp++; |
| len++; |
| } /*vb: sicherer */ |
| temp++; |
| while (isspace((unsigned char) *temp)) |
| temp++; |
| if (*temp) { |
| error(200); |
| } |
| temp = NULL; |
| for (i = 0; i < incpathc; i++) { |
| complete_len = strlen(incpath[i]) + len; |
| temp = (char *) malloc(complete_len + 1); |
| if (temp) { |
| strcpy(temp, incpath[i]); |
| strncat(temp, src, len); |
| *(temp + complete_len) = 0; |
| if (pp_include(temp)) { |
| AddStrNode(&strlist, NULL, temp); |
| if (DEBUG & 32) |
| printf("include <%s> found\n", temp); |
| string[0] = 0; |
| return (1); |
| } else { |
| if (temp) |
| free(temp); |
| } |
| } else { |
| error(196); |
| } /* HIER: Exit ? */ |
| } /* of FOR i */ |
| error(191); |
| return (0); |
| } else { |
| error(192); |
| return (0); |
| } |
| } else { |
| error(193); |
| return (0); |
| } |
| } /* EO INCLUDE */ |
| /* LINE */ |
| if (!strncmp(src, "line", 4)) { |
| src += 4; |
| if (isspace((unsigned char) *src)) { |
| return (1); /* Ignorieren und an Compiler weiterreichen */ |
| } |
| } /* EO LINE */ |
| /* ERROR */ |
| if (!strncmp(src, "error", 5)) { |
| src += 5; |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| |
| return (1); |
| } |
| } /* EO ERROR */ |
| /* PRAGMA */ |
| if (!strncmp(src, "pragma", 6)) { |
| src += 6; |
| if (isspace((unsigned char) *src)) { |
| while (isspace((unsigned char) *src)) { |
| src++; |
| } |
| |
| return (1); |
| } |
| } /* EO PRAGMA */ |
| /* Unknown */ |
| /* if(do_output){ */ |
| /*vb: */ |
| error(193); |
| return (0); |
| /* } *//*vb: */ |
| } else if (do_output) { |
| /* Normale Anweisung. Komplette Zeile expandieren */ |
| |
| /*vb: */ |
| |
| linelist = Str2List(string); |
| |
| if (DEBUG & 32) |
| PrintTL(linelist); |
| |
| /*vb: */ |
| did_expand = 0; |
| |
| if (result = ExpandList(&linelist)) { |
| switch (result) { |
| case OUT_OF_MEM: |
| error(196); |
| break; |
| case NUM_OF_ARGS: |
| error(194); |
| break; |
| case ARG_EXPECTED: |
| error(195); |
| break; |
| default: |
| ierror(0); |
| break; |
| } |
| DelStrList(&linelist); |
| return (0); |
| } |
| if (DEBUG & 32) |
| PrintTL(linelist); |
| |
| /*vb: List2Str nur aufrufen, falls etwas expandiert wurde */ |
| if (did_expand && !List2Str(linelist, string, MAXINPUT)) { |
| DelStrList(&linelist); |
| return (0); |
| } |
| DelStrList(&linelist); |
| |
| /*vb: */ |
| } else |
| string[0] = 0; |
| return (1); |
| } |