diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 328 |
1 files changed, 193 insertions, 135 deletions
@@ -30,47 +30,63 @@ const char *argp_program_version = "cflow (" PACKAGE_NAME ") " VERSION; | |||
30 | const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; | 30 | const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; |
31 | static char doc[] = ""; | 31 | static char doc[] = ""; |
32 | 32 | ||
33 | #define OPT_DEFINES 256 | ||
34 | #define OPT_LEVEL_INDENT 257 | ||
35 | #define OPT_DEBUG 258 | ||
36 | |||
33 | static struct argp_option options[] = { | 37 | static struct argp_option options[] = { |
34 | { "verbose", 'v', NULL, 0, | 38 | { NULL, 0, NULL, 0, |
35 | "be verbose on output", 0 }, | 39 | "General options:", 0}, |
36 | { "ignore-indentation", 'S', NULL, 0, | 40 | { "depth", 'd', "NUMBER", 0, |
37 | "do not rely on indentation", 0 }, | 41 | "set the depth at which the flowgraph is cut off.", 1 }, |
38 | { "c++", 'C', NULL, 0, | 42 | { "include", 'i', "SPEC", 0, |
39 | "expect C++ input", 0 }, | 43 | "Increase the number of included symbols. SPEC is a string consisting of the following characters: x (include external and static data symbols), and _ (include names that begin with an underscore). If SPEC starts with ^, its meaning is reversed", 1 }, |
40 | { "defines" , 'd', NULL, 0, | 44 | { "format", 'f', "NAME", 0, |
41 | "record defines", 0 }, | 45 | "use given output format NAME. Valid names are gnu (default) and posix", |
46 | 1 }, | ||
47 | { "reverse", 'r', NULL, 0, | ||
48 | "Print reverse call tree", 1 }, | ||
42 | { "xref", 'x', NULL, 0, | 49 | { "xref", 'x', NULL, 0, |
43 | "produce cross-reference listing only" }, | 50 | "produce cross-reference listing only", 1 }, |
44 | { "typedefs", 't', NULL, 0, | 51 | { "print", 'P', "OPT", 0, |
45 | "record typedefs" }, | 52 | "Set printing option to OPT. Valid OPT values are: xref (or cross-ref), tree. Any unambiguous abbreviation of the above is also accepted", 1 }, |
53 | { "output", 'o', "FILE", 0, | ||
54 | "set output file name (default -, meaning stdout)", 1 }, | ||
55 | |||
56 | { NULL, 0, NULL, 0, | ||
57 | "Parser control:", 10}, | ||
58 | { "ignore-indentation", 'S', NULL, 0, | ||
59 | "do not rely on indentation", 11 }, | ||
60 | { "defines" , OPT_DEFINES, NULL, 0, | ||
61 | "record defines", 11 }, | ||
62 | { "ansi", 'a', NULL, 0, | ||
63 | "Assume input to be written in ANSI C", 11 }, | ||
46 | { "pushdown", 'p', "VALUE", 0, | 64 | { "pushdown", 'p', "VALUE", 0, |
47 | "set initial token stack size to VALUE", 0 }, | 65 | "set initial token stack size to VALUE", 11 }, |
48 | { "symbol", 's', "SYM:TYPE", 0, | 66 | { "symbol", 's', "SYM:TYPE", 0, |
49 | "make cflow believe the symbol SYM is of type TYPE. Valid types are: keyword (or kw), modifier, identifier, type, wrapper. Any unambiguous abbreviation of the above is also accepted", 0 }, | 67 | "make cflow believe the symbol SYM is of type TYPE. Valid types are: keyword (or kw), modifier, identifier, type, wrapper. Any unambiguous abbreviation of the above is also accepted", 11 }, |
50 | { "ansi", 'a', NULL, 0, | 68 | { "main", 'm', "NAME", 0, |
51 | "Assume input to be written in ANSI C", 0 }, | 69 | "Assume main function to be called NAME", 11 }, |
52 | { "globals-only", 'g', NULL, 0, | 70 | |
53 | "Record only global symbols" }, | 71 | { NULL, 0, NULL, 0, |
72 | "Output control:", 20}, | ||
54 | { "print-level", 'l', NULL, 0, | 73 | { "print-level", 'l', NULL, 0, |
55 | "Print nesting level along with the call tree", 0 }, | 74 | "Print nesting level along with the call tree", 21 }, |
75 | { "level-indent", OPT_LEVEL_INDENT, "STRING", 0, | ||
76 | "Use STRING when indenting to each new level", 21 }, | ||
56 | { "tree", 'T', NULL, 0, | 77 | { "tree", 'T', NULL, 0, |
57 | "Draw tree", 0 }, | 78 | "Draw tree", 21 }, |
58 | { "level-indent", 'i', "STRING", 0, | 79 | { "brief", 'b', "BOOL", OPTION_ARG_OPTIONAL, |
59 | "Use STRING when indenting to each new level", 0 }, | 80 | "brief output", 21 }, |
60 | { "print", 'P', "OPT", 0, | 81 | |
61 | "Set printing option to OPT. Valid OPT values are: xref (or cross-ref), tree. Any unambiguous abbreviation of the above is also accepted" }, | 82 | { NULL, 0, NULL, 0, |
62 | { "output", 'o', "FILE", 0, | 83 | "Informational options:", 30}, |
63 | "set output file name (default -, meaning stdout)" }, | 84 | { "verbose", 'v', NULL, 0, |
64 | { "main", 'm', "NAME", 0, | 85 | "be verbose on output", 31 }, |
65 | "Assume main function to be called NAME", 0 }, | ||
66 | { "brief", 'b', NULL, 0, | ||
67 | "brief output" }, | ||
68 | { "reverse", 'r', NULL, 0, | ||
69 | "Print reverse call tree", 0 }, | ||
70 | { "format", 'f', "NAME", 0, | ||
71 | "use given output format NAME. Valid names are gnu (default) and posix", 0}, | ||
72 | { "license", 'L', 0, 0, | 86 | { "license", 'L', 0, 0, |
73 | "Print license and exit", 0 }, | 87 | "Print license and exit", 31 }, |
88 | { "debug", OPT_DEBUG, "NUMBER", OPTION_ARG_OPTIONAL, | ||
89 | "set debugging level", 31 }, | ||
74 | { 0, } | 90 | { 0, } |
75 | }; | 91 | }; |
76 | 92 | ||
@@ -89,6 +105,67 @@ char *cflow_license_text = | |||
89 | " along with GNU cflow; if not, write to the Free Software\n" | 105 | " along with GNU cflow; if not, write to the Free Software\n" |
90 | " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n"; | 106 | " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n"; |
91 | 107 | ||
108 | /* Structure representing various arguments of command line options */ | ||
109 | struct option_type { | ||
110 | char *str; /* optarg value */ | ||
111 | int min_match; /* minimal number of characters to match */ | ||
112 | int type; /* data associated with the arg */ | ||
113 | }; | ||
114 | |||
115 | static int find_option_type(struct option_type *, char *); | ||
116 | |||
117 | /* Args for --print option */ | ||
118 | struct option_type print_optype[] = { | ||
119 | { "xref", 1, PRINT_XREF }, | ||
120 | { "cross-ref", 1, PRINT_XREF }, | ||
121 | { "tree", 1, PRINT_TREE }, | ||
122 | { 0 }, | ||
123 | }; | ||
124 | /* Args for --symbol option */ | ||
125 | struct option_type symbol_optype[] = { | ||
126 | { "keyword", 2, WORD }, | ||
127 | { "kw", 2, WORD }, | ||
128 | { "modifier", 1, MODIFIER }, | ||
129 | { "identifier", 1, IDENTIFIER }, | ||
130 | { "type", 1, TYPE }, | ||
131 | { "wrapper", 1, PARM_WRAPPER }, | ||
132 | { 0 }, | ||
133 | }; | ||
134 | |||
135 | int debug; /* debug level */ | ||
136 | char *outname = "-"; /* default output file name */ | ||
137 | int print_option = 0; /* what to print. */ | ||
138 | int verbose; /* be verbose on output */ | ||
139 | int ignore_indentation; /* Don't rely on indentation, | ||
140 | * i.e. don't suppose the function body | ||
141 | * is necessarily surrounded by the curly braces | ||
142 | * in the first column | ||
143 | */ | ||
144 | int record_defines; /* Record macro definitions */ | ||
145 | int strict_ansi; /* Assume sources to be written in ANSI C */ | ||
146 | int print_levels; /* Print level number near every branch */ | ||
147 | int print_as_tree; /* Print as tree */ | ||
148 | int brief_listing; /* Produce short listing */ | ||
149 | int reverse_tree; /* Generate reverse tree */ | ||
150 | int max_depth; /* The depth at which the flowgraph is cut off */ | ||
151 | char *included_symbols = "s"; | ||
152 | /* A list of symbols included in the graph. | ||
153 | Consists of the following letters: | ||
154 | x Include (external and static) data symbols; | ||
155 | _ Include names that begin with an underscore; | ||
156 | s Include static functions; | ||
157 | t Include typedefs (for cross-references only); | ||
158 | */ | ||
159 | char *excluded_symbols = ""; | ||
160 | /* A list of symbols *not* included in the graph. | ||
161 | Overrides included_symbols */ | ||
162 | |||
163 | char *level_indent[] = { NULL, NULL }; | ||
164 | char *level_end[] = { "", "" }; | ||
165 | char *level_begin = ""; | ||
166 | |||
167 | char *start_name = "main"; /* Name of start symbol */ | ||
168 | |||
92 | static error_t | 169 | static error_t |
93 | parse_opt (int key, char *arg, struct argp_state *state) | 170 | parse_opt (int key, char *arg, struct argp_state *state) |
94 | { | 171 | { |
@@ -98,11 +175,8 @@ parse_opt (int key, char *arg, struct argp_state *state) | |||
98 | case 'a': | 175 | case 'a': |
99 | strict_ansi = 1; | 176 | strict_ansi = 1; |
100 | break; | 177 | break; |
101 | case 'C': | 178 | case OPT_DEBUG: |
102 | assume_cplusplus = 1; | 179 | debug = arg ? atoi(arg) : 1; |
103 | break; | ||
104 | case 'D': | ||
105 | debug = 1; | ||
106 | break; | 180 | break; |
107 | case 'L': | 181 | case 'L': |
108 | printf("License for %s:\n\n", argp_program_version); | 182 | printf("License for %s:\n\n", argp_program_version); |
@@ -122,20 +196,30 @@ parse_opt (int key, char *arg, struct argp_state *state) | |||
122 | level_end[1] = "\\-"; | 196 | level_end[1] = "\\-"; |
123 | break; | 197 | break; |
124 | case 'b': | 198 | case 'b': |
125 | brief_listing = 1; | 199 | brief_listing = arg ? (arg[0] == 'y' || arg[0] == 'Y') : 1; |
126 | break; | 200 | break; |
127 | case 'd': | 201 | case 'd': |
202 | max_depth = atoi(arg); | ||
203 | if (max_depth < 0) | ||
204 | max_depth = 0; | ||
205 | break; | ||
206 | case OPT_DEFINES: | ||
128 | record_defines = 1; | 207 | record_defines = 1; |
129 | break; | 208 | break; |
130 | case 'f': | 209 | case 'f': |
131 | if (select_output_driver(arg)) | 210 | if (select_output_driver(arg)) |
132 | argp_error(state, "%s: No such output driver", optarg); | 211 | argp_error(state, "%s: No such output driver", optarg); |
212 | else if (strcmp (arg, "posix") == 0) | ||
213 | brief_listing = 1; | ||
133 | break; | 214 | break; |
134 | case 'g': | 215 | case OPT_LEVEL_INDENT: |
135 | globals_only = 1; | 216 | set_level_indent(arg); |
136 | break; | 217 | break; |
137 | case 'i': | 218 | case 'i': |
138 | set_level_indent(arg); | 219 | if (arg[0] == '^') |
220 | excluded_symbols = arg+1; | ||
221 | else | ||
222 | included_symbols = arg; | ||
139 | break; | 223 | break; |
140 | case 'l': | 224 | case 'l': |
141 | print_levels = 1; | 225 | print_levels = 1; |
@@ -157,9 +241,6 @@ parse_opt (int key, char *arg, struct argp_state *state) | |||
157 | case 's': | 241 | case 's': |
158 | symbol_override(arg); | 242 | symbol_override(arg); |
159 | break; | 243 | break; |
160 | case 't': | ||
161 | record_typedefs = 1; | ||
162 | break; | ||
163 | case 'v': | 244 | case 'v': |
164 | verbose = 1; | 245 | verbose = 1; |
165 | break; | 246 | break; |
@@ -182,109 +263,55 @@ static struct argp argp = { | |||
182 | NULL | 263 | NULL |
183 | }; | 264 | }; |
184 | 265 | ||
185 | /* Structure representing various arguments of command line options */ | 266 | int |
186 | struct option_type { | 267 | included_char(int c) |
187 | char *str; /* optarg value */ | ||
188 | int min_match; /* minimal number of characters to match */ | ||
189 | int type; /* data associated with the arg */ | ||