#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"
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_include * | add_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 |
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
struct veri_Defines veri_defines |
Definition at line 12 of file verilog_preprocessor.c.
struct veri_Includes veri_includes |
Definition at line 11 of file verilog_preprocessor.c.