00001 #include <ctype.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <stdlib.h>
00005 #include <sys/stat.h>
00006 #include <unistd.h>
00007 #include "verilog_preprocessor.h"
00008 #include "types.h"
00009
00010
00011 struct veri_Includes veri_includes;
00012 struct veri_Defines veri_defines;
00013
00014
00015
00016
00017
00018 int init_veri_preproc()
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 }
00039
00040
00041
00042
00043 int cleanup_veri_preproc()
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 }
00073
00074
00075
00076
00077 void clean_veri_define(veri_define *current)
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 }
00093
00094
00095
00096
00097 void clean_veri_include(veri_include *current)
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 }
00109
00110
00111
00112
00113
00114 int add_veri_define(char *symbol, char *value, int line, veri_include *defined_in)
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
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
00130 veri_defines.current_size *= 2;
00131 }
00132
00133
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
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 }
00178
00179
00180
00181
00182
00183 veri_include* add_veri_include(char *path, int line, veri_include *included_from)
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
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
00199 veri_includes.current_size *= 2;
00200 }
00201
00202
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 }
00221
00222
00223
00224
00225
00226 char* ret_veri_definedval(char *symbol)
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 }
00236
00237
00238
00239
00240 int veri_is_defined(char * symbol)
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 }
00254
00255
00256
00257
00258
00259
00260
00261 FILE* open_source_file(char* filename)
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");
00269 if (src_file != NULL)
00270 {
00271 return src_file;
00272 }
00273
00274 char* path;
00275 if (global_args.verilog_file != NULL)
00276 {
00277 path = (char *) strdup(global_args.verilog_file);
00278 }
00279 else if(global_args.config_file != NULL)
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 }
00299
00300
00301
00302
00303 FILE* veri_preproc(FILE *source)
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
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
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 }
00338
00339 void veri_preproc_bootstraped(FILE *source, FILE *preproc_producer, veri_include *current_include)
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
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
00358 last_pch = trim(line) ;
00359
00360 pch = strchr( last_pch, '`' ) ;
00361 while ( pch ) {
00362
00363 strncpy( p_proc_line, last_pch, pch - last_pch ) ;
00364 p_proc_line += pch - last_pch ;
00365 *p_proc_line = '\0' ;
00366
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
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
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
00398
00399
00400 if (line[0] == '`')
00401 {
00402 token = trim((char *)strtok(line, " \t"));
00403
00404
00405
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
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
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
00427 fputc('\n', preproc_producer);
00428 }
00429
00430
00431
00432 else if (top(skip) < 1 && strcmp(token, "`define") == 0)
00433 {
00434 char *value = NULL;
00435
00436
00437 fprintf(preproc_producer, "`define %s\n", line + 1 + strlen(line));
00438
00439
00440 token = trim(strtok(NULL, " \t"));
00441
00442
00443
00444 value = trim(strtok(NULL, "\r\n"));
00445
00446
00447
00448
00449
00450
00451
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
00463 value = trim(value) ;
00464 }
00465
00466 add_veri_define(token, value, line_number, current_include);
00467 }
00468
00469
00470
00471 else if (top(skip) < 1 && strcmp(token, "`undef") == 0)
00472 {
00473 int is_defined = 0;
00474
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
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)
00497 {
00498 push(skip, 1);
00499 }
00500 else
00501 {
00502 push(skip, 0);
00503 }
00504 }
00505
00506 else {
00507 push( skip, 2 ) ;
00508 }
00509 }
00510 else if (strcmp(token, "`ifndef") == 0)
00511 {
00512
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)
00519 {
00520 push(skip, 1);
00521 }
00522 else
00523 {
00524 push(skip, 0);
00525 }
00526 }
00527
00528 else {
00529 push( skip, 2 ) ;
00530 }
00531 }
00532 else if (strcmp(token, "`else") == 0)
00533 {
00534
00535 if(top(skip) < 1)
00536 {
00537
00538 pop(skip) ;
00539 push(skip, 1);
00540 }
00541
00542 else if (top(skip) == 1)
00543 {
00544 pop(skip) ;
00545 push(skip, 0);
00546 }
00547
00548 else {
00549
00550 }
00551 }
00552 else if (strcmp(token, "`endif") == 0)
00553 {
00554 pop(skip);
00555 }
00556
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)
00565 {
00566
00567 }
00568 }
00569 line_number++;
00570 token = NULL;
00571 }
00572 free(skip);
00573 }
00574
00575
00576
00577 char* trim(char *string)
00578 {
00579 int i = 0;
00580 if (string != NULL)
00581 {
00582
00583 while( isspace( *string ) ) string++ ;
00584
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 }
00597
00598
00599
00600
00601
00602
00603
00604 int top(veri_flag_stack *stack)
00605 {
00606 if(stack != NULL && stack->top != NULL)
00607 {
00608 return stack->top->flag;
00609 }
00610 return 0;
00611
00612 }
00613
00614 int pop(veri_flag_stack *stack)
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 }
00628 void push(veri_flag_stack *stack, int flag)
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 }
00639
00640
00641
00642