option.c: fixed warnings
[k8jam.git] / src / gdcdeps.c
blob24b038cc657e1f140696695cd5292cdb2613a22a
1 #define _GNU_SOURCE
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <stdarg.h>
9 #include <sys/types.h>
10 #include <sys/wait.h>
12 #include "jam.h"
13 #include "lists.h"
14 #include "newstr.h"
16 #include "gdcdeps.h"
19 //#define GDC_DEPS_DEBUG
22 extern LIST *var_get (const char *symbol);
25 static LIST *processDepFile (const char *fname) {
26 LIST *res = NULL;
27 FILE *fl = fopen(fname, "r");
28 if (fl == NULL) return NULL;
29 char *fcont;
30 long fsize;
31 fseek(fl, 0, SEEK_END);
32 fsize = ftell(fl);
33 if (fsize <= 0) { fclose(fl); return NULL; }
34 fseek(fl, 0, SEEK_SET);
35 fcont = calloc(fsize+2, 1);
36 fread(fcont, fsize, 1, fl);
37 fclose(fl);
38 uint8_t *tmp = (uint8_t *)fcont;
39 // skip "file.o:"
40 #ifdef GDC_DEPS_DEBUG
41 printf("{{%s}}\n", tmp);
42 #endif
43 while (*tmp && *tmp != ':') ++tmp;
44 if (tmp[0] && tmp[1]) {
45 ++tmp;
46 while (*tmp) {
47 while (*tmp && (tmp[0] <= 32 || tmp[0] == '\\')) ++tmp;
48 if (!tmp[0]) goto quit;
49 #ifdef GDC_DEPS_DEBUG
50 printf("[%s]\n", tmp);
51 #endif
52 uint8_t *e = tmp;
53 while (*e && e[0] > ' ' && e[0] != '\\') ++e;
54 *e = 0;
55 res = list_new(res, (void *)tmp, 0); // don't copy it
56 #ifdef GDC_DEPS_DEBUG
57 printf(" {%s}\n", tmp);
58 #endif
59 *e = ' ';
60 tmp = e;
63 quit:
64 free(fcont);
65 return res;
68 #ifdef _AIX
69 int vasprintf(char **ret, const char *format, va_list args)
71 va_list copy;
72 va_copy(copy, args);
74 /* Make sure it is determinate, despite manuals indicating otherwise */
75 *ret = NULL;
77 int count = vsnprintf(NULL, 0, format, args);
78 if (count >= 0)
80 char *buffer = malloc(count + 1);
81 if (buffer == NULL)
82 count = -1;
83 else if ((count = vsnprintf(buffer, count + 1, format, copy)) < 0)
84 free(buffer);
85 else
86 *ret = buffer;
88 va_end(copy); // Each va_start() or va_copy() needs a va_end()
90 return count;
93 int asprintf(char **ret, const char *format, ...)
95 va_list args;
96 va_start(args, format);
97 int count = vasprintf(ret, format, args);
98 va_end(args);
99 return(count);
101 #endif
103 #define ADDARG(a_) do { \
104 if (argCount >= 510) goto error_quit; \
105 args[argCount++] = (a_); \
106 } while (0)
109 #define ADDARGPF(...) do { \
110 if (argCount >= 510) goto error_quit; \
111 asprintf(&args[argCount], __VA_ARGS__); \
112 ++argCount; \
113 } while (0)
117 #define ADDINCS(vname_) do { \
118 for (const LIST *hdrs = var_get(vname_); hdrs != NULL; hdrs = hdrs->next) { \
119 if (hdrs->string[0]) { \
120 ADDARGPF("-I%s", hdrs->string); \
121 ADDARGPF("-J%s", hdrs->string); \
124 } while (0)
128 // NULL: can't, do text scan
129 LIST *gdcDeps (const char *srcfname) {
130 LIST *res = NULL;
131 const char *compilerBin = NULL;
132 static char *args[512];
133 int argCount = 0;
134 char tmpFName[128];
135 strcpy(tmpFName, "/tmp/jamgdctmp_XXXXXX");
136 // get out if here if D compiler is not 'gdc'
138 const LIST *gdc = var_get("GDC");
139 if (gdc == NULL || gdc->string == NULL) return NULL;
140 if (strcmp(gdc->string, "gdc") == 0) {
141 compilerBin = "gdc";
142 } else {
143 return NULL;
145 gdc = var_get("ENABLE_GDC_DEPS");
146 if (gdc == NULL || gdc->string == NULL || !gdc->string[0]) return NULL;
148 // output file name
150 int fd = mkstemp(tmpFName);
151 if (fd < 0) return NULL;
152 close(fd);
154 ADDARG(strdup(compilerBin));
155 ADDARG(strdup("-c"));
156 ADDARG(strdup("-o"));
157 ADDARG(strdup("/dev/null"));
158 // copy '-fdebug' flags
159 for (const LIST *flg = var_get("GDCFLAGS.all"); flg != NULL; flg = flg->next) {
160 if (strncmp(flg->string, "-fdebug", 7) == 0) ADDARG(strdup(flg->string));
162 // add HDRS
163 for (const LIST *hdrs = var_get("HDRS"); hdrs != NULL; hdrs = hdrs->next) {
164 if (hdrs->string[0]) {
165 ADDARGPF("-I%s", hdrs->string);
166 ADDARGPF("-J%s", hdrs->string);
169 // add SUBDIR_TOKENS
170 static char zpath[8192];
171 strcpy(zpath, ".");
172 for (const LIST *hdrs = var_get("SUBDIR_TOKENS"); hdrs != NULL; hdrs = hdrs->next) {
173 if (hdrs->string[0]) {
174 strcat(zpath, "/");
175 strcat(zpath, hdrs->string);
176 ADDARGPF("-I%s", zpath);
177 ADDARGPF("-J%s", zpath);
180 // add input file path to includes
181 strcpy(zpath, srcfname);
183 char *t = strrchr(zpath, '/');
184 if (t != NULL) {
185 *t = 0;
186 ADDARGPF("-I%s", zpath);
187 ADDARGPF("-J%s", zpath);
190 // output to...
191 ADDARGPF("-fmake-mdeps=%s", tmpFName);
192 // filename
193 ADDARG(strdup(srcfname));
194 // done
195 args[argCount] = NULL;
196 #ifdef GDC_DEPS_DEBUG
197 // dump
198 for (int f = 0; f < argCount; ++f) printf("%d: [%s]\n", f, args[f]);
199 for (int f = 0; f < argCount; ++f) printf("%s ", args[f]); printf("\n");
200 #endif
201 // exec it
202 pid_t child = fork();
203 if (child == (pid_t)-1) goto error_quit;
204 if (child == 0) {
205 // child
206 // close stdout and stderr
207 //close(0);
208 close(1);
209 close(2);
210 execvp("gdc", args);
211 //fprintf(stderr, "SHIT!!!\n");
212 abort();
214 int status;
215 waitpid(child, &status, 0);
216 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) goto error_quit;
217 #ifdef GDC_DEPS_DEBUG
218 printf("OK! %s\n", tmpFName);
219 #endif
220 res = processDepFile(tmpFName);
221 unlink(tmpFName);
222 error_quit:
223 unlink(tmpFName);
224 while (--argCount >= 0) free(args[argCount]);
225 return res;