verilog_preprocessor.c File Reference

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "verilog_preprocessor.h"
#include "types.h"
Include dependency graph for verilog_preprocessor.c:

Go to the source code of this file.

Functions

int init_veri_preproc ()
int cleanup_veri_preproc ()
void clean_veri_define (veri_define *current)
void clean_veri_include (veri_include *current)
int add_veri_define (char *symbol, char *value, int line, veri_include *defined_in)
veri_includeadd_veri_include (char *path, int line, veri_include *included_from)
char * ret_veri_definedval (char *symbol)
int veri_is_defined (char *symbol)
FILE * open_source_file (char *filename)
FILE * veri_preproc (FILE *source)
void veri_preproc_bootstraped (FILE *source, FILE *preproc_producer, veri_include *current_include)
char * trim (char *string)
int top (veri_flag_stack *stack)
int pop (veri_flag_stack *stack)
void push (veri_flag_stack *stack, int flag)

Variables

struct veri_Includes veri_includes
struct veri_Defines veri_defines

Function Documentation

int add_veri_define ( char *  symbol,
char *  value,
int  line,
veri_include defined_in 
)

Definition at line 114 of file verilog_preprocessor.c.

00115 {
00116         int i;
00117         veri_define *def_iterator = veri_defines.defined_constants[0];
00118         veri_define *new_def = (veri_define *)malloc(sizeof(veri_define));
00119         if (new_def == NULL) 
00120         {
00121                 perror("new_def : malloc ");
00122                 return -1;
00123         }
00124         
00125         /* Check to see if there's enough space in our lookup table and reallocate if not. */
00126         if (veri_defines.current_index == veri_defines.current_size) 
00127         {
00128                 veri_defines.defined_constants = (veri_define **)realloc(veri_defines.defined_constants, (size_t)(veri_defines.current_size * 2) * sizeof(veri_define *));
00129                 //In a perfect world there is a check here to make sure realloc succeded
00130                 veri_defines.current_size *= 2; 
00131         }
00132         
00133         /* Check previously defined values for collisions. */
00134         for (i = 0; i < veri_defines.current_index && i < veri_defines.current_size; def_iterator = veri_defines.defined_constants[++i]) 
00135         {
00136                 if (0 == strcmp(def_iterator->symbol, symbol)) 
00137                 {
00138                         fprintf(stderr, "Warning: The constant %s defined on line %d in %s was previously defined on line %d in %s\n",
00139                                 symbol, line, defined_in->path, def_iterator->line, def_iterator->defined_in->path);
00140                         
00141                         if (value == NULL || (value[0] == '/' && value[1] == '/'))
00142 #ifndef BLOCK_EMPTY_DEFINES
00143                         {
00144                                 fprintf(stderr, "\tWarning: The new value of %s is empty\n\n", symbol); 
00145                                 free(def_iterator->value);
00146                                 def_iterator->value =NULL;
00147                         }
00148 #else           
00149                         {
00150                                 fprintf(stderr, "\tWarning: The new value of %s is empty, doing nothing\n\n", symbol);  
00151                                 return 0;
00152                         }
00153 #endif
00154                         else if (0 != strcmp(def_iterator->value, value))
00155                         {
00156                                 fprintf(stderr, "\tWarning: The value of %s has been redefined to %s, the prvious value was %s\n\n",
00157                                         symbol, value, def_iterator->value);
00158                                 free(def_iterator->value);
00159                                 def_iterator->value = (char *)strdup(value);
00160                         }
00161 
00162                         free(new_def);
00163                         return 0;
00164                 }
00165         }
00166         
00167         /* Create the new define and initalize it. */
00168         new_def->symbol = (char *)strdup(symbol);
00169         new_def->value = (value == NULL)? NULL : (char *)strdup(value);
00170         new_def->line = line;
00171         new_def->defined_in = defined_in;
00172         
00173         veri_defines.defined_constants[veri_defines.current_index] = new_def;
00174         veri_defines.current_index++;
00175         
00176         return 0;
00177 }

Here is the caller graph for this function:

veri_include* add_veri_include ( char *  path,
int  line,
veri_include included_from 
)

Definition at line 183 of file verilog_preprocessor.c.

