aboutsummaryrefslogtreecommitdiff
path: root/scripts/basic
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/basic')
-rw-r--r--scripts/basic/Makefile18
-rw-r--r--scripts/basic/docproc.c398
-rw-r--r--scripts/basic/fixdep.c393
-rw-r--r--scripts/basic/split-include.c226
4 files changed, 1035 insertions, 0 deletions
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
new file mode 100644
index 000000000..f22e94c3a
--- /dev/null
+++ b/scripts/basic/Makefile
@@ -0,0 +1,18 @@
1###
2# Makefile.basic list the most basic programs used during the build process.
3# The programs listed herein is what is needed to do the basic stuff,
4# such as splitting .config and fix dependency file.
5# This initial step is needed to avoid files to be recompiled
6# when kernel configuration changes (which is what happens when
7# .config is included by main Makefile.
8# ---------------------------------------------------------------------------
9# fixdep: Used to generate dependency information during build process
10# split-include: Divide all config symbols up in a number of files in
11# include/config/...
12# docproc: Used in Documentation/docbook
13
14hostprogs-y := fixdep split-include docproc
15always := $(hostprogs-y)
16
17# fixdep is needed to compile other host programs
18$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
new file mode 100644
index 000000000..cb02baa63
--- /dev/null
+++ b/scripts/basic/docproc.c
@@ -0,0 +1,398 @@
1/*
2 * docproc is a simple preprocessor for the template files
3 * used as placeholders for the kernel internal documentation.
4 * docproc is used for documentation-frontend and
5 * dependency-generator.
6 * The two usages have in common that they require
7 * some knowledge of the .tmpl syntax, therefore they
8 * are kept together.
9 *
10 * documentation-frontend
11 * Scans the template file and call kernel-doc for
12 * all occurrences of ![EIF]file
13 * Beforehand each referenced file are scanned for
14 * any exported sympols "EXPORT_SYMBOL()" statements.
15 * This is used to create proper -function and
16 * -nofunction arguments in calls to kernel-doc.
17 * Usage: docproc doc file.tmpl
18 *
19 * dependency-generator:
20 * Scans the template file and list all files
21 * referenced in a format recognized by make.
22 * Usage: docproc depend file.tmpl
23 * Writes dependency information to stdout
24 * in the following format:
25 * file.tmpl src.c src2.c
26 * The filenames are obtained from the following constructs:
27 * !Efilename
28 * !Ifilename
29 * !Dfilename
30 * !Ffilename
31 *
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <ctype.h>
38#include <unistd.h>
39#include <limits.h>
40#include <sys/types.h>
41#include <sys/wait.h>
42
43/* exitstatus is used to keep track of any failing calls to kernel-doc,
44 * but execution continues. */
45int exitstatus = 0;
46
47typedef void DFL(char *);
48DFL *defaultline;
49
50typedef void FILEONLY(char * file);
51FILEONLY *internalfunctions;
52FILEONLY *externalfunctions;
53FILEONLY *symbolsonly;
54
55typedef void FILELINE(char * file, char * line);
56FILELINE * singlefunctions;
57FILELINE * entity_system;
58
59#define MAXLINESZ 2048
60#define MAXFILES 250
61#define KERNELDOCPATH "scripts/"
62#define KERNELDOC "kernel-doc"
63#define DOCBOOK "-docbook"
64#define FUNCTION "-function"
65#define NOFUNCTION "-nofunction"
66
67void usage (void)
68{
69 fprintf(stderr, "Usage: docproc {doc|depend} file\n");
70 fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
71 fprintf(stderr, "doc: frontend when generating kernel documentation\n");
72 fprintf(stderr, "depend: generate list of files referenced within file\n");
73}
74
75/*
76 * Execute kernel-doc with parameters givin in svec
77 */
78void exec_kernel_doc(char **svec)
79{
80 pid_t pid;
81 int ret;
82 char real_filename[PATH_MAX + 1];
83 /* Make sure output generated so far are flushed */
84 fflush(stdout);
85 switch(pid=fork()) {
86 case -1:
87 perror("fork");
88 exit(1);
89 case 0:
90 memset(real_filename, 0, sizeof(real_filename));
91 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
92 strncat(real_filename, KERNELDOCPATH KERNELDOC,
93 PATH_MAX - strlen(real_filename));
94 execvp(real_filename, svec);
95 fprintf(stderr, "exec ");
96 perror(real_filename);
97 exit(1);
98 default:
99 waitpid(pid, &ret ,0);
100 }
101 if (WIFEXITED(ret))
102 exitstatus |= WEXITSTATUS(ret);
103 else
104 exitstatus = 0xff;
105}
106
107/* Types used to create list of all exported symbols in a number of files */
108struct symbols
109{
110 char *name;
111};
112
113struct symfile
114{
115 char *filename;
116 struct symbols *symbollist;
117 int symbolcnt;
118};
119
120struct symfile symfilelist[MAXFILES];
121int symfilecnt = 0;
122
123void add_new_symbol(struct symfile *sym, char * symname)
124{
125 sym->symbollist =
126 realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
127 sym->symbollist[sym->symbolcnt++].name = strdup(symname);
128}
129
130/* Add a filename to the list */
131struct symfile * add_new_file(char * filename)
132{
133 symfilelist[symfilecnt++].filename = strdup(filename);
134 return &symfilelist[symfilecnt - 1];
135}
136/* Check if file already are present in the list */
137struct symfile * filename_exist(char * filename)
138{
139 int i;
140 for (i=0; i < symfilecnt; i++)
141 if (strcmp(symfilelist[i].filename, filename) == 0)
142 return &symfilelist[i];
143 return NULL;
144}
145
146/*
147 * List all files referenced within the template file.
148 * Files are separated by tabs.
149 */
150void adddep(char * file) { printf("\t%s", file); }
151void adddep2(char * file, char * line) { line = line; adddep(file); }
152void noaction(char * line) { line = line; }
153void noaction2(char * file, char * line) { file = file; line = line; }
154
155/* Echo the line without further action */
156void printline(char * line) { printf("%s", line); }
157
158/*
159 * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
160 * in filename.
161 * All symbols located are stored in symfilelist.
162 */
163void find_export_symbols(char * filename)
164{
165 FILE * fp;
166 struct symfile *sym;
167 char line[MAXLINESZ];
168 if (filename_exist(filename) == NULL) {
169 char real_filename[PATH_MAX + 1];
170 memset(real_filename, 0, sizeof(real_filename));
171 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
172 strncat(real_filename, filename,
173 PATH_MAX - strlen(real_filename));
174 sym = add_new_file(filename);
175 fp = fopen(real_filename, "r");
176 if (fp == NULL)
177 {
178 fprintf(stderr, "docproc: ");
179 perror(real_filename);
180 }
181 while(fgets(line, MAXLINESZ, fp)) {
182 char *p;
183 char *e;
184 if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
185 ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
186 /* Skip EXPORT_SYMBOL{_GPL} */
187 while (isalnum(*p) || *p == '_')
188 p++;
189 /* Remove paranteses and additional ws */
190 while (isspace(*p))
191 p++;
192 if (*p != '(')
193 continue; /* Syntax error? */
194 else
195 p++;
196 while (isspace(*p))
197 p++;
198 e = p;
199 while (isalnum(*e) || *e == '_')
200 e++;
201 *e = '\0';
202 add_new_symbol(sym, p);
203 }
204 }
205 fclose(fp);
206 }
207}
208
209/*
210 * Document all external or internal functions in a file.
211 * Call kernel-doc with following parameters:
212 * kernel-doc -docbook -nofunction function_name1 filename
213 * function names are obtained from all the the src files
214 * by find_export_symbols.
215 * intfunc uses -nofunction
216 * extfunc uses -function
217 */
218void docfunctions(char * filename, char * type)
219{
220 int i,j;
221 int symcnt = 0;
222 int idx = 0;
223 char **vec;
224
225 for (i=0; i <= symfilecnt; i++)
226 symcnt += symfilelist[i].symbolcnt;
227 vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
228 if (vec == NULL) {
229 perror("docproc: ");
230 exit(1);
231 }
232 vec[idx++] = KERNELDOC;
233 vec[idx++] = DOCBOOK;
234 for (i=0; i < symfilecnt; i++) {
235 struct symfile * sym = &symfilelist[i];
236 for (j=0; j < sym->symbolcnt; j++) {
237 vec[idx++] = type;
238 vec[idx++] = sym->symbollist[j].name;
239 }
240 }
241 vec[idx++] = filename;
242 vec[idx] = NULL;
243 printf("<!-- %s -->\n", filename);
244 exec_kernel_doc(vec);
245 fflush(stdout);
246 free(vec);
247}
248void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
249void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
250
251/*
252 * Document spåecific function(s) in a file.
253 * Call kernel-doc with the following parameters:
254 * kernel-doc -docbook -function function1 [-function function2]
255 */
256void singfunc(char * filename, char * line)
257{
258 char *vec[200]; /* Enough for specific functions */
259 int i, idx = 0;
260 int startofsym = 1;
261 vec[idx++] = KERNELDOC;
262 vec[idx++] = DOCBOOK;
263
264 /* Split line up in individual parameters preceeded by FUNCTION */
265 for (i=0; line[i]; i++) {
266 if (isspace(line[i])) {
267 line[i] = '\0';
268 startofsym = 1;
269 continue;
270 }
271 if (startofsym) {
272 startofsym = 0;
273 vec[idx++] = FUNCTION;
274 vec[idx++] = &line[i];
275 }
276 }
277 vec[idx++] = filename;
278 vec[idx] = NULL;
279 exec_kernel_doc(vec);
280}
281
282/*
283 * Parse file, calling action specific functions for:
284 * 1) Lines containing !E
285 * 2) Lines containing !I
286 * 3) Lines containing !D
287 * 4) Lines containing !F
288 * 5) Default lines - lines not matching the above
289 */
290void parse_file(FILE *infile)
291{
292 char line[MAXLINESZ];
293 char * s;
294 while(fgets(line, MAXLINESZ, infile)) {
295 if (line[0] == '!') {
296 s = line + 2;
297 switch (line[1]) {
298 case 'E':
299 while (*s && !isspace(*s)) s++;
300 *s = '\0';
301 externalfunctions(line+2);
302 break;
303 case 'I':
304 while (*s && !isspace(*s)) s++;
305 *s = '\0';
306 internalfunctions(line+2);
307 break;
308 case 'D':
309 while (*s && !isspace(*s)) s++;
310 *s = '\0';
311 symbolsonly(line+2);
312 break;
313 case 'F':
314 /* filename */
315 while (*s && !isspace(*s)) s++;
316 *s++ = '\0';
317 /* function names */
318 while (isspace(*s))
319 s++;
320 singlefunctions(line +2, s);
321 break;
322 default:
323 defaultline(line);
324 }
325 }
326 else {
327 defaultline(line);
328 }
329 }
330 fflush(stdout);
331}
332
333
334int main(int argc, char *argv[])
335{
336 FILE * infile;
337 if (argc != 3) {
338 usage();
339 exit(1);
340 }
341 /* Open file, exit on error */
342 infile = fopen(argv[2], "r");
343 if (infile == NULL) {
344 fprintf(stderr, "docproc: ");
345 perror(argv[2]);
346 exit(2);
347 }
348
349 if (strcmp("doc", argv[1]) == 0)
350 {
351 /* Need to do this in two passes.
352 * First pass is used to collect all symbols exported
353 * in the various files.
354 * Second pass generate the documentation.
355 * This is required because function are declared
356 * and exported in different files :-((
357 */
358 /* Collect symbols */
359 defaultline = noaction;
360 internalfunctions = find_export_symbols;
361 externalfunctions = find_export_symbols;
362 symbolsonly = find_export_symbols;
363 singlefunctions = noaction2;
364 parse_file(infile);
365
366 /* Rewind to start from beginning of file again */
367 fseek(infile, 0, SEEK_SET);
368 defaultline = printline;
369 internalfunctions = intfunc;
370 externalfunctions = extfunc;
371 symbolsonly = printline;
372 singlefunctions = singfunc;
373
374 parse_file(infile);
375 }
376 else if (strcmp("depend", argv[1]) == 0)
377 {
378 /* Create first part of dependency chain
379 * file.tmpl */
380 printf("%s\t", argv[2]);
381 defaultline = noaction;
382 internalfunctions = adddep;
383 externalfunctions = adddep;
384 symbolsonly = adddep;
385 singlefunctions = adddep2;
386 parse_file(infile);
387 printf("\n");
388 }
389 else
390 {
391 fprintf(stderr, "Unknown option: %s\n", argv[1]);
392 exit(1);
393 }
394 fclose(infile);
395 fflush(stdout);
396 return exitstatus;
397}
398
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
new file mode 100644
index 000000000..cc2c6541b
--- /dev/null
+++ b/scripts/basic/fixdep.c
@@ -0,0 +1,393 @@
1/*
2 * "Optimize" a list of dependencies as spit out by gcc -MD
3 * for the kernel build
4 * ===========================================================================
5 *
6 * Author Kai Germaschewski
7 * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 *
13 * Introduction:
14 *
15 * gcc produces a very nice and correct list of dependencies which
16 * tells make when to remake a file.
17 *
18 * To use this list as-is however has the drawback that virtually
19 * every file in the kernel includes <linux/config.h> which then again
20 * includes <linux/autoconf.h>
21 *
22 * If the user re-runs make *config, linux/autoconf.h will be
23 * regenerated. make notices that and will rebuild every file which
24 * includes autoconf.h, i.e. basically all files. This is extremely
25 * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
26 *
27 * So we play the same trick that "mkdep" played before. We replace
28 * the dependency on linux/autoconf.h by a dependency on every config
29 * option which is mentioned in any of the listed prequisites.
30 *
31 * To be exact, split-include populates a tree in include/config/,
32 * e.g. include/config/his/driver.h, which contains the #define/#undef
33 * for the CONFIG_HIS_DRIVER option.
34 *
35 * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
36 * which depend on "include/linux/config/his/driver.h" will be rebuilt,
37 * so most likely only his driver ;-)
38 *
39 * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
40 *
41 * So to get dependencies right, there are two issues:
42 * o if any of the files the compiler read changed, we need to rebuild
43 * o if the command line given to the compile the file changed, we
44 * better rebuild as well.
45 *
46 * The former is handled by using the -MD output, the later by saving
47 * the command line used to compile the old object and comparing it
48 * to the one we would now use.
49 *
50 * Again, also this idea is pretty old and has been discussed on
51 * kbuild-devel a long time ago. I don't have a sensibly working
52 * internet connection right now, so I rather don't mention names
53 * without double checking.
54 *
55 * This code here has been based partially based on mkdep.c, which
56 * says the following about its history:
57 *
58 * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
59 * This is a C version of syncdep.pl by Werner Almesberger.
60 *
61 *
62 * It is invoked as
63 *
64 * fixdep <depfile> <target> <cmdline>
65 *
66 * and will read the dependency file <depfile>
67 *
68 * The transformed dependency snipped is written to stdout.
69 *
70 * It first generates a line
71 *
72 * cmd_<target> = <cmdline>
73 *
74 * and then basically copies the .<target>.d file to stdout, in the
75 * process filtering out the dependency on linux/autoconf.h and adding
76 * dependencies on include/config/my/option.h for every
77 * CONFIG_MY_OPTION encountered in any of the prequisites.
78 *
79 * It will also filter out all the dependencies on *.ver. We need
80 * to make sure that the generated version checksum are globally up
81 * to date before even starting the recursive build, so it's too late
82 * at this point anyway.
83 *
84 * The algorithm to grep for "CONFIG_..." is bit unusual, but should
85 * be fast ;-) We don't even try to really parse the header files, but
86 * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
87 * be picked up as well. It's not a problem with respect to
88 * correctness, since that can only give too many dependencies, thus
89 * we cannot miss a rebuild. Since people tend to not mention totally
90 * unrelated CONFIG_ options all over the place, it's not an
91 * efficiency problem either.
92 *
93 * (Note: it'd be easy to port over the complete mkdep state machine,
94 * but I don't think the added complexity is worth it)
95 */
96/*
97 * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
98 * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
99 * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
100 * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
101 * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
102 * those files will have correct dependencies.
103 */
104
105#include <sys/types.h>
106#include <sys/stat.h>
107#include <sys/mman.h>
108#include <unistd.h>
109#include <fcntl.h>
110#include <string.h>
111#include <stdlib.h>
112#include <stdio.h>
113#include <limits.h>
114#include <ctype.h>
115#include <arpa/inet.h>
116
117#define INT_CONF ntohl(0x434f4e46)
118#define INT_ONFI ntohl(0x4f4e4649)
119#define INT_NFIG ntohl(0x4e464947)
120#define INT_FIG_ ntohl(0x4649475f)
121
122char *target;
123char *depfile;
124char *cmdline;
125
126void usage(void)
127
128{
129 fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
130 exit(1);
131}
132
133/*
134 * Print out the commandline prefixed with cmd_<target filename> :=
135 */
136void print_cmdline(void)
137{
138 printf("cmd_%s := %s\n\n", target, cmdline);
139}
140
141char * str_config = NULL;
142int size_config = 0;
143int len_config = 0;
144
145/*
146 * Grow the configuration string to a desired length.
147 * Usually the first growth is plenty.
148 */
149void grow_config(int len)
150{
151 while (len_config + len > size_config) {
152 if (size_config == 0)
153 size_config = 2048;
154 str_config = realloc(str_config, size_config *= 2);
155 if (str_config == NULL)
156 { perror("fixdep:malloc"); exit(1); }
157 }
158}
159
160
161
162/*
163 * Lookup a value in the configuration string.
164 */
165int is_defined_config(const char * name, int len)
166{
167 const char * pconfig;
168 const char * plast = str_config + len_config - len;
169 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
170 if (pconfig[ -1] == '\n'
171 && pconfig[len] == '\n'
172 && !memcmp(pconfig, name, len))
173 return 1;
174 }
175 return 0;
176}
177
178/*
179 * Add a new value to the configuration string.
180 */
181void define_config(const char * name, int len)
182{
183 grow_config(len + 1);
184
185 memcpy(str_config+len_config, name, len);
186 len_config += len;
187 str_config[len_config++] = '\n';
188}
189
190/*
191 * Clear the set of configuration strings.
192 */
193void clear_config(void)
194{
195 len_config = 0;
196 define_config("", 0);
197}
198
199/*
200 * Record the use of a CONFIG_* word.
201 */
202void use_config(char *m, int slen)
203{
204 char s[PATH_MAX];
205 char *p;
206
207 if (is_defined_config(m, slen))
208 return;
209
210 define_config(m, slen);
211
212 memcpy(s, m, slen); s[slen] = 0;
213
214 for (p = s; p < s + slen; p++) {
215 if (*p == '_')
216 *p = '/';
217 else
218 *p = tolower((int)*p);
219 }
220 printf(" $(wildcard include/config/%s.h) \\\n", s);
221}
222
223void parse_config_file(char *map, size_t len)
224{
225 int *end = (int *) (map + len);
226 /* start at +1, so that p can never be < map */
227 int *m = (int *) map + 1;
228 char *p, *q;
229
230 for (; m < end; m++) {
231 if (*m == INT_CONF) { p = (char *) m ; goto conf; }
232 if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
233 if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
234 if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
235 continue;
236 conf:
237 if (p > map + len - 7)
238 continue;
239 if (memcmp(p, "CONFIG_", 7))
240 continue;
241 for (q = p + 7; q < map + len; q++) {
242 if (!(isalnum(*q) || *q == '_'))
243 goto found;
244 }
245 continue;
246
247 found:
248 use_config(p+7, q-p-7);
249 }
250}
251
252/* test is s ends in sub */
253int strrcmp(char *s, char *sub)
254{
255 int slen = strlen(s);
256 int sublen = strlen(sub);
257
258 if (sublen > slen)
259 return 1;
260
261 return memcmp(s + slen - sublen, sub, sublen);
262}
263
264void do_config_file(char *filename)
265{
266 struct stat st;
267 int fd;
268 void *map;
269
270 fd = open(filename, O_RDONLY);
271 if (fd < 0) {
272 fprintf(stderr, "fixdep: ");
273 perror(filename);
274 exit(2);
275 }
276 fstat(fd, &st);
277 if (st.st_size == 0) {
278 close(fd);
279 return;
280 }
281 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
282 if ((long) map == -1) {
283 perror("fixdep: mmap");
284 close(fd);
285 return;
286 }
287
288 parse_config_file(map, st.st_size);
289
290 munmap(map, st.st_size);
291
292 close(fd);
293}
294
295void parse_dep_file(void *map, size_t len)
296{
297 char *m = map;
298 char *end = m + len;
299 char *p;
300 char s[PATH_MAX];
301
302 p = strchr(m, ':');
303 if (!p) {
304 fprintf(stderr, "fixdep: parse error\n");
305 exit(1);
306 }
307 memcpy(s, m, p-m); s[p-m] = 0;
308 printf("deps_%s := \\\n", target);
309 m = p+1;
310
311 clear_config();
312
313 while (m < end) {
314 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
315 m++;
316 p = m;
317 while (p < end && *p != ' ') p++;
318 if (p == end) {
319 do p--; while (!isalnum(*p));
320 p++;
321 }
322 memcpy(s, m, p-m); s[p-m] = 0;
323 if (strrcmp(s, "include/autoconf.h") &&
324 strrcmp(s, "arch/um/include/uml-config.h") &&
325 strrcmp(s, ".ver")) {
326 printf(" %s \\\n", s);
327 do_config_file(s);
328 }
329 m = p + 1;
330 }
331 printf("\n%s: $(deps_%s)\n\n", target, target);
332 printf("$(deps_%s):\n", target);
333}
334
335void print_deps(void)
336{
337 struct stat st;
338 int fd;
339 void *map;
340
341 fd = open(depfile, O_RDONLY);
342 if (fd < 0) {
343 fprintf(stderr, "fixdep: ");
344 perror(depfile);
345 exit(2);
346 }
347 fstat(fd, &st);
348 if (st.st_size == 0) {
349 fprintf(stderr,"fixdep: %s is empty\n",depfile);
350 close(fd);
351 return;
352 }
353 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
354 if ((long) map == -1) {
355 perror("fixdep: mmap");
356 close(fd);
357 return;
358 }
359
360 parse_dep_file(map, st.st_size);
361
362 munmap(map, st.st_size);
363
364 close(fd);
365}
366
367void traps(void)
368{
369 static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
370
371 if (*(int *)test != INT_CONF) {
372 fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
373 *(int *)test);
374 exit(2);
375 }
376}
377
378int main(int argc, char *argv[])
379{
380 traps();
381
382 if (argc != 4)
383 usage();
384
385 depfile = argv[1];
386 target = argv[2];
387 cmdline = argv[3];
388
389 print_cmdline();
390 print_deps();
391
392 return 0;
393}
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
new file mode 100644
index 000000000..459c45276
--- /dev/null
+++ b/scripts/basic/split-include.c
@@ -0,0 +1,226 @@
1/*
2 * split-include.c
3 *
4 * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
5 * This is a C version of syncdep.pl by Werner Almesberger.
6 *
7 * This program takes autoconf.h as input and outputs a directory full
8 * of one-line include files, merging onto the old values.
9 *
10 * Think of the configuration options as key-value pairs. Then there
11 * are five cases:
12 *
13 * key old value new value action
14 *
15 * KEY-1 VALUE-1 VALUE-1 leave file alone
16 * KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file
17 * KEY-3 - VALUE-3 write VALUE-3 into file
18 * KEY-4 VALUE-4 - write an empty file
19 * KEY-5 (empty) - leave old empty file alone
20 */
21
22#include <sys/stat.h>
23#include <sys/types.h>
24
25#include <ctype.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32
33#define ERROR_EXIT(strExit) \
34 { \
35 const int errnoSave = errno; \
36 fprintf(stderr, "%s: ", str_my_name); \
37 errno = errnoSave; \
38 perror((strExit)); \
39 exit(1); \
40 }
41
42
43
44int main(int argc, const char * argv [])
45{
46 const char * str_my_name;
47 const char * str_file_autoconf;
48 const char * str_dir_config;
49
50 FILE * fp_config;
51 FILE * fp_target;
52 FILE * fp_find;
53
54 int buffer_size;
55
56 char * line;
57 char * old_line;
58 char * list_target;
59 char * ptarget;
60
61 struct stat stat_buf;
62
63 /* Check arg count. */
64 if (argc != 3)
65 {
66 fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
67 exit(1);
68 }
69
70 str_my_name = argv[0];
71 str_file_autoconf = argv[1];
72 str_dir_config = argv[2];
73
74 /* Find a buffer size. */
75 if (stat(str_file_autoconf, &stat_buf) != 0)
76 ERROR_EXIT(str_file_autoconf);
77 buffer_size = 2 * stat_buf.st_size + 4096;
78
79 /* Allocate buffers. */
80 if ( (line = malloc(buffer_size)) == NULL
81 || (old_line = malloc(buffer_size)) == NULL
82 || (list_target = malloc(buffer_size)) == NULL )
83 ERROR_EXIT(str_file_autoconf);
84
85 /* Open autoconfig file. */
86 if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
87 ERROR_EXIT(str_file_autoconf);
88
89 /* Make output directory if needed. */
90 if (stat(str_dir_config, &stat_buf) != 0)
91 {
92 if (mkdir(str_dir_config, 0755) != 0)
93 ERROR_EXIT(str_dir_config);
94 }
95
96 /* Change to output directory. */
97 if (chdir(str_dir_config) != 0)
98 ERROR_EXIT(str_dir_config);
99
100 /* Put initial separator into target list. */
101 ptarget = list_target;
102 *ptarget++ = '\n';
103
104 /* Read config lines. */
105 while (fgets(line, buffer_size, fp_config))
106 {
107 const char * str_config;
108 int is_same;
109 int itarget;
110
111 if (line[0] != '#')
112 continue;
113 if ((str_config = strstr(line, "CONFIG_")) == NULL)
114 continue;
115
116 /* Make the output file name. */
117 str_config += sizeof("CONFIG_") - 1;
118 for (itarget = 0; !isspace(str_config[itarget]); itarget++)
119 {
120 int c = (unsigned char) str_config[itarget];
121 if (isupper(c)) c = tolower(c);
122 if (c == '_') c = '/';
123 ptarget[itarget] = c;
124 }
125 ptarget[itarget++] = '.';
126 ptarget[itarget++] = 'h';
127 ptarget[itarget++] = '\0';
128
129 /* Check for existing file. */
130 is_same = 0;
131 if ((fp_target = fopen(ptarget, "r")) != NULL)
132 {
133 fgets(old_line, buffer_size, fp_target);
134 if (fclose(fp_target) != 0)
135 ERROR_EXIT(ptarget);
136 if (!strcmp(line, old_line))
137 is_same = 1;
138 }
139
140 if (!is_same)
141 {
142 /* Auto-create directories. */
143 int islash;
144 for (islash = 0; islash < itarget; islash++)
145 {
146 if (ptarget[islash] == '/')
147 {
148 ptarget[islash] = '\0';
149 if (stat(ptarget, &stat_buf) != 0
150 && mkdir(ptarget, 0755) != 0)
151 ERROR_EXIT( ptarget );
152 ptarget[islash] = '/';
153 }
154 }
155
156 /* Write the file. */
157 if ((fp_target = fopen(ptarget, "w" )) == NULL)
158 ERROR_EXIT(ptarget);
159 fputs(line, fp_target);
160 if (ferror(fp_target) || fclose(fp_target) != 0)
161 ERROR_EXIT(ptarget);
162 }
163
164 /* Update target list */
165 ptarget += itarget;
166 *(ptarget-1) = '\n';
167 }
168
169 /*
170 * Close autoconfig file.
171 * Terminate the target list.
172 */
173 if (fclose(fp_config) != 0)
174 ERROR_EXIT(str_file_autoconf);
175 *ptarget = '\0';
176
177 /*
178 * Fix up existing files which have no new value.
179 * This is Case 4 and Case 5.
180 *
181 * I re-read the tree and filter it against list_target.
182 * This is crude. But it avoids data copies. Also, list_target
183 * is compact and contiguous, so it easily fits into cache.
184 *
185 * Notice that list_target contains strings separated by \n,
186 * with a \n before the first string and after the last.
187 * fgets gives the incoming names a terminating \n.
188 * So by having an initial \n, strstr will find exact matches.
189 */
190
191 fp_find = popen("find * -type f -name \"*.h\" -print", "r");
192 if (fp_find == 0)
193 ERROR_EXIT( "find" );
194
195 line[0] = '\n';
196 while (fgets(line+1, buffer_size, fp_find))
197 {
198 if (strstr(list_target, line) == NULL)
199 {
200 /*
201 * This is an old file with no CONFIG_* flag in autoconf.h.
202 */
203
204 /* First strip the \n. */
205 line[strlen(line)-1] = '\0';
206
207 /* Grab size. */
208 if (stat(line+1, &stat_buf) != 0)
209 ERROR_EXIT(line);
210
211 /* If file is not empty, make it empty and give it a fresh date. */
212 if (stat_buf.st_size != 0)
213 {
214 if ((fp_target = fopen(line+1, "w")) == NULL)
215 ERROR_EXIT(line);
216 if (fclose(fp_target) != 0)
217 ERROR_EXIT(line);
218 }
219 }
220 }
221
222 if (pclose(fp_find) != 0)
223 ERROR_EXIT("find");
224
225 return 0;
226}