1 /* This file is part of GNU cflow
2    Copyright (C) 1997-2019 Sergey Poznyakoff
3 
4    GNU cflow is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    GNU cflow is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <getopt.h>
26 #include <errno.h>
27 #define obstack_chunk_alloc xmalloc
28 #define obstack_chunk_free free
29 #include <obstack.h>
30 #include <error.h>
31 #include <xalloc.h>
32 #include <gettext.h>
33 
34 #define _(c) gettext(c)
35 #define N_(c) c
36 
37 #if HAVE_LOCALE_H
38 # include <locale.h>
39 #endif
40 #if !HAVE_SETLOCALE
41 # define setlocale(category, locale) /* empty */
42 #endif
43 
44 /* Exit codes */
45 #define EX_OK    0  /* Success */
46 #define EX_FATAL 1  /* Fatal error */
47 #define EX_SOFT  2  /* Some input files cannot be read or parsed */
48 #define EX_USAGE 3  /* Command line usage error */
49 
50 #define NUMITEMS(a) sizeof(a)/sizeof((a)[0])
51 
52 struct linked_list_entry {
53      struct linked_list_entry *next, *prev;
54      struct linked_list *list;
55      void *data;
56 };
57 
58 typedef void (*linked_list_free_data_fp) (void*);
59 
60 struct linked_list {
61      linked_list_free_data_fp free_data;
62      struct linked_list_entry *head, *tail;
63 };
64 
65 #define linked_list_head(list) ((list) ? (list)->head : NULL)
66 
67 enum symtype {
68      SymUndefined,  /* Undefined or deleted symbol */
69      SymToken,      /* A token */
70      SymIdentifier  /* Function or variable */
71 };
72 
73 enum storage {
74      ExternStorage,
75      ExplicitExternStorage,
76      StaticStorage,
77      AutoStorage,
78      AnyStorage
79 };
80 
81 typedef struct {
82      int line;
83      char *source;
84 } Ref;
85 
86 enum symbol_flag {
87      symbol_none,
88      symbol_local,                 /* Unit-local symbol. Must be deleted after
89 				      processing current compilation unit */
90      symbol_parm,                  /* Parameter */
91      symbol_alias                  /* Alias to another symbol */
92 };
93 
94 typedef struct symbol Symbol;
95 
96 struct symbol {
97      struct table_entry *owner;
98      Symbol *next;                 /* Next symbol with the same hash */
99      struct linked_list_entry *entry;
100 
101      enum symtype type;            /* Type of the symbol */
102      char *name;                   /* Identifier */
103      enum symbol_flag flag;        /* Specific flag */
104      struct symbol *alias;         /* Points to the aliased symbol if
105 				      type==SymToken and flag==symbol_alias.
106 				      In this case, the rest of the structure
107 				      is ignored */
108 
109      int active;                   /* Set to 1 when the symbol's subtree is
110 				      being processed, prevent recursion */
111      int expand_line;              /* Output line when this symbol was first
112 				      expanded */
113 
114      int token_type;               /* Type of the token */
115      char *source;                 /* Source file */
116      int def_line;                 /* Source line */
117      struct linked_list *ref_line; /* Referenced in */
118 
119      int level;                    /* Block nesting level (for local vars),
120 				      Parameter nesting level (for params) */
121 
122      char *decl;                   /* Declaration */
123      enum storage storage;         /* Storage type */
124 
125      int arity;                    /* Number of parameters or -1 for
126 				      variables */
127 
128      int recursive;                /* Is the function recursive */
129      size_t ord;                   /* ordinal number */
130      struct linked_list *caller;   /* List of callers */
131      struct linked_list *callee;   /* List of callees */
132 };
133 
134 /* Output flags */
135 #define PRINT_XREF 0x01
136 #define PRINT_TREE 0x02
137 
138 #ifndef CFLOW_PREPROC
139 # define CFLOW_PREPROC "/usr/bin/cpp"
140 #endif
141 
142 #define MAX_OUTPUT_DRIVERS 8
143 
144 extern unsigned char *level_mark;
145 extern FILE *outfile;
146 extern char *outname;
147 
148 extern int verbose;
149 extern int print_option;
150 extern int use_indentation;
151 extern int assume_cplusplus;
152 extern int record_defines;
153 extern int strict_ansi;
154 extern char *level_indent[];
155 extern char *level_end[];
156 extern char *level_begin;
157 extern int print_levels;
158 extern int print_line_numbers;
159 extern int print_as_tree;
160 extern int brief_listing;
161 extern int reverse_tree;
162 extern int out_line;
163 extern char *start_name;
164 extern int all_functions;
165 extern int max_depth;
166 extern int emacs_option;
167 extern int debug;
168 extern int preprocess_option;
169 extern int omit_arguments_option;
170 extern int omit_symbol_names_option;
171 
172 extern int token_stack_length;
173 extern int token_stack_increase;
174 
175 extern int symbol_count;
176 extern unsigned input_file_count;
177 
178 #define INSTALL_DEFAULT     0x00
179 #define INSTALL_OVERWRITE   0x01
180 #define INSTALL_CHECK_LOCAL 0x02
181 #define INSTALL_UNIT_LOCAL  0x04
182 
183 Symbol *lookup(const char*);
184 Symbol *install(char*, int);
185 Symbol *install_ident(char *name, enum storage storage);
186 void ident_change_storage(Symbol *sp, enum storage storage);
187 void delete_autos(int level);
188 void delete_statics(void);
189 void delete_parms(int level);
190 void move_parms(int level);
191 size_t collect_symbols(Symbol ***, int (*sel)(), size_t rescnt);
192 size_t collect_functions(Symbol ***return_sym);
193 struct linked_list *linked_list_create(linked_list_free_data_fp fun);
194 void linked_list_destroy(struct linked_list **plist);
195 void linked_list_append(struct linked_list **plist, void *data);
196 void linked_list_prepend(struct linked_list **plist, void *data);
197 void linked_list_iterate(struct linked_list **plist,
198 			 int (*itr) (void *, void *), void *data);
199 void linked_list_unlink(struct linked_list *list,
200 			struct linked_list_entry *ent);
201 size_t linked_list_size(struct linked_list *list);
202 
203 int data_in_list(void *data, struct linked_list *list);
204 
205 int get_token(void);
206 int source(char *name);
207 void init_lex(int debug_level);
208 void set_preprocessor(const char *arg);
209 void pp_option(const char *arg);
210 
211 void init_parse(void);
212 int yyparse(void);
213 
214 void output(void);
215 void newline(void);
216 void print_level(int lev, int last);
217 int globals_only(void);
218 int include_symbol(Symbol *sym);
219 int symbol_is_function(Symbol *sym);
220 
221 void sourcerc(int *, char ***);
222 
223 typedef enum {
224      cflow_output_init,
225      cflow_output_begin,
226      cflow_output_end,
227      cflow_output_newline,
228      cflow_output_separator,
229      cflow_output_symbol,
230      cflow_output_text
231 } cflow_output_command;
232 
233 struct output_symbol {
234      int direct;
235      int level;
236      int last;
237      Symbol *sym;
238 };
239 
240 int register_output(const char *name,
241 		    int (*handler) (cflow_output_command cmd,
242 				    FILE *outfile, int line,
243 				    void *data, void *handler_data),
244 		    void *handler_data);
245 int select_output_driver (const char *name);
246 void output_init(void);
247 
248 int gnu_output_handler(cflow_output_command cmd,
249 		       FILE *outfile, int line,
250 		       void *data, void *handler_data);
251 int posix_output_handler(cflow_output_command cmd,
252 			 FILE *outfile, int line,
253 			 void *data, void *handler_data);
254 
255 
256 typedef struct cflow_depmap *cflow_depmap_t;
257 cflow_depmap_t depmap_alloc(size_t count);
258 void depmap_set(cflow_depmap_t dmap, size_t row, size_t col);
259 int depmap_isset(cflow_depmap_t dmap, size_t row, size_t col);
260 void depmap_tc(cflow_depmap_t dmap);
261