/* * not support '...' yet */ static void pp_define_func_macro(struct lexer *lexer, const char *name) { expect(lexer, TOK_LPAREN); struct dynarr *paramlist = dynarr_init(); union token tok = lexer_next_token(lexer); if (tok.tok_tag != TOK_RPAREN) { while (true) { assume(tok, TOK_IDENTIFIER); dynarr_add(paramlist, tok.id.s); tok = lexer_next_token(lexer); if (tok.tok_tag == TOK_RPAREN) { break; } else { assume(tok, TOK_COMMA); } tok = lexer_next_token(lexer); } } struct dynarr *darr = store_token_until_newline(lexer); struct macro *macro = func_macro_init(paramlist, darr); define_macro(lexer, name, macro); #if DUMP_MACRO macro_dump(lexer, name, macro); #endif }
static void pp_define_object_macro(struct lexer *lexer, const char *name) { struct dynarr *darr = store_token_until_newline(lexer); // simple check for: #define x x case. // a real example is in: /usr/include/bits/confname.h // // the ultimate way to sovle the (indirectly) referring itself obj/func macro is // constructing the macro expanding tree if (dynarr_size(darr) == 1) { union token *tok = dynarr_get(darr, 0); if (tok->tok_tag == TOK_IDENTIFIER && strcmp(tok->id.s, name) == 0) { token_destroy(*tok); free(tok); dynarr_destroy(darr); red("ignore identity obj macro %s", name); return; } } struct macro *macro = obj_macro_init(darr); define_macro(lexer, name, macro); #if DUMP_MACRO // fprintf(stderr, "%s define the macro %s\n", lexer->cstream->path, name); macro_dump(lexer, name, macro); #endif }
void pp_cmdline_define(struct lexer *lexer, const char *id) { struct dynarr *darr = dynarr_init(); union token int_const_tok = wrap_int_const_to_token(1); dynarr_add(darr, token_shallow_dup(&int_const_tok)); struct macro *macro = obj_macro_init(darr); define_macro(lexer, id, macro); }
static void initialize_ucpp(struct lexer_state *ls, FILE *in) { int i; /* * This code is an adaption of ucpp's sample.c */ /* step 1 */ init_cpp(); /* step 2 */ no_special_macros = 0; emit_defines = emit_assertions = 0; /* step 3 -- with assertions */ init_tables(1); /* step 4 -- no default include path */ init_include_path(0); /* step 5 -- no need to reset the two emit_* variables set in 2 */ emit_dependencies = 0; /* step 6 -- we work with stdin, this is not a real filename */ set_init_filename("[stdin]", 0); /* step 7 -- we make sure that assertions are on, and pragma are handled */ init_lexer_state(ls); init_lexer_mode(ls); ls->flags |= HANDLE_ASSERTIONS | HANDLE_PRAGMA | LINE_NUM; /* step 8 -- input is from specified FILE stream */ ls->input = in; /* step 9 -- we do not have any macro to define, but we add any argument as an include path */ /* for (i = 1; i < argc; i ++) add_incpath(argv[i]);*/ add_incpath("/usr/local/nwcc/include"); /* XXXXXXXXXXXXXXXX */ add_incpath("/usr/include"); /* XXXXXXXXXXXXXXXX */ for (i = 0; cpp_args[i] != NULL; ++i ){ if (strncmp(cpp_args[i], "-I", 2) == 0) { add_incpath(cpp_args[i]+2); } else if (strncmp(cpp_args[i], "-D", 2) == 0) { define_macro(ls, cpp_args[i]+2); } else if (strncmp(cpp_args[i], "-U", 2) == 0) { undef_macro(ls, cpp_args[i]+2); } } /* step 10 -- we are a lexer and we want CONTEXT tokens */ enter_file(ls, ls->flags); }
int main(int argc, char*argv[]) { int opt, idx; unsigned lp; 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. */ /* From 1364-2005 Chapter 19. */ define_macro("begin_keywords", "`begin_keywords", 1, 0); define_macro("celldefine", "`celldefine", 1, 0); define_macro("default_nettype", "`default_nettype", 1, 0); define_macro("end_keywords", "`end_keywords", 1, 0); define_macro("endcelldefine", "`endcelldefine", 1, 0); define_macro("line", "`line", 1, 0); define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0); define_macro("pragma", "`pragma", 1, 0); define_macro("resetall", "`resetall", 1, 0); define_macro("timescale", "`timescale", 1, 0); define_macro("unconnected_drive", "`unconnected_drive", 1, 0); /* From 1364-2005 Annex D. */ define_macro("default_decay_time", "`default_decay_time", 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_path", "`delay_mode_path", 1, 0); define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0); define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0); /* From other places. */ define_macro("disable_portfaults", "`disable_portfaults", 1, 0); define_macro("enable_portfaults", "`enable_portfaults", 1, 0); define_macro("endprotect", "`endprotect", 1, 0); define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0); define_macro("protect", "`protect", 1, 0); define_macro("suppress_faults", "`suppress_faults", 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:vV")) != 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 " VERSION " (" VERSION_TAG ")\n\n"); fprintf(stderr, "%s\n\n", COPYRIGHT); fputs(NOTICE, stderr); verbose_flag = 1; break; case 'V': fprintf(stdout, "Icarus Verilog Preprocessor version " VERSION " (" VERSION_TAG ")\n\n"); fprintf(stdout, "%s\n", COPYRIGHT); fputs(NOTICE, stdout); return 0; default: flag_errors += 1; break; } if (flag_errors) { fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n" " -F<fil> - Get defines and includes from file\n" " -f<fil> - Read the sources listed in the file\n" " -K<def> - Define a keyword macro that I just pass\n" " -L - Emit line number directives\n" " -o<fil> - Send the output to <fil>\n" " -p<fil> - Write precompiled defines to <fil>\n" " -P<fil> - Read precompiled defines from <fil>\n" " -v - Verbose\n" " -V - Print version information and quit\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) { if (out_path) fclose(out); perror(precomp_out_path); exit(1); } } if (dep_path) { depend_file = fopen(dep_path, "a"); if (depend_file == 0) { if (out_path) fclose(out); if (precomp_out) fclose(precomp_out); perror(dep_path); exit(1); } } if (source_cnt == 0) { fprintf(stderr, "%s: No input files given.\n", argv[0]); if (out_path) fclose(out); if (depend_file) fclose(depend_file); if (precomp_out) fclose(precomp_out); return 1; } if (vhdlpp_work == 0) { vhdlpp_work = strdup("ivl_vhdl_work"); } /* Pass to the lexical analyzer the list of input file, and start scanning. */ reset_lexor(out, source_list); if (yylex()) { if (out_path) fclose(out); if (depend_file) fclose(depend_file); if (precomp_out) fclose(precomp_out); return -1; } destroy_lexor(); if (depend_file) fclose(depend_file); if (precomp_out) { dump_precompiled_defines(precomp_out); fclose(precomp_out); } if (out_path) fclose(out); /* Free the source and include directory lists. */ for (lp = 0; lp < source_cnt; lp += 1) { free(source_list[lp]); } free(source_list); for (lp = 0; lp < include_cnt; lp += 1) { free(include_dir[lp]); } free(include_dir); /* Free the VHDL library directories, the path and work directory. */ for (lp = 0; lp < vhdlpp_libdir_cnt; lp += 1) { free(vhdlpp_libdir[lp]); } free(vhdlpp_libdir); free(vhdlpp_path); free(vhdlpp_work); free_macros(); return error_count; }
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); char*arg; while (tail > cp) { if (! isspace((int)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. */ arg = strchr(cp, ':'); if (arg) *arg++ = 0; if (strcmp(cp,"D") == 0) { char*val = strchr(arg, '='); const char *valo = "1"; if (val) { *val++ = 0; valo = val; } define_macro(arg, valo, 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,"Ma") == 0) || (strcmp(cp,"Mi") == 0) || (strcmp(cp,"Mm") == 0) || (strcmp(cp,"Mp") == 0)) { if (dep_path) { fprintf(stderr, "duplicate -M flag.\n"); } else { dep_mode = cp[1]; dep_path = strdup(arg); } } else if (strcmp(cp,"relative include") == 0) { if (strcmp(arg, "true") == 0) { relative_include = 1; } else { relative_include = 0; } } else if (strcmp(cp,"vhdlpp") == 0) { if (vhdlpp_path) { fprintf(stderr, "Ignore multiple vhdlpp flags\n"); } else { vhdlpp_path = strdup(arg); } } else if (strcmp(cp,"vhdlpp-work") == 0) { if (vhdlpp_work) { fprintf(stderr, "Ignore duplicate vhdlpp-work flags\n"); } else { vhdlpp_work = strdup(arg); } } else if (strcmp(cp,"vhdlpp-libdir") == 0) { vhdlpp_libdir = realloc(vhdlpp_libdir, (vhdlpp_libdir_cnt+1)*sizeof(char*)); vhdlpp_libdir[vhdlpp_libdir_cnt] = strdup(arg); vhdlpp_libdir_cnt += 1; } else { fprintf(stderr, "%s: Invalid keyword %s\n", path, cp); } } fclose(fd); return 0; }
int main(int argc, char*argv[]) { int opt, idx; const char*flist_path = 0; unsigned flag_errors = 0; const char*out_path = 0; const char*dep_path = NULL; FILE*out; /* Define preprocessor keywords that I plan to just pass. */ define_macro("celldefine", "`celldefine", 1); define_macro("default_nettype", "`default_nettype", 1); define_macro("delay_mode_distributed", "`delay_mode_distributed", 1); define_macro("delay_mode_unit", "`delay_mode_unit", 1); define_macro("delay_mode_path", "`delay_mode_path", 1); define_macro("disable_portfaults", "`disable_portfaults", 1); define_macro("enable_portfaults", "`enable_portfaults", 1); define_macro("endcelldefine", "`endcelldefine", 1); define_macro("endprotect", "`endprotect", 1); define_macro("nosuppress_faults", "`nosuppress_faults", 1); define_macro("nounconnected_drive", "`nounconnected_drive", 1); define_macro("protect", "`protect", 1); define_macro("resetall", "`resetall", 1); define_macro("suppress_faults", "`suppress_faults", 1); define_macro("timescale", "`timescale", 1); define_macro("unconnected_drive", "`unconnected_drive", 1); define_macro("uselib", "`uselib", 1); include_dir = malloc(sizeof(char*)); include_dir[0] = strdup("."); include_cnt = 1; while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) { case 'D': { char*tmp = strdup(optarg); char*val = strchr(tmp, '='); if (val) *val++ = 0; else val = "1"; define_macro(tmp, val, 0); free(tmp); break; } case 'f': if (flist_path) { fprintf(stderr, "%s: duplicate -f flag\n", argv[0]); flag_errors += 1; } flist_path = optarg; break; case 'I': include_dir = realloc(include_dir, (include_cnt+1)*sizeof(char*)); include_dir[include_cnt] = strdup(optarg); include_cnt += 1; break; case 'K': { char*buf = malloc(strlen(optarg) + 2); buf[0] = '`'; strcpy(buf+1, optarg); define_macro(optarg, buf, 1); free(buf); break; } case 'L': line_direct_flag = 1; break; case 'M': if (dep_path) { fprintf(stderr, "duplicate -M flag.\n"); } else { dep_path = optarg; } break; case 'o': if (out_path) { fprintf(stderr, "duplicate -o flag.\n"); } else { out_path = optarg; } break; case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version %s\n\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][-I<dir>][-D<def>] <file>...\n" " -D<def> - Predefine a value.\n" " -f<fil> - Read the sources listed in the file\n" " -I<dir> - Add an include file search directory\n" " -K<def> - Define a keyword macro that I just pass\n" " -L - Emit line number directives\n" " -M<fil> - Write dependencies to <fil>\n" " -o<fil> - Send the output to <fil>\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(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 the parser. */ reset_lexor(out, source_list); if (yyparse()) return -1; if(depend_file) { fclose(depend_file); } return error_count; }