added "jammod" command and "genman" module
[k8jam.git] / src / gdcdeps.c
blobb493a53ce39c7bf2c402177d77084d3663661ea1
1 #define _GNU_SOURCE
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
11 #include "jam.h"
12 #include "lists.h"
13 #include "newstr.h"
15 #include "gdcdeps.h"
18 //#define GDC_DEPS_DEBUG
21 extern LIST *var_get (const char *symbol);
24 static LIST *processDepFile (const char *fname) {
25 LIST *res = NULL;
26 FILE *fl = fopen(fname, "r");
27 if (fl == NULL) return NULL;
28 char *fcont;
29 long fsize;
30 fseek(fl, 0, SEEK_END);
31 fsize = ftell(fl);
32 if (fsize <= 0) { fclose(fl); return NULL; }
33 fseek(fl, 0, SEEK_SET);
34 fcont = calloc(fsize+2, 1);
35 fread(fcont, fsize, 1, fl);
36 fclose(fl);
37 uint8_t *tmp = (uint8_t *)fcont;
38 // skip "file.o:"
39 #ifdef GDC_DEPS_DEBUG
40 printf("{{%s}}\n", tmp);
41 #endif
42 while (*tmp && *tmp != ':') ++tmp;
43 if (tmp[0] && tmp[1]) {
44 ++tmp;
45 while (*tmp) {
46 while (*tmp && (tmp[0] <= 32 || tmp[0] == '\\')) ++tmp;
47 if (!tmp[0]) goto quit;
48 #ifdef GDC_DEPS_DEBUG
49 printf("[%s]\n", tmp);
50 #endif
51 uint8_t *e = tmp;
52 while (*e && e[0] > ' ' && e[0] != '\\') ++e;
53 *e = 0;
54 res = list_new(res, (void *)tmp, 0); // don't copy it
55 #ifdef GDC_DEPS_DEBUG
56 printf(" {%s}\n", tmp);
57 #endif
58 *e = ' ';
59 tmp = e;
62 quit:
63 free(fcont);
64 return res;
68 #define ADDARG(a_) do { \
69 if (argCount >= 510) goto error_quit; \
70 args[argCount++] = (a_); \
71 } while (0)
74 #define ADDARGPF(...) do { \
75 if (argCount >= 510) goto error_quit; \
76 asprintf(&args[argCount], __VA_ARGS__); \
77 ++argCount; \
78 } while (0)
82 #define ADDINCS(vname_) do { \
83 for (const LIST *hdrs = var_get(vname_); hdrs != NULL; hdrs = hdrs->next) { \
84 if (hdrs->string[0]) { \
85 ADDARGPF("-I%s", hdrs->string); \
86 ADDARGPF("-J%s", hdrs->string); \
87 } \
88 } \
89 } while (0)
93 // NULL: can't, do text scan
94 LIST *gdcDeps (const char *srcfname) {
95 LIST *res = NULL;
96 const char *compilerBin = NULL;
97 static char *args[512];
98 int argCount = 0;
99 char tmpFName[128];
100 strcpy(tmpFName, "/tmp/jamgdctmp_XXXXXX");
101 // get out if here if D compiler is not 'gdc'
103 const LIST *gdc = var_get("GDC");
104 if (gdc == NULL || gdc->string == NULL) return NULL;
105 if (strcmp(gdc->string, "gdc") == 0) {
106 compilerBin = "gdc";
107 } else {
108 return NULL;
110 gdc = var_get("ENABLE_GDC_DEPS");
111 if (gdc == NULL || gdc->string == NULL || !gdc->string[0]) return NULL;
113 // output file name
115 int fd = mkstemp(tmpFName);
116 if (fd < 0) return NULL;
117 close(fd);
119 ADDARG(strdup(compilerBin));
120 ADDARG(strdup("-c"));
121 ADDARG(strdup("-o"));
122 ADDARG(strdup("/dev/null"));
123 // copy '-fdebug' flags
124 for (const LIST *flg = var_get("GDCFLAGS.all"); flg != NULL; flg = flg->next) {
125 if (strncmp(flg->string, "-fdebug", 7) == 0) ADDARG(strdup(flg->string));
127 // add HDRS
128 for (const LIST *hdrs = var_get("HDRS"); hdrs != NULL; hdrs = hdrs->next) {
129 if (hdrs->string[0]) {
130 ADDARGPF("-I%s", hdrs->string);
131 ADDARGPF("-J%s", hdrs->string);
134 // add SUBDIR_TOKENS
135 static char zpath[8192];
136 strcpy(zpath, ".");
137 for (const LIST *hdrs = var_get("SUBDIR_TOKENS"); hdrs != NULL; hdrs = hdrs->next) {
138 if (hdrs->string[0]) {
139 strcat(zpath, "/");
140 strcat(zpath, hdrs->string);
141 ADDARGPF("-I%s", zpath);
142 ADDARGPF("-J%s", zpath);
145 // add input file path to includes
146 strcpy(zpath, srcfname);
148 char *t = strrchr(zpath, '/');
149 if (t != NULL) {
150 *t = 0;
151 ADDARGPF("-I%s", zpath);
152 ADDARGPF("-J%s", zpath);
155 // output to...
156 ADDARGPF("-fmake-mdeps=%s", tmpFName);
157 // filename
158 ADDARG(strdup(srcfname));
159 // done
160 args[argCount] = NULL;
161 #ifdef GDC_DEPS_DEBUG
162 // dump
163 for (int f = 0; f < argCount; ++f) printf("%d: [%s]\n", f, args[f]);
164 for (int f = 0; f < argCount; ++f) printf("%s ", args[f]); printf("\n");
165 #endif
166 // exec it
167 pid_t child = fork();
168 if (child == (pid_t)-1) goto error_quit;
169 if (child == 0) {
170 // child
171 // close stdout and stderr
172 //close(0);
173 close(1);
174 close(2);
175 execvp("gdc", args);
176 //fprintf(stderr, "SHIT!!!\n");
177 abort();
179 int status;
180 waitpid(child, &status, 0);
181 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) goto error_quit;
182 #ifdef GDC_DEPS_DEBUG
183 printf("OK! %s\n", tmpFName);
184 #endif
185 res = processDepFile(tmpFName);
186 unlink(tmpFName);
187 error_quit:
188 unlink(tmpFName);
189 while (--argCount >= 0) free(args[argCount]);
190 return res;