Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Ported palacios to Kbuild
[palacios.git] / scripts / basic / split-include.c
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
44 int 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 }