/* Copyright (C) 1993 Bell-Northern Research This file is part of vmkr. Vmkr is distributed in the hope that it will be useful, but without any warranty. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Everyone is granted permission to copy, modify and redistribute vmkr, but only under the conditions described in the document "vmkr copying permission notice". An exact copy of the document is supposed to have been given to you along with vmkr so that you can know how you may redistribute it all. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include "typedef.h" /* * Original Author : Himanshu M. Thaker */ extern struct names *hashtab[BASE]; extern struct entity_struct *header_entity; extern struct arch_struct *header_arch; extern struct packages *header_package; extern struct config_struct *header_config; extern struct lib_names *header_lib; extern int return_code; extern int print_libs; /* * subprogram to parse a file, and return a pointer that points * to a linked list of tokens, their variables, and keywords. */ struct token_holder *get_tokens(fname) char *fname; { char token[MAXTOKEN]; char tt[MAXTOKEN]; char line[MAXLINE]; int nottoken, found_token; int hashval; struct names *np, *lookup(); char *next_token(); int state; int begin_count; char keywrd[MAXTOKEN], var1[MAXTOKEN], var2[MAXTOKEN]; int last_state; struct token_holder *newtokens; struct token_holder *head; struct token_holder *current_head; FILE *fp, *fopen(); nottoken = FALSE; found_token = FALSE; head = NULL; /* * The initial state is 1. */ state = 1; last_state = 1; /* * Now, open the file, and start to parse it. */ if ((fp = fopen(fname, "r")) == NULL) { /*++++printf("about to return a null... name does not exist\n");*/ return (NULL); } strcpy(token, next_token(fp)); while(stringcmp(token, "") != 0) { hashval = hash(token); np = lookup(token); if (state == 1) { last_state = state; if (np != NULL) { found_token = TRUE; strcpy(keywrd, token); if ( stringcmp(token, "ARCHITECTURE") == 0 ) { state = 2; } else if ( stringcmp(token, "END") == 0 ) { state = 5; } else if ( (stringcmp(token, "ENTITY") == 0) || (stringcmp(token, "PORT") == 0) || (stringcmp(token, "FOR") == 0) ) { state = 6; } else if ( stringcmp(token, "PACKAGE") == 0 ) { state = 7; } else if ( stringcmp(token, "USE") == 0 ) { state = 9; } else if ( stringcmp(token, "CONFIGURATION") == 0 ) { state = 13; } else { printf("illegal token :%s: found in state 1\n",token); } if ( (state == 2) || (state == 7) || (state == 6) || (state == 9) || (state == 13) ) { /* * If we have encountered a keyword that we are looking for, then * get a new token_holder structure and initialize the * keyword and next fields. */ if (head == NULL) { head = MALLOC(token_holder); current_head = head; newtokens = head; } else { newtokens = MALLOC(token_holder); /* * assign the current pointer to this new token. */ current_head->next = newtokens; current_head = newtokens; } newtokens->keywrd = NMALLOC(strlen(token)+1, char); strcpy(newtokens->keywrd, token); newtokens->var1 = NULL; newtokens->var2 = NULL; newtokens->token = NULL; newtokens->next = NULL; /*----printf("note, just installed keyword %s\n",newtokens->keywrd);*/ } } } else if (state == 2) { last_state = state; newtokens->var1 = NMALLOC(strlen(token)+1, char); strcpy(newtokens->var1, token); state = 3; } else if (state == 3) { /* * If, for the ARCHITECTURE keyword, we don't detect "OF" after we * detect the name (state 2), then we don't have an architecture, and * must ingnore this token. */ last_state = state; if (stringcmp(token, "OF") == 0) state = 4; else state = 1; } else if (state == 4) { last_state = state; newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } else if (state == 5) { last_state = state; state = 1; } else if (state == 6) { last_state = state; newtokens->var1 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var1, ""); newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } else if (state == 7) { last_state = state; if ( stringcmp(token, "BODY") == 0 ) { strcpy(var1, token); newtokens->var1 = NMALLOC(strlen(token)+1, char); strcpy(newtokens->var1, token); state = 8; } else { newtokens->var1 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var1, ""); newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } } else if (state == 8) { last_state = state; newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } else if (state == 9) { last_state = state; strcpy(var1, token); if ( stringcmp(token, "ENTITY") == 0 ) { newtokens->var1 = NMALLOC(strlen(token)+1, char); strcpy(newtokens->var1, token); state = 10; } else if ( stringcmp(token, "CONFIGURATION") == 0 ) { newtokens->var1 = NMALLOC(strlen(token)+1, char); strcpy(newtokens->var1, token); state = 11; } else { newtokens->var1 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var1, ""); newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 16; } /*++++printf("note that the use token is %s\n",token);*/ /*++++printf("and going from state 9 to state %d\n",state);*/ } else if (state == 10) { last_state = state; strcpy(var2, token); newtokens->var2 = NMALLOC(strlen(token)+1, char); strcpy(newtokens->var2, token); state = 12; } else if (state == 11) { last_state = state; newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } else if (state == 12) { last_state = state; newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } else if (state == 13) { last_state = state; /* * Got a CONFIGURATION token, and this token is assigned * to var1, and represents the configuration name. */ newtokens->var1 = NMALLOC(strlen(token)+1, char); strcpy(newtokens->var1, token); newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); state = 14; } else if (state == 14) { /* * used to swallow token "OF" */ last_state = state; state = 15; } else if (state == 15) { /* * copy the entity name to token field. */ last_state = state; newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 1; } else if (state == 16) { if ( stringcmp(token, ";") != 0 ) { newtokens = MALLOC(token_holder); current_head->next = newtokens; current_head = newtokens; sprintf(tt, "USE"); newtokens->keywrd = NMALLOC(strlen(tt)+1, char); strcpy(newtokens->keywrd, tt); newtokens->var1 = NULL; newtokens->var2 = NULL; newtokens->token = NULL; newtokens->next = NULL; newtokens->var1 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var1, ""); newtokens->var2 = NMALLOC(strlen("")+1, char); strcpy(newtokens->var2, ""); newtokens->token = NMALLOC(strlen(token)+1, char); strcpy(newtokens->token, token); state = 16; } else { state = 1; } } sprintf(token,""); nottoken = FALSE; strcpy(token, next_token(fp)); } /* * remember to close the files. */ fclose(fp); return (head); } hash(token) char *token; { int a; int hashindex; int hashval; for (hashval = 0; *token != '\0';) { a = *token++; if(isupper(a)) a=tolower(a); hashval += a; } /* printf("hashindex = %d and hashval = %d ",hashindex,hashval); */ return ( hashindex = (hashval) % BASE) ; } create_database() { int hashval; char token[MAXTOKEN]; sprintf(token, "ARCHITECTURE"); install(token); sprintf(token, "CONFIGURATION");install(token); sprintf(token, "END"); install(token); sprintf(token, "ENTITY"); install(token); sprintf(token, "FOR"); install(token); sprintf(token, "PACKAGE"); install(token); sprintf(token, "PORT"); install(token); sprintf(token, "USE"); install(token); /* sprintf(token, "ABS"); install(token); sprintf(token, "ACCESS"); install(token); sprintf(token, "AFTER"); install(token); sprintf(token, "ALIAS"); install(token); sprintf(token, "ALL"); install(token); sprintf(token, "AND"); install(token); sprintf(token, "ARRAY"); install(token); sprintf(token, "ASSERT"); install(token); sprintf(token, "ATTRIBUTE"); install(token); sprintf(token, "BEGIN"); install(token); sprintf(token, "BLOCK"); install(token); sprintf(token, "BODY"); install(token); sprintf(token, "BUFFER"); install(token); sprintf(token, "BUS"); install(token); sprintf(token, "CASE"); install(token); sprintf(token, "COMPONENT"); install(token); sprintf(token, "CONSTANT"); install(token); sprintf(token, "DISCONNECT"); install(token); sprintf(token, "DOWNTO"); install(token); sprintf(token, "ELSE"); install(token); sprintf(token, "ELSIF"); install(token); sprintf(token, "EXIT"); install(token); sprintf(token, "FILE"); install(token); sprintf(token, "FUNCTION"); install(token); sprintf(token, "GENERATE"); install(token); sprintf(token, "GENERIC"); install(token); sprintf(token, "GUARDED"); install(token); sprintf(token, "IF"); install(token); sprintf(token, "IN"); install(token); sprintf(token, "INOUT"); install(token); sprintf(token, "IS"); install(token); sprintf(token, "LABEL"); install(token); sprintf(token, "LIBRARY"); install(token); sprintf(token, "LINKAGE"); install(token); sprintf(token, "LOOP"); install(token); sprintf(token, "MAP"); install(token); sprintf(token, "MOD"); install(token); sprintf(token, "NAND"); install(token); sprintf(token, "NEW"); install(token); sprintf(token, "NEXT"); install(token); sprintf(token, "NOR"); install(token); sprintf(token, "NOT"); install(token); sprintf(token, "NULL"); install(token); sprintf(token, "OF"); install(token); sprintf(token, "ON"); install(token); sprintf(token, "OPEN"); install(token); sprintf(token, "OR"); install(token); sprintf(token, "OTHERS"); install(token); sprintf(token, "OUT"); install(token); sprintf(token, "PROCEDURE"); install(token); sprintf(token, "PROCESS"); install(token); sprintf(token, "RANGE"); install(token); sprintf(token, "RECORD"); install(token); sprintf(token, "REGISTER"); install(token); sprintf(token, "REM"); install(token); sprintf(token, "REPORT"); install(token); sprintf(token, "RETURN"); install(token); sprintf(token, "SELECT"); install(token); sprintf(token, "SEVERITY"); install(token); sprintf(token, "SIGNAL"); install(token); sprintf(token, "SUBTYPE"); install(token); sprintf(token, "THEN"); install(token); sprintf(token, "TO"); install(token); sprintf(token, "TRANSPORT"); install(token); sprintf(token, "TYPE"); install(token); sprintf(token, "UNITS"); install(token); sprintf(token, "UNTIL"); install(token); sprintf(token, "VARIABLE"); install(token); sprintf(token, "WAIT"); install(token); sprintf(token, "WHEN"); install(token); sprintf(token, "WHILE"); install(token); sprintf(token, "WITH"); install(token); sprintf(token, "XOR"); install(token); */ } struct names *lookup(s) char *s; { struct names *np; /* * first get a hash value of token, and assign np to the * pointer in the hash table corresponding to it. * Then, go thru the database until a match is found for * the token. If a match is found, return the pointer to * the name. If no match is found, return NULL. */ for (np = hashtab[hash(s)]; np != NULL; np = np->next) { if (stringcmp(s,np->name) == 0) { return(np); } } return(NULL); } install(name) char *name; { struct names *np, *newnp, *oldnp, *lookup(), *p; char *strsave(); int hashval; np = lookup(name); if (np == NULL) { /* * get a new element of type np, and assign the * name field. */ newnp = MALLOC(names); newnp->name = NMALLOC(strlen(name)+1, char); strcpy(newnp->name, name); /* * get the hashtable pointer indicated by the hashing of the name. */ hashval = hash(name); np = hashtab[hashval]; if (np == NULL) /* * if the table entry is null, update that entry to point to * the new element. */ { hashtab[hashval] = newnp; } else { /* * else, until this pointer is null, search thru the data. */ while (np != NULL) { oldnp = np; np = np->next; } /* * now, update the data so that the old end of data points to * the new element, which is now the end of data. */ oldnp->next = newnp; } } } /*-----------------------------------------------------------------------------*/ char *next_token(fp) FILE *fp; { int x; int found; int state; char token[MAXTOKEN], tmp_token[MAXTOKEN]; x = fgetc(fp); state = 0; found = FALSE; sprintf(token, ""); while ( (x != EOF) && (!found) ) { if (state == 0) { /* * first, check to see if we have encountered a terminating character that * is also a token. */ if (x == ';') { state = 0; found = TRUE; sprintf(token,"%c",x); } /* * now check to see if we have encountered a character that is a terminating * character, but doesn't become part of a token. */ else if ( (x == ' ') || (x == '[') || (x == ']') || (x == '(') || (x == ')') || (x == '+') || (x == ':') || (x == '|') || (x == '#') || (x == '^') || (x == '*') || (x == ',') || (x == '<') || (x == '>') || (x == '/') || (x == 9) || (x == 10) ) { state = 2; } else if (x == '-') { /* * '-' is a terminating token, but could also be part of '--' which implies a comment * for the rest of the line. */ state = 3; } else if (x == '"') { /* * we must swallow everything between quotes. */ state = 4; } else { /* * otherwise, we have part of a token... */ sprintf(token,"%c",x); state = 1; } } else if (state == 1) { /* * if we are composing a token... */ if ( (x == ';') || (x == '-') || (x == '"') ) { /* * if we get a terminating character that we need info on next time into * this sub program, return that character to the stream. */ state = 0; ungetc(x, fp); found = TRUE; } /* * now check to see if we have encountered a character that is a terminating * character, but doesn't become part of a token. */ else if ( (x == ' ') || (x == '[') || (x == ']') || (x == '(') || (x == ')') || (x == '+') || (x == ':') || (x == '|') || (x == '#') || (x == '^') || (x == '*') || (x == ',') || (x == '<') || (x == '>') || (x == '/') || (x == 9) || (x == 10) ) { state = 0; found = TRUE; } else { sprintf(token, "%s%c", token, x); } } else if (state == 2) { /* * else, if we are eating up terminating characters... */ if (x == ';') { sprintf(token, "%c", x); found = TRUE; state = 0; } else if (x == '-') { state = 3; } else if (x == '"') { state = 4; } else if ( (x == ' ') || (x == '[') || (x == ']') || (x == '(') || (x == ')') || (x == '+') || (x == ':') || (x == '|') || (x == '#') || (x == '^') || (x == '*') || (x == ',') || (x == '<') || (x == '>') || (x == '/') || (x == 9) || (x == 10) ) { } else { sprintf(token, "%c", x); state = 1; } } else if (state == 3) { if (x == ';') { sprintf(token, "%c", x); found = TRUE; state = 0; } else if (x == '-') { state = 5; } else if (x == '"') { state = 4; } else if ( (x == ' ') || (x == '[') || (x == ']') || (x == '(') || (x == ')') || (x == '+') || (x == ':') || (x == '|') || (x == '#') || (x == '^') || (x == '*') || (x == ',') || (x == '<') || (x == '>') || (x == '/') || (x == 9) || (x == 10) ) { state = 2; } else { sprintf(token, "%c", x); state = 1; } } else if (state == 4) { if ( (x == '"') || (x == 10) ) { /* * If we find the matching ", or we reach the end of the line (assume that * the user forgot the other ")... */ state = 0; } } else if (state == 5) { /* * we have encountered two '-' in a row... thus whatever follows, to the end of the * line is a comment, and to be ignored. */ if (x == 10) { state = 0; } } else { sprintf(tmp_token, "ERROR : illegal state '%d' encountered while in next_token()\n", state); print_err(tmp_token); } if (!found) x = fgetc(fp); } return (token); } /* * the following procedure lexically compares two strings and tests * to see if a is less, equal, or greater than b, lexically, without * begin case sensitive. */ stringcmp(a, b) char *a, *b; { int i; int different; int end; int aa, bb; i = 0; different = 0; end = FALSE; while ( (different == 0) && (!end) ) { aa = a[i]; bb = b[i]; if isupper(aa) aa = tolower(aa); if isupper(bb) bb = tolower(bb); if ( (aa == '\0') && (bb != '\0') ) /* if a ends before b, then a is less than b */ different = -1; else if ( (bb == '\0') && (aa != '\0') ) /* if b ends before a, then a is greater than b */ different = 1; else if ( (aa == '\0') && (bb == '\0') ) /* if a and b end at the same time, then they are equal */ end = TRUE; /* * now if the strings haven't ended, check to see if the next * character is less than, greater than, or equal. */ else if (aa < bb) different = -1; else if (aa > bb) different = 1; else i++; } return (different); }