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
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
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
33 #include "errormesg.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];
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
);
58 /* Defined in lexer.l */
60 bool lex_include_file
(const char *incfile
);
61 void lex_set_format
(SourceFmt fmt
);
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
89 assignment_stmt: WORD ASSIGNMENT_OP other EOSTMT
/* Ignore */
91 keyword_stmt: WORD EOSTMT
{
92 if
(strcasecmp
($1, "interface") == 0)
96 | WORD WORD other EOSTMT
{
97 if
(strcasecmp
($1, "use") == 0) {
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
))) {
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);
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) {
128 } else if
(strcasecmp
($2, "interface") == 0
129 && strcasecmp
($1, "end") == 0) {
130 in_interface
= false
;
136 | WORD STRING other EOSTMT
{
137 if
(strcasecmp
($1, "include") == 0) {
143 | include STRING other EOSTMT
{
147 | CPP_INCLUDE GARBAGE other EOSTMT
/* Ignore #include <whatever.h> */
148 | define WORD other EOSTMT
{
150 DEBUG_PRINT
("%s defined\n", $2);
151 defmac
= macro_new
();
152 macro_setname
(defmac
, $2);
153 if
(!list_find
(macrolist
, defmac
, ¯ocmp
))
154 macrolist
= list_prepend
(macrolist
, defmac
);
157 | undef WORD other EOSTMT
{
163 macro_setname
(mac
, $2);
165 l
= list_find
(macrolist
, mac
, ¯ocmp
);
167 macrolist
= list_remove
(macrolist
, l
);
174 | ifdef WORD other EOSTMT
{
178 macro_setname
(mac
, $2);
183 else if
(!list_find
(macrolist
, mac
, ¯ocmp
))
186 skip_to_end
[skip_i
] = true
;
190 | ifndef WORD other EOSTMT
{
194 macro_setname
(mac
, $2);
199 if
(list_find
(macrolist
, mac
, ¯ocmp
))
202 skip_to_end
[skip_i
] = true
;
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'). */
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
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
)
222 else if
(pp_ignore
== 0)
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
277 misc_code: WORD
{ free
($1); }
278 | STRING
{ free
($1); }
281 | UNTERMINATED_STRING
{
282 if
(options.warn_confused
)
283 warning
("Unterminated string in file '%s' on line %i",
290 int yyerror(const char *s
)
294 if
(options.warn_confused
)
295 warning
("Line %i in file '%s' confuses me\n", yylineno
, curr_file
);
301 /* Return false for failure reading file, else return true. */
303 bool find_dep
(char *file
, Dependency
*d
, List
**mods
, const List
*predef_macro
)
319 yyin
= open_src_file
(file
, options.src_path
);
321 warning
("Skipping file '%s': %s", file
, strerror
(errno
));
325 /* Check source format */
326 if
(options.src_fmt
== SUFFIX
)
327 lex_set_format
(get_format
(file
));
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 */
334 for
(h
= predef_macro
; h
; h
= h
->next
) {
336 macro_copy
(mac
, (Macro
*)h
->data
);
337 if
(!list_find
(macrolist
, mac
, ¯ocmp
))
338 macrolist
= list_prepend
(macrolist
, mac
);
344 /* Delete macrolist */
345 for
(h
= macrolist
; h
; h
= h
->next
)
346 macro_free
((Macro
*)h
->data
);
347 list_free
(macrolist
);
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
)
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
;
402 curr_file
= filestack
[--filestack_i
];
406 void handle_include
(const char *incfile
)
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
);
426 m
= (Module
*) xmalloc
(sizeof
(Module
));
427 m
->modulename
= m
->modfile_name
= m
->sourcefile
= NULL
;
432 Dependency
*dependency_new
()
436 d
= (Dependency
*) xmalloc
(sizeof
(Dependency
));
437 d
->sourcefile
= NULL
;
438 d
->targets
= d
->modules
= d
->includes
= NULL
;