00184 {
00185         int i;
00186         veri_include *inc_iterator = veri_includes.included_files[0];
00187         veri_include *new_inc = (veri_include *)malloc(sizeof(veri_include));
00188         if (new_inc == NULL) 
00189         {
00190                 perror("new_inc : malloc ");
00191                 return NULL;
00192         }
00193 
00194         /* Check to see if there's enough space in our lookup table and reallocate if not. */
00195         if (veri_includes.current_index == veri_includes.current_size) 
00196         {
00197                 veri_includes.included_files = (veri_include **)realloc(veri_includes.included_files, (size_t)(veri_includes.current_size * 2) * sizeof(veri_include *));
00198                 //In a perfect world there is a check here to make sure realloc succeded
00199                 veri_includes.current_size *= 2; 
00200         }
00201         
00202         /* Scan previous includes to make sure the file wasn't included previously. */
00203         for (i = 0; i < veri_includes.current_index && i < veri_includes.current_size && inc_iterator != NULL; inc_iterator = veri_includes.included_files[++i]) 
00204         {
00205                 if (0 == strcmp(path, inc_iterator->path))
00206                 {
00207                         free(new_inc);
00208                         return NULL;
00209                 }
00210         }
00211         
00212         new_inc->path = (char *)strdup(path);
00213         new_inc->included_from = included_from;
00214         new_inc->line = line;
00215         
00216         veri_includes.included_files[veri_includes.current_index] = new_inc;
00217         veri_includes.current_index++;
00218         
00219         return new_inc;
00220 }

Here is the caller graph for this function:

void clean_veri_define ( veri_define current  ) 

Definition at line 77 of file verilog_preprocessor.c.

00078 {
00079         if (current != NULL) 
00080         {
00081                 fprintf(stderr, "\tCleaning Symbol: %s, ", current->symbol);
00082                 free(current->symbol);
00083                 fprintf(stderr, "Value: %s ", current->value);
00084                 free(current->value);
00085                 
00086                 current->defined_in = NULL;
00087                 
00088                 free(current);
00089                 current=NULL;
00090                 fprintf(stderr, "...done\n");
00091         }
00092 }

Here is the caller graph for this function:

void clean_veri_include ( veri_include current  ) 

Definition at line 97 of file verilog_preprocessor.c.

00098 {
00099         if (current != NULL)
00100         {
00101                 fprintf(stderr, "\tCleaning Include: %s ", current->path);
00102                 free(current->path);
00103                 
00104                 free(current);
00105                 current = NULL;
00106                 fprintf(stderr, "...done\n");
00107         }
00108 }

Here is the caller graph for this function:

int cleanup_veri_preproc (  ) 

Definition at line 43 of file verilog_preprocessor.c.

00044 {
00045         fprintf(stderr, "Cleaning up the verilog preprocessor\n");
00046         
00047         veri_define *def_iterator = veri_defines.defined_constants[0];
00048         veri_include *inc_iterator = veri_includes.included_files[0];
00049         int i;
00050         
00051         for (i = 0; i < veri_defines.current_index && i < veri_defines.current_size; def_iterator = veri_defines.defined_constants[++i]) 
00052         {
00053                 clean_veri_define(def_iterator);
00054         }
00055         def_iterator = NULL;
00056         veri_defines.current_index = 0;
00057         veri_defines.current_size = 0;
00058         free(veri_defines.defined_constants);
00059 
00060         for (i = 0; i < veri_includes.current_index && i < veri_includes.current_size; inc_iterator = veri_includes.included_files[++i]) 
00061         {
00062                 clean_veri_include(inc_iterator);
00063         }
00064         inc_iterator = NULL;
00065         veri_includes.current_index = 0;
00066         veri_includes.current_size = 0;
00067         free(veri_includes.included_files);
00068         
00069         fprintf(stderr, " --- Finished\n");
00070 
00071         return 0;
00072 }

Here is the call graph for this function:

Here is the caller graph for this function:

int init_veri_preproc (  ) 

Definition at line 18 of file verilog_preprocessor.c.

