0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 #include <sys/types.h>
0093 #include <sys/stat.h>
0094 #include <unistd.h>
0095 #include <fcntl.h>
0096 #include <string.h>
0097 #include <stdarg.h>
0098 #include <stdlib.h>
0099 #include <stdio.h>
0100 #include <ctype.h>
0101
0102 static void usage(void)
0103 {
0104 fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
0105 exit(1);
0106 }
0107
0108 struct item {
0109 struct item *next;
0110 unsigned int len;
0111 unsigned int hash;
0112 char name[];
0113 };
0114
0115 #define HASHSZ 256
0116 static struct item *hashtab[HASHSZ];
0117
0118 static unsigned int strhash(const char *str, unsigned int sz)
0119 {
0120
0121 unsigned int i, hash = 2166136261U;
0122
0123 for (i = 0; i < sz; i++)
0124 hash = (hash ^ str[i]) * 0x01000193;
0125 return hash;
0126 }
0127
0128
0129
0130
0131 static int is_defined_config(const char *name, int len, unsigned int hash)
0132 {
0133 struct item *aux;
0134
0135 for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) {
0136 if (aux->hash == hash && aux->len == len &&
0137 memcmp(aux->name, name, len) == 0)
0138 return 1;
0139 }
0140 return 0;
0141 }
0142
0143
0144
0145
0146 static void define_config(const char *name, int len, unsigned int hash)
0147 {
0148 struct item *aux = malloc(sizeof(*aux) + len);
0149
0150 if (!aux) {
0151 perror("fixdep:malloc");
0152 exit(1);
0153 }
0154 memcpy(aux->name, name, len);
0155 aux->len = len;
0156 aux->hash = hash;
0157 aux->next = hashtab[hash % HASHSZ];
0158 hashtab[hash % HASHSZ] = aux;
0159 }
0160
0161
0162
0163
0164 static void use_config(const char *m, int slen)
0165 {
0166 unsigned int hash = strhash(m, slen);
0167
0168 if (is_defined_config(m, slen, hash))
0169 return;
0170
0171 define_config(m, slen, hash);
0172
0173 printf(" $(wildcard include/config/%.*s) \\\n", slen, m);
0174 }
0175
0176
0177 static int str_ends_with(const char *s, int slen, const char *sub)
0178 {
0179 int sublen = strlen(sub);
0180
0181 if (sublen > slen)
0182 return 0;
0183
0184 return !memcmp(s + slen - sublen, sub, sublen);
0185 }
0186
0187 static void parse_config_file(const char *p)
0188 {
0189 const char *q, *r;
0190 const char *start = p;
0191
0192 while ((p = strstr(p, "CONFIG_"))) {
0193 if (p > start && (isalnum(p[-1]) || p[-1] == '_')) {
0194 p += 7;
0195 continue;
0196 }
0197 p += 7;
0198 q = p;
0199 while (isalnum(*q) || *q == '_')
0200 q++;
0201 if (str_ends_with(p, q - p, "_MODULE"))
0202 r = q - 7;
0203 else
0204 r = q;
0205 if (r > p)
0206 use_config(p, r - p);
0207 p = q;
0208 }
0209 }
0210
0211 static void *read_file(const char *filename)
0212 {
0213 struct stat st;
0214 int fd;
0215 char *buf;
0216
0217 fd = open(filename, O_RDONLY);
0218 if (fd < 0) {
0219 fprintf(stderr, "fixdep: error opening file: ");
0220 perror(filename);
0221 exit(2);
0222 }
0223 if (fstat(fd, &st) < 0) {
0224 fprintf(stderr, "fixdep: error fstat'ing file: ");
0225 perror(filename);
0226 exit(2);
0227 }
0228 buf = malloc(st.st_size + 1);
0229 if (!buf) {
0230 perror("fixdep: malloc");
0231 exit(2);
0232 }
0233 if (read(fd, buf, st.st_size) != st.st_size) {
0234 perror("fixdep: read");
0235 exit(2);
0236 }
0237 buf[st.st_size] = '\0';
0238 close(fd);
0239
0240 return buf;
0241 }
0242
0243
0244 static int is_ignored_file(const char *s, int len)
0245 {
0246 return str_ends_with(s, len, "include/generated/autoconf.h") ||
0247 str_ends_with(s, len, "include/generated/autoksyms.h");
0248 }
0249
0250
0251
0252
0253
0254
0255 static void parse_dep_file(char *m, const char *target)
0256 {
0257 char *p;
0258 int is_last, is_target;
0259 int saw_any_target = 0;
0260 int is_first_dep = 0;
0261 void *buf;
0262
0263 while (1) {
0264
0265 while (*m == ' ' || *m == '\\' || *m == '\n')
0266 m++;
0267
0268 if (!*m)
0269 break;
0270
0271
0272 p = m;
0273 while (*p && *p != ' ' && *p != '\\' && *p != '\n')
0274 p++;
0275 is_last = (*p == '\0');
0276
0277 is_target = (*(p-1) == ':');
0278
0279 if (is_target) {
0280
0281 is_first_dep = 1;
0282 } else if (!is_ignored_file(m, p - m)) {
0283 *p = '\0';
0284
0285
0286
0287
0288
0289
0290
0291 if (is_first_dep) {
0292
0293
0294
0295
0296
0297
0298
0299
0300 if (!saw_any_target) {
0301 saw_any_target = 1;
0302 printf("source_%s := %s\n\n",
0303 target, m);
0304 printf("deps_%s := \\\n", target);
0305 }
0306 is_first_dep = 0;
0307 } else {
0308 printf(" %s \\\n", m);
0309 }
0310
0311 buf = read_file(m);
0312 parse_config_file(buf);
0313 free(buf);
0314 }
0315
0316 if (is_last)
0317 break;
0318
0319
0320
0321
0322
0323 m = p + 1;
0324 }
0325
0326 if (!saw_any_target) {
0327 fprintf(stderr, "fixdep: parse error; no targets found\n");
0328 exit(1);
0329 }
0330
0331 printf("\n%s: $(deps_%s)\n\n", target, target);
0332 printf("$(deps_%s):\n", target);
0333 }
0334
0335 int main(int argc, char *argv[])
0336 {
0337 const char *depfile, *target, *cmdline;
0338 void *buf;
0339
0340 if (argc != 4)
0341 usage();
0342
0343 depfile = argv[1];
0344 target = argv[2];
0345 cmdline = argv[3];
0346
0347 printf("cmd_%s := %s\n\n", target, cmdline);
0348
0349 buf = read_file(depfile);
0350 parse_dep_file(buf, target);
0351 free(buf);
0352
0353 fflush(stdout);
0354
0355
0356
0357
0358
0359 if (ferror(stdout)) {
0360 fprintf(stderr, "fixdep: not all data was written to the output\n");
0361 exit(1);
0362 }
0363
0364 return 0;
0365 }