updated top-level README and version_decl for V4.5 (#1847)
[WRF.git] / var / da / makedepf90-2.8.8 / find_dep.y
blob329c6169c60b2c8984264fd4b234b621e0f65da1
1 %{
2 /*
3 * Copyright (C) 2000-2006 Erik Edelmann <Erik.Edelmann@iki.fi>
5 * This program is free software; you can redistribute it
6 * and/or modify it under the terms of the GNU General Public
7 * License version 2 as published by the Free Software
8 * Foundation.
10 * This program is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more
14 * details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307 USA
22 #include <errno.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
27 #ifdef HAVE_ALLOCA_H
28 # include <alloca.h>
29 #endif
31 #include "finddep.h"
32 #include "utils.h"
33 #include "errormesg.h"
34 #include "global.h"
35 #include "macro.h"
36 #include "modfile_name.h"
38 static char *sourcefile;
39 static char *curr_file;
40 static Dependency *dep; /* Dependencies of the file */
41 static List *modules; /* Modules defined in the file */
42 static List *macrolist;
43 static char *filestack[INCLUDE_RECURSION_LIMIT+1];
44 static int filestack_i;
45 static int pp_ignore; /* In 'false'-branch of a pre-processor 'if' */
46 static bool skip_to_end[20];
47 static int skip_i;
48 static bool in_interface = false;
50 int yyerror(const char *s);
52 static int modcmp(const void *m1, const void *m2);
53 SourceFmt get_format(const char *filename);
54 void handle_include(const char *incfile);
56 Macro *defmac;
58 /* Defined in lexer.l */
59 int yylex();
60 bool lex_include_file(const char *incfile);
61 void lex_set_format(SourceFmt fmt);
65 %union {
66 char *string;
67 int number;
70 %token EOSTMT ASSIGNMENT_OP GARBAGE
71 %token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
72 %token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
73 %token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
74 %token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
75 %token <string> CPP_TOENDL
76 %token <number> UNTERMINATED_STRING
77 %token <string> STRING WORD
81 code: /* empty */
82 | code stmt
85 stmt: keyword_stmt
86 | assignment_stmt
89 assignment_stmt: WORD ASSIGNMENT_OP other EOSTMT /* Ignore */
91 keyword_stmt: WORD EOSTMT {
92 if (strcasecmp($1, "interface") == 0)
93 in_interface = true;
94 free($1);
96 | WORD WORD other EOSTMT {
97 if (strcasecmp($1, "use") == 0) {
98 if (!pp_ignore) {
99 DEBUG_PRINT("Use '%s'\n", $2);
100 if (!list_find(options.ignore_mods, $2,COMP_FUN(&strcasecmp))) {
101 if (!list_find(dep->modules, $2, COMP_FUN(&strcasecmp)))
102 dep->modules = list_prepend(dep->modules, $2);
105 } else if (strcasecmp($1, "module") == 0) {
106 if (!pp_ignore && !in_interface) {
107 if (!list_find(options.ignore_mods, $2,COMP_FUN(&strcasecmp))) {
108 Module *mod;
110 mod = module_new();
111 mod->sourcefile = xstrdup(sourcefile);
112 mod->modulename = $2;
113 mod->modfile_name = modfile_name($2, mod->sourcefile);
115 if (list_find(modules, mod, &modcmp))
116 warning("Several modules named '%s'", $2);
117 else
118 modules = list_prepend(modules, mod);
120 if (!list_find(dep->targets, mod->modfile_name,
121 COMP_FUN(&strcasecmp)))
122 dep->targets=list_prepend(dep->targets, mod->modfile_name);
125 } else if (strcasecmp($1, "interface") == 0) {
126 in_interface = true;
127 free($2);
128 } else if (strcasecmp($2, "interface") == 0
129 && strcasecmp($1, "end") == 0) {
130 in_interface = false;
131 free($2);
134 free($1);
136 | WORD STRING other EOSTMT {
137 if (strcasecmp($1, "include") == 0) {
138 handle_include($2);
140 free($1);
141 free($2);
143 | include STRING other EOSTMT {
144 handle_include($2);
145 free($2);
147 | CPP_INCLUDE GARBAGE other EOSTMT /* Ignore #include <whatever.h> */
148 | define WORD other EOSTMT{
149 if (!pp_ignore) {
150 DEBUG_PRINT("%s defined\n", $2);
151 defmac = macro_new();
152 macro_setname(defmac, $2);
153 if (!list_find(macrolist, defmac, &macrocmp))
154 macrolist = list_prepend(macrolist, defmac);
157 | undef WORD other EOSTMT {
158 if (!pp_ignore) {
159 Macro *mac;
160 List *l;
162 mac = macro_new();
163 macro_setname(mac, $2);
165 l = list_find(macrolist, mac, &macrocmp);
166 if (l) {
167 macrolist = list_remove(macrolist, l);
168 macro_free(l->data);
169 list_free(l);
171 macro_free(mac);
174 | ifdef WORD other EOSTMT {
175 Macro *mac;
177 mac = macro_new();
178 macro_setname(mac, $2);
180 skip_i++;
181 if (pp_ignore)
182 pp_ignore++;
183 else if (!list_find(macrolist, mac, &macrocmp))
184 pp_ignore = 1;
185 else
186 skip_to_end[skip_i] = true;
188 macro_free(mac);
190 | ifndef WORD other EOSTMT {
191 Macro *mac;
193 mac = macro_new();
194 macro_setname(mac, $2);
196 skip_i++;
197 if (pp_ignore)
198 pp_ignore++;
199 if (list_find(macrolist, mac, &macrocmp))
200 pp_ignore = 1;
201 else
202 skip_to_end[skip_i] = true;
204 macro_free(mac);
206 | if other EOSTMT {
207 /* #if:s can't be completely ignored, since #else:s, #elif:s and
208 * #endif:s aren't. An #if branch is allways taken, and so are any
209 * following #else or #elif:s (ie. no 'skip_to_end'). */
210 skip_i++;
211 if (pp_ignore) pp_ignore++;
212 skip_to_end[skip_i] = false;
214 | elif other EOSTMT {
215 /* Allways taken unless an #ifdef or #ifndef-branch has been taken
216 * allready. */
217 if (skip_to_end[skip_i] && pp_ignore == 0) pp_ignore = 1;
219 | else other EOSTMT {
220 if (pp_ignore == 1 && skip_to_end[skip_i] == false)
221 pp_ignore = 0;
222 else if (pp_ignore == 0)
223 pp_ignore = 1;
225 | endif other EOSTMT {
226 skip_to_end[skip_i] = false;
227 if (skip_i > 0) skip_i--;
228 if (pp_ignore) pp_ignore--;
230 | WORD GARBAGE other EOSTMT /* Ignore */
231 | GARBAGE other EOSTMT
232 | EOSTMT
233 | error { yyerrok; }
236 include: CPP_INCLUDE
237 | F90PPR_INCLUDE
238 | COCO_INCLUDE
241 define: CPP_DEFINE
242 | F90PPR_DEFINE
245 undef: CPP_UNDEF
246 | F90PPR_UNDEF
249 ifdef: CPP_IFDEF
250 | F90PPR_IFDEF
253 ifndef: CPP_IFNDEF
254 | F90PPR_IFNDEF
257 if: CPP_IF
258 | F90PPR_IF
261 elif: CPP_ELIF
262 | F90PPR_ELIF
265 else: CPP_ELSE
266 | F90PPR_ELSE
269 endif: CPP_ENDIF
270 | F90PPR_ENDIF
273 other: /* empty */
274 | other misc_code
277 misc_code: WORD { free ($1); }
278 | STRING { free ($1); }
279 | GARBAGE
280 | ASSIGNMENT_OP
281 | UNTERMINATED_STRING {
282 if (options.warn_confused)
283 warning ("Unterminated string in file '%s' on line %i",
284 curr_file, $1);
290 int yyerror(const char *s)
292 extern int yylineno;
294 if (options.warn_confused)
295 warning("Line %i in file '%s' confuses me\n", yylineno, curr_file);
297 return 0;
301 /* Return false for failure reading file, else return true. */
303 bool find_dep(char *file, Dependency *d, List **mods, const List *predef_macro)
305 extern FILE *yyin;
306 extern int yylineno;
307 Macro *mac;
308 const List *h;
310 /* Initialize */
311 sourcefile = file;
312 curr_file = file;
313 dep = d;
314 modules = *mods;
315 yylineno = 1;
316 filestack_i = 0;
317 pp_ignore = 0;
319 yyin = open_src_file(file, options.src_path);
320 if (yyin == NULL) {
321 warning("Skipping file '%s': %s", file, strerror(errno));
322 return false;
325 /* Check source format */
326 if (options.src_fmt == SUFFIX)
327 lex_set_format(get_format(file));
328 else
329 lex_set_format(options.src_fmt);
331 /* Initialize a list of macros, and fill it with macrodefinitions from -D
332 * flags at the command line */
333 macrolist = NULL;
334 for (h = predef_macro; h; h = h->next) {
335 mac = macro_new();
336 macro_copy(mac, (Macro *)h->data);
337 if (!list_find(macrolist, mac, &macrocmp))
338 macrolist = list_prepend(macrolist, mac);
341 yyparse();
342 *mods = modules;
344 /* Delete macrolist */
345 for (h = macrolist; h; h = h->next)
346 macro_free((Macro *)h->data);
347 list_free(macrolist);
349 fclose(yyin);
351 return true;
355 int modstrcmp(const void *s, const void *m)
357 return strcasecmp(((Module *)m)->modulename, (char *)s);
362 static int modcmp (const void *m1, const void *m2)
364 return strcasecmp(((Module *)m1)->modulename, ((Module *)m2)->modulename);
369 static char *fixed_suffixes[] = {".f", ".F", ".for", ".FOR", ".ftn", ".FTN"};
371 static char *free_suffixes[] = {".f90", ".F90", ".f95", ".F95"};
373 static const int fixsuffn = sizeof(fixed_suffixes)/sizeof(void *);
374 static const int freesuffn = sizeof(free_suffixes)/sizeof(void *);
377 SourceFmt get_format(const char *filename)
379 const char *p;
380 int i;
382 /* Search for the end */
383 for (p = filename; *p; p++);
385 /* Search backwards for the last '.' */
386 for (; *p != '.' && p != filename; p--);
388 /* Check for any of the free suffixes */
389 for (i = 0; i < freesuffn; i++)
390 if (strcmp(p, free_suffixes[i]) == 0) return FREE;
392 /* Check for any of the fixed suffixes */
393 for (i = 0; i < fixsuffn; i++)
394 if (strcmp(p, fixed_suffixes[i]) == 0) return FIXED;
396 return UNKNOWN;
400 void pop_filestack()
402 curr_file = filestack[--filestack_i];
406 void handle_include(const char *incfile)
408 if (!pp_ignore) {
409 filestack[filestack_i++] = curr_file;
410 curr_file = remove_citation(incfile);
411 if (lex_include_file(curr_file)) {
412 DEBUG_PRINT("including file '%s'\n", curr_file);
413 if (!list_find(dep->includes, curr_file, COMP_FUN(&strcasecmp)))
414 dep->includes = list_prepend(dep->includes, curr_file);
415 } else {
416 pop_filestack();
422 Module *module_new()
424 Module *m;
426 m = (Module *) xmalloc(sizeof(Module));
427 m->modulename = m->modfile_name = m->sourcefile = NULL;
428 return m;
432 Dependency *dependency_new()
434 Dependency *d;
436 d = (Dependency *) xmalloc(sizeof(Dependency));
437 d->sourcefile = NULL;
438 d->targets = d->modules = d->includes = NULL;
439 return d;