00019 {
00020         veri_includes.included_files = (veri_include **) calloc(DefaultSize, sizeof(veri_include *));
00021         if (veri_includes.included_files == NULL) 
00022         {
00023                 perror("veri_includes.included_files : calloc ");
00024                 return -1;
00025         }
00026         veri_includes.current_size = DefaultSize;
00027         veri_includes.current_index = 0;
00028         
00029         veri_defines.defined_constants = (veri_define **) calloc(DefaultSize, sizeof(veri_define *));
00030         if (veri_defines.defined_constants == NULL) 
00031         {
00032                 perror("veri_defines.defined_constants : calloc ");
00033                 return -1;
00034         }
00035         veri_defines.current_size = DefaultSize;
00036         veri_defines.current_index = 0;
00037         return 0;
00038 }

Here is the caller graph for this function:

FILE* open_source_file ( char *  filename  ) 

Definition at line 261 of file verilog_preprocessor.c.

00262 {
00263         extern global_args_t global_args;
00264         extern config_t configuration;
00265         extern int current_parse_file;
00266 
00267         
00268         FILE* src_file = fopen(filename, "r"); //Look for the file in the PWD
00269         if (src_file != NULL)
00270         {
00271                 return src_file;
00272         }
00273         
00274         char* path;
00275         if (global_args.verilog_file != NULL) //ODIN_II was called with the -V option.
00276         {
00277                 path = (char *) strdup(global_args.verilog_file);
00278         }
00279         else if(global_args.config_file != NULL) //ODIN_II was called with the -c option.
00280         {
00281                 path = (char *) strdup(configuration.list_of_file_names[current_parse_file]);
00282         }
00283         
00284         char* last_slash = strrchr(path, '/') + 1;
00285         *last_slash = '\0';
00286         strcat(path, filename);
00287         
00288         src_file = fopen(path, "r");
00289         if (src_file != NULL)
00290         {
00291                 fprintf(stderr, "Warning: Unable to find %s in the present working directory, opening %s instead\n", 
00292                                 filename, path);
00293                 free(path);
00294                 return src_file;
00295         }
00296         
00297         return NULL;
00298 }

Here is the caller graph for this function:

int pop ( veri_flag_stack stack  ) 

Definition at line 614 of file verilog_preprocessor.c.

00615 {
00616         if(stack != NULL && stack->top != NULL)
00617         {
00618                 veri_flag_node *top = stack->top;
00619                 int flag = top->flag;
00620                 
00621                 stack->top = top->next;
00622                 free(top);
00623         
00624                 return flag;
00625         }
00626         return 0;
00627 }

Here is the call graph for this function:

Here is the caller graph for this function:

void push ( veri_flag_stack stack,
int  flag 
)

Definition at line 628 of file verilog_preprocessor.c.

00629 {
00630         if(stack != NULL)
00631         {
00632                 veri_flag_node *new_node = (veri_flag_node *)malloc(sizeof(veri_flag_node));
00633                 new_node->next = stack->top;
00634                 new_node->flag = flag;
00635                 
00636                 stack->top = new_node;
00637         }
00638 }

Here is the caller graph for this function:

char* ret_veri_definedval ( char *  symbol  ) 

Definition at line 226 of file verilog_preprocessor.c.

00227 {
00228         int is_defined = veri_is_defined(symbol);
00229         if(0 <= is_defined)
00230         {
00231                 return veri_defines.defined_constants[is_defined]->value;
00232         }
00233         return NULL;
00234         
00235 }

Here is the call graph for this function:

Here is the caller graph for this function:

int top ( veri_flag_stack stack  ) 

Definition at line 604 of file verilog_preprocessor.c.

00605 {
00606         if(stack != NULL && stack->top != NULL)
00607         {
00608                 return stack->top->flag;
00609         }
00610         return 0;
00611 
00612 }

Here is the caller graph for this function:

char* trim ( char *  string  ) 

Definition at line 577 of file verilog_preprocessor.c.

00578 {
00579         int i = 0;
00580         if (string != NULL)
00581         {
00582                 // advance past all spaces at the beginning
00583                 while( isspace( *string ) ) string++ ;
00584                 // trim all spaces at the end
00585                 for(i = strlen(string)-1; i >= 0 ; i--)
00586                 {
00587                         if(isspace(string[i]) > 0)
00588                         {
00589                                 string[i] = '\0';
00590                         }
00591                         else
00592                                 break ;
00593                 }
00594         }
00595         return string;
00596 }

