18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * "Optimize" a list of dependencies as spit out by gcc -MD 38c2ecf20Sopenharmony_ci * for the kernel build 48c2ecf20Sopenharmony_ci * =========================================================================== 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author Kai Germaschewski 78c2ecf20Sopenharmony_ci * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This software may be used and distributed according to the terms 108c2ecf20Sopenharmony_ci * of the GNU General Public License, incorporated herein by reference. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Introduction: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * gcc produces a very nice and correct list of dependencies which 168c2ecf20Sopenharmony_ci * tells make when to remake a file. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * To use this list as-is however has the drawback that virtually 198c2ecf20Sopenharmony_ci * every file in the kernel includes autoconf.h. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * If the user re-runs make *config, autoconf.h will be 228c2ecf20Sopenharmony_ci * regenerated. make notices that and will rebuild every file which 238c2ecf20Sopenharmony_ci * includes autoconf.h, i.e. basically all files. This is extremely 248c2ecf20Sopenharmony_ci * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * So we play the same trick that "mkdep" played before. We replace 278c2ecf20Sopenharmony_ci * the dependency on autoconf.h by a dependency on every config 288c2ecf20Sopenharmony_ci * option which is mentioned in any of the listed prerequisites. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * kconfig populates a tree in include/config/ with an empty file 318c2ecf20Sopenharmony_ci * for each config symbol and when the configuration is updated 328c2ecf20Sopenharmony_ci * the files representing changed config options are touched 338c2ecf20Sopenharmony_ci * which then let make pick up the changes and the files that use 348c2ecf20Sopenharmony_ci * the config symbols are rebuilt. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * So if the user changes his CONFIG_HIS_DRIVER option, only the objects 378c2ecf20Sopenharmony_ci * which depend on "include/config/his/driver.h" will be rebuilt, 388c2ecf20Sopenharmony_ci * so most likely only his driver ;-) 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * The idea above dates, by the way, back to Michael E Chastain, AFAIK. 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * So to get dependencies right, there are two issues: 438c2ecf20Sopenharmony_ci * o if any of the files the compiler read changed, we need to rebuild 448c2ecf20Sopenharmony_ci * o if the command line given to the compile the file changed, we 458c2ecf20Sopenharmony_ci * better rebuild as well. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * The former is handled by using the -MD output, the later by saving 488c2ecf20Sopenharmony_ci * the command line used to compile the old object and comparing it 498c2ecf20Sopenharmony_ci * to the one we would now use. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * Again, also this idea is pretty old and has been discussed on 528c2ecf20Sopenharmony_ci * kbuild-devel a long time ago. I don't have a sensibly working 538c2ecf20Sopenharmony_ci * internet connection right now, so I rather don't mention names 548c2ecf20Sopenharmony_ci * without double checking. 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * This code here has been based partially based on mkdep.c, which 578c2ecf20Sopenharmony_ci * says the following about its history: 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>. 608c2ecf20Sopenharmony_ci * This is a C version of syncdep.pl by Werner Almesberger. 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * It is invoked as 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * fixdep <depfile> <target> <cmdline> 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * and will read the dependency file <depfile> 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * The transformed dependency snipped is written to stdout. 708c2ecf20Sopenharmony_ci * 718c2ecf20Sopenharmony_ci * It first generates a line 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * cmd_<target> = <cmdline> 748c2ecf20Sopenharmony_ci * 758c2ecf20Sopenharmony_ci * and then basically copies the .<target>.d file to stdout, in the 768c2ecf20Sopenharmony_ci * process filtering out the dependency on autoconf.h and adding 778c2ecf20Sopenharmony_ci * dependencies on include/config/my/option.h for every 788c2ecf20Sopenharmony_ci * CONFIG_MY_OPTION encountered in any of the prerequisites. 798c2ecf20Sopenharmony_ci * 808c2ecf20Sopenharmony_ci * We don't even try to really parse the header files, but 818c2ecf20Sopenharmony_ci * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will 828c2ecf20Sopenharmony_ci * be picked up as well. It's not a problem with respect to 838c2ecf20Sopenharmony_ci * correctness, since that can only give too many dependencies, thus 848c2ecf20Sopenharmony_ci * we cannot miss a rebuild. Since people tend to not mention totally 858c2ecf20Sopenharmony_ci * unrelated CONFIG_ options all over the place, it's not an 868c2ecf20Sopenharmony_ci * efficiency problem either. 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * (Note: it'd be easy to port over the complete mkdep state machine, 898c2ecf20Sopenharmony_ci * but I don't think the added complexity is worth it) 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#include <sys/types.h> 938c2ecf20Sopenharmony_ci#include <sys/stat.h> 948c2ecf20Sopenharmony_ci#include <unistd.h> 958c2ecf20Sopenharmony_ci#include <fcntl.h> 968c2ecf20Sopenharmony_ci#include <string.h> 978c2ecf20Sopenharmony_ci#include <stdarg.h> 988c2ecf20Sopenharmony_ci#include <stdlib.h> 998c2ecf20Sopenharmony_ci#include <stdio.h> 1008c2ecf20Sopenharmony_ci#include <ctype.h> 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic void usage(void) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n"); 1058c2ecf20Sopenharmony_ci exit(1); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci * In the intended usage of this program, the stdout is redirected to .*.cmd 1108c2ecf20Sopenharmony_ci * files. The return value of printf() and putchar() must be checked to catch 1118c2ecf20Sopenharmony_ci * any error, e.g. "No space left on device". 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_cistatic void xprintf(const char *format, ...) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci va_list ap; 1168c2ecf20Sopenharmony_ci int ret; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci va_start(ap, format); 1198c2ecf20Sopenharmony_ci ret = vprintf(format, ap); 1208c2ecf20Sopenharmony_ci if (ret < 0) { 1218c2ecf20Sopenharmony_ci perror("fixdep"); 1228c2ecf20Sopenharmony_ci exit(1); 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci va_end(ap); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic void xputchar(int c) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci int ret; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci ret = putchar(c); 1328c2ecf20Sopenharmony_ci if (ret == EOF) { 1338c2ecf20Sopenharmony_ci perror("fixdep"); 1348c2ecf20Sopenharmony_ci exit(1); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* 1398c2ecf20Sopenharmony_ci * Print out a dependency path from a symbol name 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_cistatic void print_dep(const char *m, int slen, const char *dir) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci int c, prev_c = '/', i; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci xprintf(" $(wildcard %s/", dir); 1468c2ecf20Sopenharmony_ci for (i = 0; i < slen; i++) { 1478c2ecf20Sopenharmony_ci c = m[i]; 1488c2ecf20Sopenharmony_ci if (c == '_') 1498c2ecf20Sopenharmony_ci c = '/'; 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci c = tolower(c); 1528c2ecf20Sopenharmony_ci if (c != '/' || prev_c != '/') 1538c2ecf20Sopenharmony_ci xputchar(c); 1548c2ecf20Sopenharmony_ci prev_c = c; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci xprintf(".h) \\\n"); 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistruct item { 1608c2ecf20Sopenharmony_ci struct item *next; 1618c2ecf20Sopenharmony_ci unsigned int len; 1628c2ecf20Sopenharmony_ci unsigned int hash; 1638c2ecf20Sopenharmony_ci char name[]; 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci#define HASHSZ 256 1678c2ecf20Sopenharmony_cistatic struct item *hashtab[HASHSZ]; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic unsigned int strhash(const char *str, unsigned int sz) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci /* fnv32 hash */ 1728c2ecf20Sopenharmony_ci unsigned int i, hash = 2166136261U; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci for (i = 0; i < sz; i++) 1758c2ecf20Sopenharmony_ci hash = (hash ^ str[i]) * 0x01000193; 1768c2ecf20Sopenharmony_ci return hash; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/* 1808c2ecf20Sopenharmony_ci * Lookup a value in the configuration string. 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_cistatic int is_defined_config(const char *name, int len, unsigned int hash) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct item *aux; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) { 1878c2ecf20Sopenharmony_ci if (aux->hash == hash && aux->len == len && 1888c2ecf20Sopenharmony_ci memcmp(aux->name, name, len) == 0) 1898c2ecf20Sopenharmony_ci return 1; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci/* 1958c2ecf20Sopenharmony_ci * Add a new value to the configuration string. 1968c2ecf20Sopenharmony_ci */ 1978c2ecf20Sopenharmony_cistatic void define_config(const char *name, int len, unsigned int hash) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci struct item *aux = malloc(sizeof(*aux) + len); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (!aux) { 2028c2ecf20Sopenharmony_ci perror("fixdep:malloc"); 2038c2ecf20Sopenharmony_ci exit(1); 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci memcpy(aux->name, name, len); 2068c2ecf20Sopenharmony_ci aux->len = len; 2078c2ecf20Sopenharmony_ci aux->hash = hash; 2088c2ecf20Sopenharmony_ci aux->next = hashtab[hash % HASHSZ]; 2098c2ecf20Sopenharmony_ci hashtab[hash % HASHSZ] = aux; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* 2138c2ecf20Sopenharmony_ci * Record the use of a CONFIG_* word. 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_cistatic void use_config(const char *m, int slen) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci unsigned int hash = strhash(m, slen); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (is_defined_config(m, slen, hash)) 2208c2ecf20Sopenharmony_ci return; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci define_config(m, slen, hash); 2238c2ecf20Sopenharmony_ci print_dep(m, slen, "include/config"); 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci/* test if s ends in sub */ 2278c2ecf20Sopenharmony_cistatic int str_ends_with(const char *s, int slen, const char *sub) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci int sublen = strlen(sub); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (sublen > slen) 2328c2ecf20Sopenharmony_ci return 0; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci return !memcmp(s + slen - sublen, sub, sublen); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic void parse_config_file(const char *p) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci const char *q, *r; 2408c2ecf20Sopenharmony_ci const char *start = p; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci while ((p = strstr(p, "CONFIG_"))) { 2438c2ecf20Sopenharmony_ci if (p > start && (isalnum(p[-1]) || p[-1] == '_')) { 2448c2ecf20Sopenharmony_ci p += 7; 2458c2ecf20Sopenharmony_ci continue; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci p += 7; 2488c2ecf20Sopenharmony_ci q = p; 2498c2ecf20Sopenharmony_ci while (isalnum(*q) || *q == '_') 2508c2ecf20Sopenharmony_ci q++; 2518c2ecf20Sopenharmony_ci if (str_ends_with(p, q - p, "_MODULE")) 2528c2ecf20Sopenharmony_ci r = q - 7; 2538c2ecf20Sopenharmony_ci else 2548c2ecf20Sopenharmony_ci r = q; 2558c2ecf20Sopenharmony_ci if (r > p) 2568c2ecf20Sopenharmony_ci use_config(p, r - p); 2578c2ecf20Sopenharmony_ci p = q; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic void *read_file(const char *filename) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct stat st; 2648c2ecf20Sopenharmony_ci int fd; 2658c2ecf20Sopenharmony_ci char *buf; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci fd = open(filename, O_RDONLY); 2688c2ecf20Sopenharmony_ci if (fd < 0) { 2698c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: error opening file: "); 2708c2ecf20Sopenharmony_ci perror(filename); 2718c2ecf20Sopenharmony_ci exit(2); 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci if (fstat(fd, &st) < 0) { 2748c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: error fstat'ing file: "); 2758c2ecf20Sopenharmony_ci perror(filename); 2768c2ecf20Sopenharmony_ci exit(2); 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci buf = malloc(st.st_size + 1); 2798c2ecf20Sopenharmony_ci if (!buf) { 2808c2ecf20Sopenharmony_ci perror("fixdep: malloc"); 2818c2ecf20Sopenharmony_ci exit(2); 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci if (read(fd, buf, st.st_size) != st.st_size) { 2848c2ecf20Sopenharmony_ci perror("fixdep: read"); 2858c2ecf20Sopenharmony_ci exit(2); 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci buf[st.st_size] = '\0'; 2888c2ecf20Sopenharmony_ci close(fd); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return buf; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* Ignore certain dependencies */ 2948c2ecf20Sopenharmony_cistatic int is_ignored_file(const char *s, int len) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci return str_ends_with(s, len, "include/generated/autoconf.h") || 2978c2ecf20Sopenharmony_ci str_ends_with(s, len, "include/generated/autoksyms.h"); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci/* 3018c2ecf20Sopenharmony_ci * Important: The below generated source_foo.o and deps_foo.o variable 3028c2ecf20Sopenharmony_ci * assignments are parsed not only by make, but also by the rather simple 3038c2ecf20Sopenharmony_ci * parser in scripts/mod/sumversion.c. 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_cistatic void parse_dep_file(char *m, const char *target) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci char *p; 3088c2ecf20Sopenharmony_ci int is_last, is_target; 3098c2ecf20Sopenharmony_ci int saw_any_target = 0; 3108c2ecf20Sopenharmony_ci int is_first_dep = 0; 3118c2ecf20Sopenharmony_ci void *buf; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci while (1) { 3148c2ecf20Sopenharmony_ci /* Skip any "white space" */ 3158c2ecf20Sopenharmony_ci while (*m == ' ' || *m == '\\' || *m == '\n') 3168c2ecf20Sopenharmony_ci m++; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (!*m) 3198c2ecf20Sopenharmony_ci break; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Find next "white space" */ 3228c2ecf20Sopenharmony_ci p = m; 3238c2ecf20Sopenharmony_ci while (*p && *p != ' ' && *p != '\\' && *p != '\n') 3248c2ecf20Sopenharmony_ci p++; 3258c2ecf20Sopenharmony_ci is_last = (*p == '\0'); 3268c2ecf20Sopenharmony_ci /* Is the token we found a target name? */ 3278c2ecf20Sopenharmony_ci is_target = (*(p-1) == ':'); 3288c2ecf20Sopenharmony_ci /* Don't write any target names into the dependency file */ 3298c2ecf20Sopenharmony_ci if (is_target) { 3308c2ecf20Sopenharmony_ci /* The /next/ file is the first dependency */ 3318c2ecf20Sopenharmony_ci is_first_dep = 1; 3328c2ecf20Sopenharmony_ci } else if (!is_ignored_file(m, p - m)) { 3338c2ecf20Sopenharmony_ci *p = '\0'; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* 3368c2ecf20Sopenharmony_ci * Do not list the source file as dependency, so that 3378c2ecf20Sopenharmony_ci * kbuild is not confused if a .c file is rewritten 3388c2ecf20Sopenharmony_ci * into .S or vice versa. Storing it in source_* is 3398c2ecf20Sopenharmony_ci * needed for modpost to compute srcversions. 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_ci if (is_first_dep) { 3428c2ecf20Sopenharmony_ci /* 3438c2ecf20Sopenharmony_ci * If processing the concatenation of multiple 3448c2ecf20Sopenharmony_ci * dependency files, only process the first 3458c2ecf20Sopenharmony_ci * target name, which will be the original 3468c2ecf20Sopenharmony_ci * source name, and ignore any other target 3478c2ecf20Sopenharmony_ci * names, which will be intermediate temporary 3488c2ecf20Sopenharmony_ci * files. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci if (!saw_any_target) { 3518c2ecf20Sopenharmony_ci saw_any_target = 1; 3528c2ecf20Sopenharmony_ci xprintf("source_%s := %s\n\n", 3538c2ecf20Sopenharmony_ci target, m); 3548c2ecf20Sopenharmony_ci xprintf("deps_%s := \\\n", target); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci is_first_dep = 0; 3578c2ecf20Sopenharmony_ci } else { 3588c2ecf20Sopenharmony_ci xprintf(" %s \\\n", m); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci buf = read_file(m); 3628c2ecf20Sopenharmony_ci parse_config_file(buf); 3638c2ecf20Sopenharmony_ci free(buf); 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (is_last) 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* 3708c2ecf20Sopenharmony_ci * Start searching for next token immediately after the first 3718c2ecf20Sopenharmony_ci * "whitespace" character that follows this token. 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_ci m = p + 1; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (!saw_any_target) { 3778c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: parse error; no targets found\n"); 3788c2ecf20Sopenharmony_ci exit(1); 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci xprintf("\n%s: $(deps_%s)\n\n", target, target); 3828c2ecf20Sopenharmony_ci xprintf("$(deps_%s):\n", target); 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci const char *depfile, *target, *cmdline; 3888c2ecf20Sopenharmony_ci void *buf; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (argc != 4) 3918c2ecf20Sopenharmony_ci usage(); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci depfile = argv[1]; 3948c2ecf20Sopenharmony_ci target = argv[2]; 3958c2ecf20Sopenharmony_ci cmdline = argv[3]; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci xprintf("cmd_%s := %s\n\n", target, cmdline); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci buf = read_file(depfile); 4008c2ecf20Sopenharmony_ci parse_dep_file(buf, target); 4018c2ecf20Sopenharmony_ci free(buf); 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci return 0; 4048c2ecf20Sopenharmony_ci} 405