Merge branch 'master' into verilog-ams
[sverilog.git] / ivlpp / main.c
blob2727dd7dba36eedfa30e31b5d4fcf226c2da4d35
1 const char COPYRIGHT[] =
2 "Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)";
3 /*
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 # include "config.h"
22 const char NOTICE[] =
23 " This program is free software; you can redistribute it and/or modify\n"
24 " it under the terms of the GNU General Public License as published by\n"
25 " the Free Software Foundation; either version 2 of the License, or\n"
26 " (at your option) any later version.\n"
27 "\n"
28 " This program is distributed in the hope that it will be useful,\n"
29 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
30 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
31 " GNU General Public License for more details.\n"
32 "\n"
33 " You should have received a copy of the GNU General Public License\n"
34 " along with this program; if not, write to the Free Software\n"
35 " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
38 const char VERSION[] = "$Name: $ $State: Exp $";
40 # include <stdio.h>
41 # include <stdlib.h>
42 #ifdef HAVE_MALLOC_H
43 # include <malloc.h>
44 #endif
45 # include <unistd.h>
46 # include <string.h>
47 # include <ctype.h>
48 #if defined(HAVE_GETOPT_H)
49 # include <getopt.h>
50 #endif
51 # include "globals.h"
53 #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
54 extern int getopt(int argc, char*argv[], const char*fmt);
55 extern int optind;
56 extern const char*optarg;
57 #endif
58 /* Path to the dependency file, if there is one. */
59 char *dep_path = NULL;
63 * Keep in source_list an array of pointers to file names. The array
64 * is terminated by a pointer to null.
66 static char**source_list = 0;
67 static unsigned source_cnt = 0;
69 void add_source_file(const char*name)
71 if (source_list == 0) {
72 source_list = calloc(2, sizeof(char*));
73 source_list[0] = strdup(name);
74 source_list[1] = 0;
75 source_cnt = 1;
76 } else {
77 source_list = realloc(source_list, sizeof(char*) * (source_cnt+2));
78 source_list[source_cnt+0] = strdup(name);
79 source_list[source_cnt+1] = 0;
80 source_cnt += 1;
84 char**include_dir = 0;
85 unsigned include_cnt = 0;
87 int line_direct_flag = 0;
89 unsigned error_count = 0;
90 FILE *depend_file = NULL;
92 static int flist_read_flags(const char*path)
94 char line_buf[2048];
95 FILE*fd = fopen(path, "r");
96 if (fd == 0) {
97 fprintf(stderr, "%s: unable to open for reading.\n", path);
98 return -1;
101 while (fgets(line_buf, sizeof line_buf, fd) != 0) {
102 /* Skip leading white space. */
103 char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
104 /* Remove trailing white space. */
105 char*tail = cp + strlen(cp);
106 while (tail > cp) {
107 if (! isspace(tail[-1]))
108 break;
109 tail -= 1;
110 tail[0] = 0;
113 /* Skip empty lines */
114 if (*cp == 0)
115 continue;
116 /* Skip comment lines */
117 if (cp[0] == '#')
118 continue;
120 /* The arg points to the argument to the keyword. */
121 char*arg = strchr(cp, ':');
122 if (arg) *arg++ = 0;
124 if (strcmp(cp,"D") == 0) {
125 char*val = strchr(arg, '=');
126 if (val)
127 *val++ = 0;
128 else
129 val = "1";
131 define_macro(arg, val, 0, 0);
133 } else if (strcmp(cp,"I") == 0) {
134 include_dir = realloc(include_dir,
135 (include_cnt+1)*sizeof(char*));
136 include_dir[include_cnt] = strdup(arg);
137 include_cnt += 1;
139 } else if (strcmp(cp,"keyword") == 0) {
140 char*buf = malloc(strlen(arg) + 2);
141 buf[0] = '`';
142 strcpy(buf+1, optarg);
143 define_macro(optarg, buf, 1, 0);
144 free(buf);
146 } else if (strcmp(cp,"M") == 0) {
147 if (dep_path) {
148 fprintf(stderr, "duplicate -M flag.\n");
149 } else {
150 dep_path = strdup(arg);
153 } else {
154 fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
158 fclose(fd);
159 return 0;
163 * This function reads from a file a list of file names. Each name
164 * starts with the first non-space character, and ends with the last
165 * non-space character. Spaces in the middle are OK.
167 static int flist_read_names(const char*path)
169 char line_buf[2048];
171 FILE*fd = fopen(path, "r");
172 if (fd == 0) {
173 fprintf(stderr, "%s: unable to open for reading.\n", path);
174 return 1;
177 while (fgets(line_buf, sizeof line_buf, fd) != 0) {
178 char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
179 char*tail = cp + strlen(cp);
180 while (tail > cp) {
181 if (! isspace(tail[-1]))
182 break;
183 tail -= 1;
184 tail[0] = 0;
187 if (cp < tail)
188 add_source_file(cp);
191 return 0;
194 int main(int argc, char*argv[])
196 int opt, idx;
197 const char*flist_path = 0;
198 unsigned flag_errors = 0;
199 char*out_path = 0;
200 FILE*out;
201 char*precomp_out_path = 0;
202 FILE*precomp_out = NULL;
204 /* Define preprocessor keywords that I plan to just pass. */
205 define_macro("celldefine", "`celldefine", 1, 0);
206 define_macro("default_decay_time", "`default_decay_time", 1, 0);
207 define_macro("default_nettype", "`default_nettype", 1, 0);
208 define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0);
209 define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
210 define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
211 define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
212 define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0);
213 define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
214 define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
215 define_macro("endcelldefine", "`endcelldefine", 1, 0);
216 define_macro("endprotect", "`endprotect", 1, 0);
217 define_macro("line", "`line", 1, 0);
218 define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
219 define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
220 define_macro("protect", "`protect", 1, 0);
221 define_macro("resetall", "`resetall", 1, 0);
222 define_macro("suppress_faults", "`suppress_faults", 1, 0);
223 define_macro("timescale", "`timescale", 1, 0);
224 define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
225 define_macro("uselib", "`uselib", 1, 0);
227 include_cnt = 2;
228 include_dir = malloc(include_cnt*sizeof(char*));
229 include_dir[0] = 0; /* 0 is reserved for the current files path. */
230 include_dir[1] = strdup(".");
232 while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) {
234 case 'F':
235 flist_read_flags(optarg);
236 break;
238 case 'f':
239 if (flist_path) {
240 fprintf(stderr, "%s: duplicate -f flag\n", argv[0]);
241 flag_errors += 1;
243 flist_path = optarg;
244 break;
246 case 'K': {
247 char*buf = malloc(strlen(optarg) + 2);
248 buf[0] = '`';
249 strcpy(buf+1, optarg);
250 define_macro(optarg, buf, 1, 0);
251 free(buf);
252 break;
255 case 'L':
256 line_direct_flag = 1;
257 break;
259 case 'o':
260 if (out_path) {
261 fprintf(stderr, "duplicate -o flag.\n");
262 } else {
263 out_path = optarg;
265 break;
267 case 'p':
268 if (precomp_out_path) {
269 fprintf(stderr, "duplicate -p flag.\n");
270 } else {
271 precomp_out_path = optarg;
273 break;
275 case 'P': {
276 FILE*src = fopen(optarg, "rb");
277 if (src == 0) {
278 perror(optarg);
279 exit(1);
281 load_precompiled_defines(src);
282 fclose(src);
283 break;
286 case 'v':
287 fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
288 VERSION);
289 fprintf(stderr, "%s\n", COPYRIGHT);
290 fputs(NOTICE, stderr);
291 break;
293 default:
294 flag_errors += 1;
295 break;
298 if (flag_errors) {
299 fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n"
300 " -F<fil> - Get defines and includes from file\n"
301 " -f<fil> - Read the sources listed in the file\n"
302 " -K<def> - Define a keyword macro that I just pass\n"
303 " -L - Emit line number directives\n"
304 " -o<fil> - Send the output to <fil>\n"
305 " -p<fil> - Write precompiled defines to <fil>\n"
306 " -P<fil> - Read precompiled defines from <fil>\n"
307 " -v - Print version information\n",
308 argv[0]);
309 return flag_errors;
312 /* Collect the file names on the command line in the source
313 file list, then if there is a file list, read more file
314 names from there. */
315 for (idx = optind ; idx < argc ; idx += 1)
316 add_source_file(argv[idx]);
319 if (flist_path) {
320 int rc = flist_read_names(flist_path);
321 if (rc != 0)
322 return rc;
325 /* Figure out what to use for an output file. Write to stdout
326 if no path is specified. */
327 if (out_path) {
328 out = fopen(out_path, "w");
329 if (out == 0) {
330 perror(out_path);
331 exit(1);
333 } else {
334 out = stdout;
337 if (precomp_out_path) {
338 precomp_out = fopen(precomp_out_path, "wb");
339 if (precomp_out == 0) {
340 perror(precomp_out_path);
341 exit(1);
345 if(dep_path) {
346 depend_file = fopen(dep_path, "w");
347 if (depend_file == 0) {
348 perror(dep_path);
349 exit(1);
353 if (source_cnt == 0) {
354 fprintf(stderr, "%s: No input files given.\n", argv[0]);
355 return 1;
358 /* Pass to the lexical analyzer the list of input file, and
359 start scanning. */
360 reset_lexor(out, source_list);
361 if (yylex()) return -1;
363 if(depend_file) {
364 fclose(depend_file);
367 if (precomp_out) {
368 dump_precompiled_defines(precomp_out);
369 fclose(precomp_out);
372 return error_count;