added iterator funcions for hash and rulelist
[k8jam.git] / src / hdrmacro.c
blob0ce4cad8651f4ff9d29f987c559b9b15543c04be
1 /*
2 * Copyright 1993, 2000 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6 #include "jam.h"
7 #include "lists.h"
8 #include "parse.h"
9 #include "compile.h"
10 #include "rules.h"
11 #include "variable.h"
12 #include "hsregexp.h"
13 #include "hdrmacro.h"
14 #include "hash.h"
15 #include "newstr.h"
18 * hdrmacro.c - handle header files that define macros used in
19 * #include statements.
21 * we look for lines like "#define MACRO <....>" or '#define MACRO " "'
22 * in the target file. When found, we
24 * we then phony up a rule invocation like:
26 * $(HDRRULE) <target> : <resolved included files> ;
28 * External routines:
29 * headers1() - scan a target for "#include MACRO" lines and try
30 * to resolve them when needed
32 * Internal routines:
33 * headers1() - using regexp, scan a file and build include LIST
35 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
36 * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
37 * so that headers() doesn't have to mock up a parse structure
38 * just to invoke a rule.
41 /*k8: static LIST *header_macros1(LIST *l, char *file, int rec, HSRegExp *re[]);*/
44 /* this type is used to store a dictionary of file header macros */
45 typedef struct header_macro {
46 const char* symbol;
47 const char* filename; /* we could maybe use a LIST here ?? */
48 } HEADER_MACRO;
50 static struct hash *header_macros_hash = 0;
54 * headers() - scan a target for include files and call HDRRULE
56 #define MAXINC (10)
58 void macro_headers (TARGET *t) {
59 HSRegExp re;
60 HSRxMatch mt[4];
61 int err;
62 FILE *f;
63 char buf[4096];
65 if (DEBUG_HEADER) printf("macro header scan for %s\n", t->name);
66 /* this regexp is used to detect lines of the form */
67 /* "#define MACRO <....>" or "#define MACRO "....." */
68 /* in the header macro files */
69 if ((f = fopen(t->boundname, "r")) == 0) return;
70 err = hsrxCompile(&re, "^[[:space:]]*#[[:space:]]*define[[:space:]]*([A-Za-z][A-Za-z0-9_]*)[[:space:]]*[<\"]([^\">]*)[\">].*$", HSRX_EXTENDED);
71 if (err != 0) {
72 hsrxError(err, &re, buf, sizeof(buf));
73 hsrxFree(&re);
74 printf("FATAL: %s\n", buf);
75 exit(42);
77 while (fgets(buf, sizeof(buf), f)) {
78 HEADER_MACRO var, *v = &var;
80 if (hsrxExec(&re, buf, 3, mt, 0) == HSRX_NOERROR) {
81 char buf1[MAXSYM], buf2[MAXSYM];
82 int l1, l2;
84 l1 = mt[1].rm_eo-mt[1].rm_so;
85 l2 = mt[2].rm_eo-mt[2].rm_so;
86 if (l1 > 0 && l2 > 0) {
87 memcpy(buf1, buf+mt[1].rm_so, l1); buf1[l1] = '\0';
88 memcpy(buf2, buf+mt[2].rm_so, l2); buf2[l2] = '\0';
89 /* we detected a line that looks like "#define MACRO filename */
90 if (DEBUG_HEADER) printf("macro '%s' used to define filename '%s' in '%s'\n", buf1, buf2, t->boundname);
91 /* add macro definition to hash table */
92 if (!header_macros_hash) header_macros_hash = hashinit(sizeof(HEADER_MACRO), "hdrmacros");
93 v->symbol = (const char *)buf1;
94 v->filename = 0;
95 if (hashenter(header_macros_hash, (HASHDATA **)&v)) {
96 v->symbol = newstr(buf1); /* never freed */
97 v->filename = newstr(buf2); /* never freed */
100 /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS! */
101 /* WE MIGHT AS WELL USE A LIST TO STORE THEM */
104 fclose(f);
105 hsrxFree(&re);
109 const char *macro_header_get (const char *macro_name) {
110 HEADER_MACRO var, *v = &var;
112 v->symbol = (char*)macro_name;
113 if (header_macros_hash && hashcheck(header_macros_hash, (HASHDATA **)&v)) {
114 if (DEBUG_HEADER) printf("### macro '%s' evaluated to '%s'\n", macro_name, v->filename);
115 return (const char *)v->filename;
117 return 0;