The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/scripts/split-include.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/types.h>
   23 #include <sys/stat.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((int)str_config[itarget]); itarget++)
  119         {
  120             char c = str_config[itarget];
  121             if (isupper((int)c)) c = tolower((int)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 }

Cache object: 9438389989c5d1cdb565101c372855fd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.