📄 uno_local.c
字号:
/***** uno: uno_local.c *****//* Copyright (c) 2000-2003 by Lucent Technologies - Bell Laboratories *//* All Rights Reserved. This software is for educational purposes only. *//* Permission is given to distribute this code provided that this intro- *//* ductory message is not removed and no monies are exchanged. *//* No guarantee is expressed or implied by the distribution of this code. *//* Software written by Gerard J. Holzmann based on the public domain *//* ANSI-C parser Ctree Version 0.14 from Shaun Flisakowski */#include <stdio.h>#include <string.h>#include <stdlib.h>#include "uno_version.h"#define DEFINE_GLOBALS#include "globals.h"#undef DEFINE_GLOBALSint Verbose;int uno = 4, do_dflow = 1;int nopre, localonly, show_syms, keeptmps;int usecheck, allerr, allerrs, lintlike, picky, gui;char *want = "main", cur_in[512];char *preproc_info = "", *never, *master_dfn = "_uno_.dfn";char *progname = "uno:local";char *CPRE; /* set in process_input() below */treenode *parse_tree;context_t *contxt;extern char *current_filename(void);extern void name_scope(context_t *, char *, int);extern DefUse *walk_tree(treenode *, unsigned long);extern void *emalloc(uint);extern void dot_start(treenode *);voidUsage(char *prog){ fprintf(stderr, "%s\n", VERSION); fprintf(stderr, "=======================\n"); fprintf(stderr,"Usage: %s [option] file.c\n", prog); fprintf(stderr,"\t-V\tversion information\n"); fprintf(stderr,"\t-s\tsymbol table information\n"); fprintf(stderr,"\t-CPP=...\tset preprocessor\n"); fprintf(stderr,"\t-D...\tdefine macro name (preprocessor)\n"); fprintf(stderr,"\t-U...\tundefine macro name (preprocessor)\n"); fprintf(stderr,"\t-I...\tdirectory to search for include files\n"); fprintf(stderr, "\t-localonly\tdo not generate intermediate .uno file\n"); fprintf(stderr, "\t-master x\tprepend file x to source before parsing\n"); fprintf(stderr, "\t-nopre \tignore #include directives\n"); fprintf(stderr, "\t-prop x\tapply user-defined property def in file x\n"); fprintf(stderr, "\t-allerr\treport all error paths, not a selection\n"); fprintf(stderr, "\t-exit x\tadd x to list of fcts known to have no return\n"); fprintf(stderr, "\t-picky\tmore picky and verbose, includes -use\n"); fprintf(stderr, "\t-use\tcomplain about redundancies\n"); fprintf(stderr, "\t-cfg\tgenerate control flow graph (from main) in dot format\n"); fprintf(stderr, "\t-cfg fct\tgenerate control flow graph (from fct) in dot format\n"); fprintf(stderr, "\t-gui\treserved for use with feaver gui\n"); fprintf(stderr, "\t-local\tignored (for backward compatability)\n"); fprintf(stderr, "\t-v\tverbose (multiple -v's add verbosity)\n"); fprintf(stderr, "\t-w\tdo not remove temporary files (debugging)\n"); exit(1);}voidadd_never(FILE *fo){ FILE *fd; char buf[1024]; if ((fd = fopen(never, "r")) == NULL) { fprintf(stderr, "uno: cannot open %s\n", never); return; } fprintf(fo, "/** property from %s: **/\n", never); fprintf(fo, "#undef ANY\n"); fprintf(fo, "#undef NONE\n"); fprintf(fo, "#undef DEF\n"); fprintf(fo, "#undef USE\n"); fprintf(fo, "#undef FCALL\n"); fprintf(fo, "#undef REF0\n"); fprintf(fo, "#undef REF1\n"); fprintf(fo, "#undef REF2\n"); fprintf(fo, "#undef DEREF\n"); fprintf(fo, "#undef ALIAS\n"); fprintf(fo, "#undef ARRAY_DECL\n"); fprintf(fo, "#undef HIDE\n"); fprintf(fo, "#undef DECL\n"); fprintf(fo, "#undef USEafterdef\n"); fprintf(fo, "#undef USEbeforedef\n"); fprintf(fo, "#undef UNO_CONST\n"); fprintf(fo, "#undef PARAM\n"); fprintf(fo, "#undef NOT_SCALAR\n"); fprintf(fo, "#define NONE %d\n", NONE); fprintf(fo, "#define ANY %d\n", ANY); fprintf(fo, "#define DEF %d\n", DEF); fprintf(fo, "#define FCALL %d\n", FCALL); fprintf(fo, "#define USE %d\n", USE); fprintf(fo, "#define REF0 %d\n", REF0); fprintf(fo, "#define REF1 %d\n", REF1); fprintf(fo, "#define REF2 %d\n", REF2); fprintf(fo, "#define DEREF %d\n", DEREF); fprintf(fo, "#define ALIAS %d\n", ALIAS); fprintf(fo, "#define ARRAY_DECL %d\n", ARRAY_DECL); fprintf(fo, "#define HIDE %d\n", HIDE); fprintf(fo, "#define DECL %d\n", DECL); fprintf(fo, "#define USEafterdef %d\n", USEafterdef); fprintf(fo, "#define USEbeforedef %d\n", USEbeforedef); fprintf(fo, "#define UNO_CONST %d\n", UNO_CONST); fprintf(fo, "#define PARAM %d\n", PARAM); fprintf(fo, "#define NOT_SCALAR (REF0|REF1|REF2|ALIAS|DEREF)\n"); fprintf(fo, "#line 1 \"%s\"\n", never); while (fgets(buf, 1024, fd)) fprintf(fo, "%s", buf); fclose(fd);}voidadd_pieces(FILE *fp, char *f){ FILE *x; char buf[1024]; if (nopre) { fprintf(fp, "typedef int __builtin_va_list;\n"); /* gcc-ism */ fprintf(fp, "typedef int __w64;\n"); /* cl-ism */ } else { fprintf(fp, "#define UnoType typedef int\n"); fprintf(fp, "UnoType __builtin_va_list;\n"); /* gcc-ism */ fprintf(fp, "UnoType __w64;\n"); /* cl-ism */ } fprintf(fp, "#define UNO\n"); if ((x = fopen(master_dfn, "r")) != NULL) { fprintf(fp, "/* from %s */\n", master_dfn); while (fgets(buf, sizeof(buf), x)) { if (nopre && strncmp(buf, "UnoType", strlen("UnoType")) == 0) fprintf(fp, "typedef int %s", &buf[strlen("UnoType")+1]); else fprintf(fp, "%s", buf); } fclose(x); fprintf(fp, "/* end */\n"); } if (!f) return; fprintf(fp, "#include \"%s\"\n", f); if (never) add_never(fp);}voidprocess_input(char *f){ FILE *fp; char *cpp1, *cpp2, *cpp_cmd; if (!CPRE) /* not set on command line */ {#ifdef CPP CPRE = CPP; /* set at compilation time */#else#ifdef PC CPRE = "cl -E -nologo"; /* microsoft visual studio */#else#ifdef PLAN9 CPRE = "cpp"; /* plan9, brazil */#else CPRE = "gcc -E"; /* unix, linux */#endif#endif#endif } if (!f || strstr(f, ".c") == NULL) Usage("uno_local"); strcpy(cur_in, f); cpp2 = (char *) emalloc(strlen(f)+1+2); sprintf(cpp2, "__%s", f); cpp1 = cpp2+sizeof(char); cpp_cmd = (char *) emalloc(sizeof(char)* (strlen(CPRE)+ (preproc_info?strlen(preproc_info):0)+ strlen(f)+ strlen(cpp2)+ 32 ) ); if (nopre) { FILE *f1, *f2; char *x, buf[4096]; if ((f1 = fopen(f, "r")) == NULL || (f2 = fopen(cpp2, "w")) == NULL) { fprintf(stderr, "uno: no file '%s', or cannot create '%s'\n", f, cpp2); exit(1); } add_pieces(f2, (char *) 0); fprintf(f2, "#line 1 \"%s\"\n", f); while (fgets(buf, sizeof(buf), f1)) { for (x = buf; *x == ' ' || *x == '\t'; x++) ; if (strncmp(x, "#include", strlen("#include")) != 0) /* not an include */ fprintf(f2, "%s", buf); else fprintf(f2, "\n"); /* maintain line count */ } if (never) add_never(f2); fclose(f1); fclose(f2); } else { if ((fp = fopen(cpp2, "w")) == NULL) { fprintf(stderr, "uno: cannot create '%s'\n", cpp2); exit(1); } add_pieces(fp, f); fclose(fp); } sprintf(cpp_cmd, "%s %s %s >%s", CPRE, preproc_info?preproc_info:"", cpp2, cpp1); if (system(cpp_cmd) < 0) { fprintf(stderr, "preprocessing command '%s' failed\n", cpp_cmd); exit(1); } if ((fp = fopen(cpp1, "r")) == NULL) { fprintf(stderr, "uno: cannot open '%s'\n", cpp2); exit(1); } init_nmetab(); ParseStack = new_treestk(); DoneStack = new_treestk(); contxt = new_context(); ParseStack->contxt = contxt; handle_new_file(ParseStack, fp, file_name); enter_scope(contxt); tree_parse(ParseStack, 0); /* gram.y */ name_scope(ParseStack->contxt, current_filename(), NONE_T); parse_tree = (top_of_stack(DoneStack))->parse_tree; fclose(fp); if (!parse_tree) fprintf(stderr, "uno: no parsetree for %s\n", f); else if (do_dflow) { dflow_reset(); walk_tree(parse_tree, 0); /* dflow.c */ } if (!keeptmps) { unlink(cpp2); unlink(cpp1); } exit_scope(contxt); free_context(contxt);}intmain(int argc, char **argv){ char *arg; argc--; argv++; file_name = "-"; while (argc-- > 0) { arg = *argv++; if (strcmp(arg, "-allerr") == 0) { allerr = allerrs = 1; continue; } else if (strcmp(arg, "-cfg") == 0) { uno = 2; if (argc > 1 && *(*argv) != '-') { want = *argv++; } continue; } else if (strcmp(arg, "-localonly") == 0) { localonly = 1; continue; } else if (strcmp(arg, "-picky") == 0) { lintlike = picky = 1; usecheck = 1; continue; } else if (strcmp(arg, "-use") == 0) { usecheck = 1; continue; } else if (strcmp(arg, "-gui") == 0) { gui = 1; continue; } else if (strcmp(arg, "-nopre") == 0) { nopre = 1; continue; } else if (strcmp(arg, "-local") == 0) { continue; /* backward compatibility with modex */ } else if (strcmp(arg, "-prop") == 0) { never = (char *) emalloc(strlen(*argv)+1); strcpy(never, *argv); argc--; argv++; continue; } else if (strcmp(arg, "-exit") == 0) { custom_exit(*argv); argc--; argv++; continue; } else if (strcmp(arg, "-master") == 0) { master_dfn = (char *) emalloc(strlen(*argv)+1); strcpy(master_dfn, *argv); argc--; argv++; continue; } else if (strcmp(arg, "-V") == 0) { printf("%s\n", VERSION); exit(0); } else if (strncmp(arg, "-v", 2) == 0) { Verbose++; /* -v or e.g. -verbose */ continue; } else if (strncmp(arg, "-w", 2) == 0) { keeptmps = 1; /* intermediate files */ continue; } else if (strcmp(arg, "-s") == 0) { show_syms = 1; continue; } if (strncmp(arg, "-CPP=", strlen("-CPP=")) == 0) { CPRE = arg+strlen("-CPP="); continue; } if (strncmp(arg, "-U", 2) == 0 || strncmp(arg, "-D", 2) == 0 || strncmp(arg, "-I", 2) == 0) { if (!preproc_info) { preproc_info = (char *) emalloc(strlen(arg)+1); strcpy(preproc_info, arg); } else { char *pp = (char *) emalloc(strlen(arg)+strlen(preproc_info)+1+1); strcpy(pp, preproc_info); strcat(pp, " "); strcat(pp, arg); preproc_info = pp; } continue; } break; } custom_exit("exit"); /* fcts known not to return */ custom_exit("fatal"); custom_exit("panic"); if (!arg) Usage("uno"); for (file_name = arg; file_name && argc >= 0; file_name = *argv++, argc--) { if (Verbose) printf("uno: %s\n", file_name); process_input(file_name); /* parses file */ lts_start(parse_tree); /* uno_lts.c */ if (show_syms) show_symtab(contxt->syms, stdout); /* uno cannot tell that contxt has a value here */ if (Verbose) memstats();#if 1 while (!is_empty(ParseStack)) delete_stk_item(pop(ParseStack)); if (Verbose) printf("parsestack\n"); while (!is_empty(DoneStack)) delete_stk_item(Parse_TOS = pop(DoneStack)); if (Verbose) printf("donestack\n"); Parse_TOS = (Stk_Item *) 0; DoneStack = (TreeStack *) 0; parse_tree = (treenode *) 0; ParseStack = (TreeStack *) 0;#endif } if (Verbose) printf("done\n"); exit(0);}char *x_stmnt(treenode *n){ extern char *buf_recur(treenode *); return buf_recur(n);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -