Merge remote-tracking branch 'origin/release-v4.5.2'
[WRF.git] / var / da / makedepf90-2.8.8 / main.c
blobe73bdeffe8a7446e297cadf5e0225661d164f811
1 /*
2 * Copyright (C) 2000-2006 Erik Edelmann <Erik.Edelmann@iki.fi>
4 * This program is free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License version 2 as published by the Free Software
7 * Foundation.
9 * This program is distributed in the hope that it will be
10 * useful, but WITHOUT ANY WARRANTY; without even the implied
11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the GNU General Public License for more
13 * details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free
17 * Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307 USA
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <fnmatch.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include "list.h"
29 #include "finddep.h"
30 #include "utils.h"
31 #include "errormesg.h"
32 #include "modfile_name.h"
33 #include "global.h"
34 #include "macro.h"
35 #include "xmalloc.h"
37 Options options;
40 typedef struct {
41 /* File Specific Rules */
42 char *file;
43 char *rule;
44 } Fsr;
47 static int fsr_strcmp(const char *file, const Fsr *rule)
49 return fnmatch(rule->file, file, FNM_PATHNAME);
53 static const char helpstring[] =
54 "\nUsage: makedepf90 [options] sourcefile(s)\n\n"
55 "Options:\n"
56 "\n-h\tprint this message to stdout and quit.\n"
57 "\n-V\tprint version and copyright information to stdout and quit.\n"
58 "\n-W\tprint warning messages about missing includes/modules.\n"
59 "\n-m fmt\tWrite mod-file names using the format 'fmt'.\n"
60 "\t'fmt' may contain any of the following modifiers:\n"
61 "\t '%%' for '%'\n"
62 "\t '%f' for name of the source file (without suffix),\n"
63 "\t '%m' for 'modulename' (in lowercase)\n"
64 "\t '%M' for 'MODULENAME' (in uppercase).\n"
65 "\tDefault: \"%f.o\".\n"
66 "\n-u module\n\tIgnore modules named 'module'.\n"
67 "\n-d file\tMake all targets dependent on 'file'.\n"
68 "\n-r rule\tAdd 'rule' (indented by a tab) to all dependency lines,\n"
69 "\texcept lines given rule(s) with the -R option below.\n"
70 "\t'rule' may contain the modifiers:\n"
71 "\t '%f' for the name (without suffix) of the source file that\n"
72 "\t line was created for.\n"
73 "\t '%%' for '%'\n"
74 "\n-R pattern rule\n\tAdd 'rule' (indented by a tab) to the dependency\n"
75 "\tline for files matching 'pattern', where 'pattern' is a\n"
76 "\t\"shell pattern\", i.e it may contain the wildcards\n"
77 "\t '*' for any number of any characters\n"
78 "\t '?' for any character\n"
79 "\t '[abc]' for any of 'a', 'b' or 'c'.\n"
80 "\n-fixed\tTreat all files as fixed format.\n"
81 "\n-free\tTreat all files as free format.\n"
82 "\n-o name\tCreate a dependency line + rule for linking the final\n"
83 "\texecutable 'name'.\n"
84 "\n-l rule\tUse 'rule' for linking the executable.\n"
85 "\tDefault: $(FC) -o $@ $(FFLAGS) $(LDFLAGS) $(FOBJ) $(LIBS)\n"
86 "\n-coco\tLook for coco set-files. Implies '-free'.\n"
87 "\n-D NAME\tDefine pre-processor symbol 'NAME'\n"
88 "\n-b PATH\tAssume object files are placed in PATH.\n"
89 "\n-nosrc\tRemove the explicit dependency on the source file\n"
90 "\n-I PATH1:PATH2:...\n\tSearch path(s) for source files\n"
91 "\n\nReport bugs to erik.edelmann@iki.fi\n";
94 static char ver[]="makedepf90 version " VERSION;
97 static const char license[]=
98 "\nCopyright (C) 2000--2006 Erik Edelmann <Erik.Edelmann@iki.fi>\n"
99 "\n"
100 "makedepf90 is free software; you can redistribute it and/or modify\n"
101 "it under the terms of the GNU General Public License version 2 as\n"
102 "published by the Free Software Foundation.\n"
103 "\n"
104 "This program is distributed in the hope that it will be useful,\n"
105 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
106 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
107 "General Public License for more details.\n"
108 "\n"
109 "You should have received a copy of the GNU General Public License\n"
110 "along with this program; if not, write to the Free Software Foundation,\n"
111 "Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.";
114 int main (int argc, char **argv)
116 int i, j, n;
117 List *files = NULL;
118 char *s, *srcfile;
119 Dependency *dep;
120 List *deplist = NULL; /* Dependencies */
121 List *modlist = NULL; /* Defined modules */
122 List *extradeps = NULL; /* "Extra" dependencies (given by the '-d' option */
123 List *rules = NULL; /* List of rules to be added to all dependency lines */
124 List *fspecrules = NULL; /* FileSpecific rules */
125 List *obj = NULL;
126 List *macrolist = NULL; /* -D MACRO */
127 Module *mod;
128 List *h1, *h2;
130 set_progname(argv[0]);
132 if (argc == 1) {
133 printf ("%s", helpstring);
134 exit (EXIT_SUCCESS);
137 /* Set a few option defaults */
138 options.warn_missing = false;
139 options.modfile_fmt = (char *)MODFILE_FMT_DEFAULT;
140 options.src_fmt = SUFFIX;
141 options.create_obj = false;
142 options.exe_name = NULL;
143 options.link_rule = (char *)LINK_RULE_DEFAULT;
144 options.coco = false;
145 options.obj_dir_set = false;
146 options.obj_dir = "";
147 options.src_dep = true;
148 options.ignore_mods = NULL;
149 options.src_path = NULL;
151 /* Parse command line arguments */
152 for (i = 1; i < argc; i++) {
153 if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
154 printf ("%s", helpstring);
155 exit (EXIT_SUCCESS);
157 } else if (strcmp(argv[i], "-V") == 0
158 || strcmp(argv[i], "--version") == 0) {
159 printf("%s\n", ver);
160 printf("%s\n", license);
161 exit (EXIT_SUCCESS);
163 } else if (strcmp(argv[i], "-W") == 0
164 || strcmp(argv[i], "-Wmissing") == 0) {
165 options.warn_missing = true;
167 } else if (strcmp(argv[i], "-Wconfused") == 0) {
168 options.warn_confused = true;
170 } else if (strncmp(argv[i], "-m", 2) == 0) {
171 if (strlen(argv[i]) == 2) {
172 if (i == argc-1) fatal_error("Option '-m' needs argument");
173 options.modfile_fmt = xstrdup(argv[++i]);
174 } else
175 options.modfile_fmt = xstrdup(&(argv[i][2]));
177 } else if (strncmp (argv[i], "-u", 2) == 0) {
178 if (strlen(argv[i]) == 2) {
179 if (i == argc-1) fatal_error("Option '-u' needs argument");
180 s = xstrdup(argv[++i]);
181 } else
182 s = xstrdup(&(argv[i][2]));
184 if (!list_find(options.ignore_mods, s, COMP_FUN(&strcasecmp)))
185 options.ignore_mods = list_prepend(options.ignore_mods, s);
187 } else if (strcmp(argv[i], "-fixed") == 0) {
188 options.src_fmt = FIXED;
190 } else if (strcmp(argv[i], "-free") == 0) {
191 options.src_fmt = FREE;
193 } else if (strncmp(argv[i], "-d", 2) == 0) {
194 if (strlen(argv[i]) == 2) {
195 if (i == argc-1) fatal_error("Option '-d' needs argument");
196 s = xstrdup(argv[++i]);
197 } else
198 s = xstrdup(&(argv[i][2]));
200 if (!list_find(extradeps, s, COMP_FUN(&strcasecmp)))
201 extradeps = list_prepend(extradeps, s);
203 } else if (strncmp(argv[i], "-r", 2) == 0) {
204 if (strlen(argv[i]) == 2) {
205 if (i == argc-1) fatal_error ("Option '-r' needs argument");
206 s = xstrdup(argv[++i]);
207 } else
208 s = xstrdup(&(argv[i][2]));
210 if (!list_find(rules, s, COMP_FUN(&strcasecmp)))
211 rules = list_append(rules, s);
213 } else if (strncmp(argv[i], "-R", 2) == 0) {
214 Fsr *h;
215 h = (Fsr *) xmalloc(sizeof(Fsr));
216 if (strlen(argv[i]) == 2) {
217 if (i == argc-1) fatal_error("Option '-R' needs 2 arguments");
218 h->file = xstrdup(argv[++i]);
219 } else
220 h->file = xstrdup(&(argv[i][2]));
222 if (i == argc-1) fatal_error("Option '-R' needs 2 arguments");
223 h->rule = xstrdup (argv[++i]);
224 fspecrules = list_append(fspecrules, h);
226 } else if (strncmp(argv[i], "-o", 2) == 0) {
227 options.create_obj = true;
228 if (strlen(argv[i]) == 2) {
229 if (i == argc-1) fatal_error("Option '-o' needs argument");
230 options.exe_name = xstrdup(argv[++i]);
231 } else
232 options.exe_name = xstrdup(&(argv[i][2]));
234 } else if (strncmp(argv[i], "-l", 2) == 0) {
235 if (strlen(argv[i]) == 2) {
236 if (i == argc-1) fatal_error("Option '-l' needs argument");
237 options.link_rule = xstrdup(argv[++i]);
238 } else
239 options.link_rule = xstrdup(&(argv[i][2]));
241 } else if (strcmp(argv[i], "-coco") == 0) {
242 options.coco = true;
243 options.src_fmt = FREE;
245 } else if (strncmp(argv[i], "-D", 2) == 0) {
246 Macro *mac;
247 char *eq;
248 char *s;
250 /* Copy the argument of -D (ignoring any '=definition') to a
251 * 'Macro' and add it to 'macrolist'. */
252 mac = macro_new ();
253 if (strlen(argv[i]) == 2) {
254 char *eq;
255 char *s;
257 if (i == argc-1) fatal_error("Option '-D' needs argument");
258 i++;
260 eq = strchr(argv[i], '=');
261 if (eq != NULL)
262 s = xstrndup(argv[i], eq - argv[i]);
263 else
264 s = xstrdup(argv[i]);
266 macro_setname(mac, s);
267 } else {
268 eq = strchr(&argv[i][2], '=');
269 if (eq != NULL)
270 s = xstrndup(&argv[i][2], eq - argv[i] - 2);
271 else
272 s = xstrdup(&argv[i][2]);
274 macro_setname(mac, s);
276 if (!list_find(macrolist, mac, &macrocmp))
277 macrolist = list_prepend(macrolist, mac);
279 } else if (strncmp(argv[i], "-b", 2) == 0) {
280 if (strlen(argv[i]) == 2) {
281 if (i == argc - 1) fatal_error("Option '-b' needs argument");
282 options.obj_dir = xstrdup(argv[++i]);
283 } else
284 if (argv[i][2] == '=') {
285 options.obj_dir = xstrdup(&(argv[i][3]));
286 } else
287 options.obj_dir = xstrdup(&(argv[i][2]));
289 n = strlen(options.obj_dir);
290 if (n > 0 && options.obj_dir[n - 1] != '/') {
291 options.obj_dir = xrealloc(options.obj_dir, n+2);
292 strcat(options.obj_dir, "/");
295 options.obj_dir_set = true;
297 } else if (strncmp(argv[i], "-I", 2) == 0) {
298 int jp;
300 if (strlen(argv[i]) == 2) {
301 if (i == argc - 1) fatal_error("Option '-I' needs argument");
302 s = xstrdup(argv[++i]);
303 } else
304 if (argv[i][2] == '=' ) {
305 s = xstrdup(&(argv[i][3]));
306 } else
307 s = xstrdup(&(argv[i][2]));
309 n = strlen(s);
310 jp = 0;
311 for(j = 0;j < n; j++){
312 if (s[j] == ' ' || s[j]==':') {
313 options.src_path = list_append(options.src_path,
314 xstrndup(s+jp, j-jp));
315 jp = j + 1;
316 } else if (j == n-1) {
317 options.src_path = list_append(options.src_path,xstrdup(s+jp));
321 } else if (strcmp(argv[i], "-nosrc") == 0) {
322 options.src_dep = false;
325 * Add new options here
328 } else if (*argv[i] == '-') {
329 fatal_error("Unknown Option '%s'", argv[i]);
331 } else {
332 /* Gee, we got a filename! */
333 if (!list_find(files, argv[i], COMP_FUN(&strcasecmp)))
334 files = list_prepend(files, argv[i]);
338 /* Parse the files, creating target and dependency lists. */
339 for (h1 = files; h1; h1 = h1->next) {
340 char *tmp;
342 dep = dependency_new();
343 srcfile = (char *)h1->data;
344 if (find_dep(srcfile, dep, &modlist, macrolist)) {
345 dep->sourcefile = srcfile;
347 tmp = replace_suffix(srcfile, ".o");
348 if (!list_find(dep->targets, tmp, COMP_FUN(&strcasecmp)))
349 dep->targets = list_prepend(dep->targets, tmp);
350 else
351 free(tmp);
353 if (options.src_dep)
354 dep->includes = list_prepend(dep->includes, srcfile);
356 if (options.coco) {
357 char *setfile;
358 struct stat blah;
360 setfile = replace_suffix(srcfile, ".set");
361 if (stat(setfile, &blah) == 0) {
362 if (!list_find(dep->includes,setfile,COMP_FUN(&strcasecmp)))
363 dep->includes = list_append(dep->includes, setfile);
364 } else if (stat("coco.set", &blah) == 0) {
365 free(setfile);
366 setfile = xstrdup("coco.set");
367 if (!list_find(dep->includes,setfile,COMP_FUN(&strcasecmp)))
368 dep->includes = list_append(dep->includes, setfile);
369 } else
370 free(setfile);
373 deplist = list_prepend(deplist, dep);
374 } else
375 free(dep);
377 if (options.create_obj)
378 obj = list_prepend(obj, replace_suffix(srcfile, ".o"));
381 /* Print FOBJ macro and linking dependecy-line + rule. */
382 if (options.create_obj) {
383 printf("FOBJ=");
384 for (h1 = obj; h1; h1 = h1->next)
385 if (options.obj_dir_set)
386 printf("%s ", set_path(h1->data, options.obj_dir));
387 else
388 printf("%s ", (char *)h1->data);
389 printf("\n\n%s: $(FOBJ)\n\t%s\n\n", options.exe_name,options.link_rule);
392 /* Print the 'target: dependency' lists. */
393 for (h1 = deplist; h1; h1 = h1->next) {
394 bool byR = false;
396 dep = (Dependency *)h1->data;
398 /* If there are no dependencys, there is no need to output anything */
399 if (list_length(dep->includes) + list_length(dep->modules) == 0)
400 continue;
402 /* Targets */
403 for (h2 = dep->targets; h2; h2 = h2->next)
404 if (options.obj_dir_set)
405 printf("%s ", set_path(h2->data, options.obj_dir));
406 else
407 printf("%s ", (char *)h2->data);
409 printf(": ");;
411 /* Includes */
412 for (h2 = dep->includes; h2; h2 = h2->next)
413 printf("%s ", (char *)h2->data);
415 /* Modules */
416 for (h2 = dep->modules; h2; h2 = h2->next) {
417 List *l;
418 s = (char *)h2->data;
420 if (!(l = list_find(modlist, s, &modstrcmp))) {
421 /* Don't write *.mod-file to dependency list if its definition
422 * isn't found. */
423 if (options.warn_missing) warning("Module '%s' not found", s);
425 } else {
426 mod = (Module *)l->data;
427 if (strcasecmp(mod->sourcefile, dep->sourcefile) == 0) {
428 /* Dont' write *.mod-file to the dependency list if it
429 * defined in the same file it is USEd from. */
430 } else {
431 if (options.obj_dir_set)
432 printf("%s ",
433 set_path(mod->modfile_name, options.obj_dir));
434 else
435 printf("%s ", mod->modfile_name);
441 /* Extra dependencies (given with the '-d' option */
442 for (h2 = extradeps; h2; h2 = h2->next)
443 printf("%s ", (char *)h2->data);
445 putchar('\n');
447 /* Print -R rules (if there are any) */
448 for (h2 = fspecrules; h2; h2 = h2->next) {
449 Fsr *h = (Fsr *)h2->data;
451 if (fsr_strcmp(dep->sourcefile, h) == 0) {
452 char *tmp = expand_rule(h->rule, dep->sourcefile);
453 printf("%s\n", tmp);
454 free(tmp);
455 byR = true;
459 /* If the file wasn't given any rules by the -R option, print -r rules*/
460 if (!byR) {
461 for (h2 = rules; h2; h2 = h2->next) {
462 char *tmp = expand_rule((char *)h2->data, dep->sourcefile);
463 printf("%s\n", tmp);
464 free(tmp);
470 exit(EXIT_SUCCESS);