Here is the caller graph for this function:

int veri_is_defined ( char *  symbol  ) 

Definition at line 240 of file verilog_preprocessor.c.

00241 {
00242         int i;
00243         veri_define *def_iterator = veri_defines.defined_constants[0];
00244         
00245         for (i = 0; (i < veri_defines.current_index) && (i < veri_defines.current_size) && (def_iterator != NULL); def_iterator = veri_defines.defined_constants[++i])
00246         {
00247                 if (0 == strcmp(symbol, def_iterator->symbol))
00248                 {
00249                         return i;
00250                 }
00251         }
00252         return -1;
00253 }

Here is the caller graph for this function:

FILE* veri_preproc ( FILE *  source  ) 

Definition at line 303 of file verilog_preprocessor.c.

00304 {
00305         extern global_args_t global_args;
00306         extern config_t configuration;
00307         extern int current_parse_file;
00308         FILE *preproc_producer = NULL;
00309         
00310         /* Was going to use filename to prevent duplication but the global var isn't used in the case of a config value */
00311         char* current_file = (global_args.verilog_file != NULL) ? global_args.verilog_file : configuration.list_of_file_names[current_parse_file];
00312         veri_include *veri_initial = add_veri_include(current_file, 0, NULL);
00313         if (veri_initial == NULL)
00314         {
00315                 fprintf(stderr, "Unable to store include information returning original FILE pointer\n\n");
00316                 return source;
00317         }
00318 
00319         preproc_producer = tmpfile();
00320         preproc_producer = freopen(NULL, "r+", preproc_producer);
00321 
00322         
00323         
00324         if (preproc_producer == NULL) 
00325         {
00326                 perror("preproc_producer : fdopen - returning original FILE pointer");
00327                 exit(-1);
00328                 return source;
00329         }
00330         
00331         /* to thread or not to thread, that is the question. Wether yac will block when waitin */
00332         fprintf(stderr, "\tpreprocessing ...\n\n");
00333         veri_preproc_bootstraped(source, preproc_producer, veri_initial);
00334 
00335         rewind(preproc_producer);       
00336         return preproc_producer;
00337 }

Here is the call graph for this function:

Here is the caller graph for this function:

void veri_preproc_bootstraped ( FILE *  source,
FILE *  preproc_producer,
veri_include current_include 
)

Definition at line 339 of file verilog_preprocessor.c.

