const char COPYRIGHT[] = "Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)"; /* * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ # include "config.h" const char NOTICE[] = " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" " the Free Software Foundation; either version 2 of the License, or\n" " (at your option) any later version.\n" "\n" " This program is distributed in the hope that it will be useful,\n" " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" " GNU General Public License for more details.\n" "\n" " You should have received a copy of the GNU General Public License\n" " along with this program; if not, write to the Free Software\n" " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n" ; const char VERSION[] = "$Name: $ $State: Exp $"; # include # include #ifdef HAVE_MALLOC_H # include #endif # include # include # include #if defined(HAVE_GETOPT_H) # include #endif # include "globals.h" #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H) extern int getopt(int argc, char*argv[], const char*fmt); extern int optind; extern const char*optarg; #endif /* Path to the dependency file, if there is one. */ char *dep_path = NULL; /* * Keep in source_list an array of pointers to file names. The array * is terminated by a pointer to null. */ static char**source_list = 0; static unsigned source_cnt = 0; void add_source_file(const char*name) { if (source_list == 0) { source_list = calloc(2, sizeof(char*)); source_list[0] = strdup(name); source_list[1] = 0; source_cnt = 1; } else { source_list = realloc(source_list, sizeof(char*) * (source_cnt+2)); source_list[source_cnt+0] = strdup(name); source_list[source_cnt+1] = 0; source_cnt += 1; } } char**include_dir = 0; unsigned include_cnt = 0; int line_direct_flag = 0; unsigned error_count = 0; FILE *depend_file = NULL; static int flist_read_flags(const char*path) { char line_buf[2048]; FILE*fd = fopen(path, "r"); if (fd == 0) { fprintf(stderr, "%s: unable to open for reading.\n", path); return -1; } while (fgets(line_buf, sizeof line_buf, fd) != 0) { /* Skip leading white space. */ char*cp = line_buf + strspn(line_buf, " \t\r\b\f"); /* Remove trailing white space. */ char*tail = cp + strlen(cp); while (tail > cp) { if (! isspace(tail[-1])) break; tail -= 1; tail[0] = 0; } /* Skip empty lines */ if (*cp == 0) continue; /* Skip comment lines */ if (cp[0] == '#') continue; /* The arg points to the argument to the keyword. */ char*arg = strchr(cp, ':'); if (arg) *arg++ = 0; if (strcmp(cp,"D") == 0) { char*val = strchr(arg, '='); if (val) *val++ = 0; else val = "1"; define_macro(arg, val, 0, 0); } else if (strcmp(cp,"I") == 0) { include_dir = realloc(include_dir, (include_cnt+1)*sizeof(char*)); include_dir[include_cnt] = strdup(arg); include_cnt += 1; } else if (strcmp(cp,"keyword") == 0) { char*buf = malloc(strlen(arg) + 2); buf[0] = '`'; strcpy(buf+1, optarg); define_macro(optarg, buf, 1, 0); free(buf); } else if (strcmp(cp,"M") == 0) { if (dep_path) { fprintf(stderr, "duplicate -M flag.\n"); } else { dep_path = strdup(arg); } } else { fprintf(stderr, "%s: Invalid keyword %s\n", path, cp); } } fclose(fd); return 0; } /* * This function reads from a file a list of file names. Each name * starts with the first non-space character, and ends with the last * non-space character. Spaces in the middle are OK. */ static int flist_read_names(const char*path) { char line_buf[2048]; FILE*fd = fopen(path, "r"); if (fd == 0) { fprintf(stderr, "%s: unable to open for reading.\n", path); return 1; } while (fgets(line_buf, sizeof line_buf, fd) != 0) { char*cp = line_buf + strspn(line_buf, " \t\r\b\f"); char*tail = cp + strlen(cp); while (tail > cp) { if (! isspace(tail[-1])) break; tail -= 1; tail[0] = 0; } if (cp < tail) add_source_file(cp); } return 0; } int main(int argc, char*argv[]) { int opt, idx; const char*flist_path = 0; unsigned flag_errors = 0; char*out_path = 0; FILE*out; char*precomp_out_path = 0; FILE*precomp_out = NULL; /* Define preprocessor keywords that I plan to just pass. */ define_macro("celldefine", "`celldefine", 1, 0); define_macro("default_decay_time", "`default_decay_time", 1, 0); define_macro("default_nettype", "`default_nettype", 1, 0); define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0); define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0); define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0); define_macro("delay_mode_path", "`delay_mode_path", 1, 0); define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0); define_macro("disable_portfaults", "`disable_portfaults", 1, 0); define_macro("enable_portfaults", "`enable_portfaults", 1, 0); define_macro("endcelldefine", "`endcelldefine", 1, 0); define_macro("endprotect", "`endprotect", 1, 0); define_macro("line", "`line", 1, 0); define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0); define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0); define_macro("protect", "`protect", 1, 0); define_macro("resetall", "`resetall", 1, 0); define_macro("suppress_faults", "`suppress_faults", 1, 0); define_macro("timescale", "`timescale", 1, 0); define_macro("unconnected_drive", "`unconnected_drive", 1, 0); define_macro("uselib", "`uselib", 1, 0); include_cnt = 2; include_dir = malloc(include_cnt*sizeof(char*)); include_dir[0] = 0; /* 0 is reserved for the current files path. */ include_dir[1] = strdup("."); while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) { case 'F': flist_read_flags(optarg); break; case 'f': if (flist_path) { fprintf(stderr, "%s: duplicate -f flag\n", argv[0]); flag_errors += 1; } flist_path = optarg; break; case 'K': { char*buf = malloc(strlen(optarg) + 2); buf[0] = '`'; strcpy(buf+1, optarg); define_macro(optarg, buf, 1, 0); free(buf); break; } case 'L': line_direct_flag = 1; break; case 'o': if (out_path) { fprintf(stderr, "duplicate -o flag.\n"); } else { out_path = optarg; } break; case 'p': if (precomp_out_path) { fprintf(stderr, "duplicate -p flag.\n"); } else { precomp_out_path = optarg; } break; case 'P': { FILE*src = fopen(optarg, "rb"); if (src == 0) { perror(optarg); exit(1); } load_precompiled_defines(src); fclose(src); break; } case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version %s\n", VERSION); fprintf(stderr, "%s\n", COPYRIGHT); fputs(NOTICE, stderr); break; default: flag_errors += 1; break; } if (flag_errors) { fprintf(stderr, "\nUsage: %s [-v][-L][-F][-f] ...\n" " -F - Get defines and includes from file\n" " -f - Read the sources listed in the file\n" " -K - Define a keyword macro that I just pass\n" " -L - Emit line number directives\n" " -o - Send the output to \n" " -p - Write precompiled defines to \n" " -P - Read precompiled defines from \n" " -v - Print version information\n", argv[0]); return flag_errors; } /* Collect the file names on the command line in the source file list, then if there is a file list, read more file names from there. */ for (idx = optind ; idx < argc ; idx += 1) add_source_file(argv[idx]); if (flist_path) { int rc = flist_read_names(flist_path); if (rc != 0) return rc; } /* Figure out what to use for an output file. Write to stdout if no path is specified. */ if (out_path) { out = fopen(out_path, "w"); if (out == 0) { perror(out_path); exit(1); } } else { out = stdout; } if (precomp_out_path) { precomp_out = fopen(precomp_out_path, "wb"); if (precomp_out == 0) { perror(precomp_out_path); exit(1); } } if(dep_path) { depend_file = fopen(dep_path, "w"); if (depend_file == 0) { perror(dep_path); exit(1); } } if (source_cnt == 0) { fprintf(stderr, "%s: No input files given.\n", argv[0]); return 1; } /* Pass to the lexical analyzer the list of input file, and start scanning. */ reset_lexor(out, source_list); if (yylex()) return -1; if(depend_file) { fclose(depend_file); } if (precomp_out) { dump_precompiled_defines(precomp_out); fclose(precomp_out); } return error_count; }