00340 {
00341         int line_number = 1;
00342         veri_flag_stack *skip = (veri_flag_stack *)calloc(1, sizeof(veri_flag_stack));;
00343         char line[MaxLine];
00344         char *token, *p;
00345         FILE *included_file = NULL;
00346         veri_include *new_include = NULL;
00347 
00348         while (NULL != fgets(line, MaxLine, source))
00349         {
00350                 //fprintf(stderr, "%s:%d\t%s", current_include->path,line_number, line);
00351 
00352                 char proc_line[MaxLine] ;
00353                 char symbol[MaxLine] ;
00354                 char *value ;
00355                 char *p_proc_line = proc_line ;
00356                 char *last_pch, *pch, *pch_end ;
00357                 // advance past all whitespace
00358                 last_pch = trim(line) ;
00359                 // start searching for backtick
00360                 pch = strchr( last_pch, '`' ) ;
00361                 while ( pch ) {
00362                         // if symbol found, copy everything from end of last_pch to here
00363                         strncpy( p_proc_line, last_pch, pch - last_pch ) ;
00364                         p_proc_line += pch - last_pch ;
00365                         *p_proc_line = '\0' ;
00366                         // find the end of the symbol
00367                         pch_end = pch+1 ;
00368                         while ( ( *pch_end >= '0' && *pch_end <= '9' ) ||
00369                                 ( *pch_end >= 'A' && *pch_end <= 'Z' ) ||
00370                                 ( *pch_end >= 'a' && *pch_end <= 'z' ) || 
00371                                 *pch_end == '_' )
00372                                 pch_end++ ;
00373                         // copy symbol into array
00374                         strncpy( symbol, pch+1, pch_end - (pch+1) ) ;
00375                         *(symbol + (pch_end - (pch+1))) = '\0' ;
00376                         value = ret_veri_definedval( symbol ) ;
00377                         if ( value ) {
00378                                 strcpy( p_proc_line, value ) ;
00379                                 p_proc_line += strlen( value ) ;
00380                         }
00381                         else {
00382                                 // symbol not found, just pass it through
00383                                 *p_proc_line++ = '`' ;
00384                                 strcpy( p_proc_line, symbol ) ;
00385                                 p_proc_line += strlen( symbol ) ;
00386                         }
00387                         last_pch = pch_end ;
00388                         pch = strchr( last_pch+1, '`' ) ;
00389                 }
00390                 pch = strchr( last_pch, '\0' ) ;
00391                 strncpy( p_proc_line, last_pch, pch - last_pch ) ;
00392                 p_proc_line += pch - last_pch ;
00393                 *p_proc_line = '\0' ;
00394 
00395                 strcpy( line, proc_line ) ;
00396                 
00397                 //fprintf(stderr, "%s:%d\t%s\n", current_include->path,line_number, line);
00398 
00399                 /* Preprocessor directives have a backtick on the first coloumn. */
00400                 if (line[0] == '`') 
00401                 {
00402                         token = trim((char *)strtok(line, " \t"));
00403                         //printf("preproc first token: %s\n", token);
00404                         /* If we encounter an `included directive we want to recurse using included_file and 
00405                          * new_include in place of source and current_include
00406                          */
00407                         if (top(skip) < 1 && strcmp(token, "`include") == 0)
00408                         {
00409                                 token = trim((char *)strtok(NULL, "\""));
00410                                 
00411                                 included_file = open_source_file(token);
00412 
00413                                 /* If we failed to open the included file handle the error */
00414                                 if (included_file == NULL)
00415                                 {                       
00416                                         fprintf(stderr, "Warning: Unable to open file %s included on line %d of %s\n", 
00417                                                 token, line_number, current_include->path);
00418                                         perror("included_file : fopen");
00419                                         /*return erro or exit ? */
00420                                 } 
00421                                 else if (NULL != (new_include = add_veri_include(token, line_number, current_include)))
00422                                 {
00423                                         veri_preproc_bootstraped(included_file, preproc_producer, new_include);
00424                                 }
00425                                 fclose(included_file);
00426                                 /* If last included file has no newline an error could result so we add one. */
00427                                 fputc('\n', preproc_producer);
00428                         } 
00429                         /* If we encounter a `define directive we want to add it and its value if any to our
00430                          * symbol table.
00431                          */
00432                         else if (top(skip) < 1 && strcmp(token, "`define") == 0)
00433                         {
00434                                 char *value = NULL;
00435                                 
00436                                 /* strtok is destructive to the original string which we need to retain unchanged, this fixes it. */
00437                                 fprintf(preproc_producer, "`define %s\n", line + 1 + strlen(line));
00438                                 //printf("\tIn define: %s", token + 1 + strlen(token));
00439                                 
00440                                 token = trim(strtok(NULL, " \t"));
00441                                 //printf("token is: %s\n", token);
00442 
00443                                 // symbol value can potentially be to the end of the line!
00444                                 value = trim(strtok(NULL, "\r\n"));
00445                                 //printf("value is: %s\n", value);
00446 
00447                                 // however, be aware of "`define SYMBOL 1 + 2 + 3 + 4 // comment!"
00448                                 // if a comment is found, terminate string there
00449                                 // fortunately, we don't need to worry about /* */ style comments 
00450                                 // because they shouldn't comment out the rest of the line, 
00451                                 // unless it dangles past one line
00452                                 if ( value ) {
00453                                         p = value ;
00454                                         while (*p) {
00455                                                 if (*p == '/')
00456                                                         if ( *(p+1) == '/' ) {
00457                                                                 *p = '\0' ;
00458                                                                 break; 
00459                                                         }
00460                                                 p++ ;
00461                                         }
00462                                         // trim it again just in case
00463                                         value = trim(value) ;
00464                                 }
00465                                 
00466                                 add_veri_define(token, value, line_number, current_include);
00467                         }
00468                         /* If we encounter a `undef preprocessor directive we want to remove the corresponding
00469                          * symbol from our lookup table.
00470                          */
00471                         else if (top(skip) < 1 && strcmp(token, "`undef") == 0)
00472                         {
00473                                 int is_defined = 0;
00474                                 /* strtok is destructive to the original string which we need to retain unchanged, this fixes it. */
00475                                 fprintf(preproc_producer, "`undef %s", line + 1 + strlen(line));
00476                                 
00477                                 token = trim(strtok(NULL, " \t"));
00478                                 
00479                                 is_defined = veri_is_defined(token);
00480                         
00481                                 if(is_defined >= 0)
00482                                 {
00483                                         clean_veri_define(veri_defines.defined_constants[is_defined]);
00484                                         veri_defines.defined_constants[is_defined] = veri_defines.defined_constants[veri_defines.current_index];
00485                                         veri_defines.defined_constants[veri_defines.current_index--] = NULL;
00486                                 }
00487                         }
00488                         else if (strcmp(token, "`ifdef") == 0)
00489                         {
00490                                 // if parent is not skipped
00491                                 if ( top(skip) < 1 ) {
00492                                         int is_defined = 0;
00493                                         
00494                                         token = trim(strtok(NULL, " \t"));
00495                                         is_defined = veri_is_defined(token);
00496                                         if(is_defined < 0) //If we are unable to locate the symbol in the table
00497                                         {
00498                                                 push(skip, 1);
00499                                         }
00500                                         else
00501                                         {
00502                                                 push(skip, 0);
00503                                         }
00504                                 } 
00505                                 // otherwise inherit skip from parent (use 2)
00506                                 else {
00507                                         push( skip, 2 ) ;
00508                                 }
00509                         }
00510                         else if (strcmp(token, "`ifndef") == 0)
00511                         {
00512                                 // if parent is not skipped
00513                                 if ( top(skip) < 1 ) {
00514                                         int is_defined = 0;
00515                                         
00516                                         token = trim(strtok(NULL, " \t"));
00517                                         is_defined = veri_is_defined(token);
00518                                         if(is_defined >= 0) //If we are able to locate the symbol in the table
00519                                         {
00520                                                 push(skip, 1);
00521                                         }
00522                                         else
00523                                         {
00524                                                 push(skip, 0);
00525                                         }
00526                                 }
00527                                 // otherwise inherit skip from parent (use 2)
00528                                 else {
00529                                         push( skip, 2 ) ;
00530                                 }
00531                         }
00532                         else if (strcmp(token, "`else") == 0)
00533                         {
00534                                 // if skip was 0 (prev. ifdef was 1) 
00535                                 if(top(skip) < 1)
00536                                 {
00537                                         // then set to 0
00538                                         pop(skip) ;
00539                                         push(skip, 1);
00540                                 } 
00541                                 // only when prev skip was 1 do we set to 0 now
00542                                 else if (top(skip) == 1)
00543                                 {
00544                                         pop(skip) ;
00545                                         push(skip, 0);
00546                                 }
00547                                 // but if it's 2 (parent ifdef is 1)
00548                                 else {
00549                                         // then do nothing 
00550                                 }
00551                         }
00552                         else if (strcmp(token, "`endif") == 0)
00553                         {
00554                                 pop(skip);
00555                         }
00556                         /* Leave unhandled preprcessor directives in place. */
00557                         else if (top(skip) < 1)
00558                         {
00559                                 fprintf(preproc_producer, "%s %s\n", line, line + 1 + strlen(line));
00560                         }
00561                 }
00562                 else if(top(skip) < 1)
00563                 {
00564                         if (fprintf(preproc_producer, "%s\n", line) < 0)//fputs(line, preproc_producer))
00565                         {
00566                                 /* There was an error writing to the stream */
00567                         }
00568                 }
00569                 line_number++;
00570                 token = NULL;
00571         }
00572         free(skip);
00573 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 12 of file verilog_preprocessor.c.

Definition at line 11 of file verilog_preprocessor.c.

Generated on Tue Aug 2 10:43:55 2011 for ODIN_II by  doxygen 1.6.3