"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.1/src/makecfg.c" (24 Dec 2016, 10950 Bytes) of archive /linux/misc/tin-2.4.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "makecfg.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.0_vs_2.4.1.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : makecfg.c
    4  *  Author    : Thomas E. Dickey
    5  *  Created   : 1997-08-23
    6  *  Updated   : 2016-11-18
    7  *  Notes     : #defines and structs for options_menu.c
    8  *
    9  * Copyright (c) 1997-2017 Thomas E. Dickey <dickey@invisible-island.net>
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. The name of the author may not be used to endorse or promote
   21  *    products derived from this software without specific prior written
   22  *    permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   25  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 
   38 #define __BUILD__
   39 #define PROTO_H 1   /* don't include proto.h */
   40 #ifndef TIN_H
   41 #   include "tin.h"
   42 #endif /* !TIN_H */
   43 
   44 #define L_CURL '{'
   45 #define R_CURL '}'
   46 
   47 #define MAXNAME 36 /* maximum name-length (just for readability formatting) */
   48 #define MAXTYPE 5  /* limits opt_type to keep names unique within 31 chars */
   49 
   50 #define MYDATA struct mydata
   51 MYDATA {
   52     MYDATA *link;
   53     char *name;
   54     char *type;
   55 };
   56 
   57 static MYDATA *all_data;
   58 static int line_no;
   59 
   60 static void
   61 failed(
   62     const char *message)
   63 {
   64     perror(message);
   65     exit(EXIT_FAILURE);
   66 }
   67 
   68 static FILE *
   69 open_it(
   70     const char *filename,
   71     const char *mode)
   72 {
   73     FILE *fp = fopen(filename, mode);
   74 
   75     if (fp == 0)
   76         failed(filename);
   77     return fp;
   78 }
   79 
   80 static char *
   81 string_dup(
   82     const char *string)
   83 {
   84     char *buf;
   85 
   86     if ((buf = malloc(strlen(string) + 1)) == NULL)
   87         failed("malloc() failed");
   88 
   89     return strcpy(buf, string);
   90 }
   91 
   92 static void
   93 store_data(
   94     const char *name,
   95     const char *type)
   96 {
   97     MYDATA *p, *q;
   98 
   99     if ((p = (MYDATA *) malloc(sizeof(MYDATA))) == NULL)
  100         failed("malloc() failed");
  101 
  102     p->link = 0;
  103     p->name = string_dup(name);
  104     p->type = string_dup(type);
  105 
  106     if ((q = all_data) == 0)
  107         all_data = p;
  108     else {
  109         while (q->link != 0)
  110             q = q->link;
  111         q->link = p;
  112     }
  113 }
  114 
  115 static void
  116 parse_tbl(
  117     char *buffer)
  118 {
  119     char *s = buffer;
  120     char *t = s + strlen(s);
  121 
  122     /* strip leading/trailing blanks */
  123     while ((t-- != s) && isspace ((int)*t))
  124         *t = '\0';
  125     while (isspace ((int)*s))
  126         s++;
  127     buffer = s;
  128 
  129     line_no++;
  130     if (*buffer != ';' && *buffer != '\0') {    /* ignore comments */
  131         if (*buffer == '#') {
  132             store_data(buffer, "");
  133         } else {
  134             /*
  135              * otherwise the data consists of 2 blank
  136              * separated columns (name, type).
  137              */
  138             while (*s && !isspace ((int)*s))
  139                 s++;
  140             while (isspace ((int)*s))
  141                 *s++ = '\0';
  142             store_data(buffer, s);
  143         }
  144     }
  145 }
  146 
  147 static void
  148 write_it(
  149     FILE *ofp,
  150     const char * const *table)
  151 {
  152     int n;
  153 
  154     for (n = 0; table[n] != 0; n++)
  155         fprintf(ofp, "%s\n", table[n]);
  156 }
  157 
  158 static int
  159 index_of(
  160     MYDATA *p)
  161 {
  162     int result = 0;
  163     MYDATA *q;
  164 
  165     for (q = all_data; q != 0 && q != p; q = q->link) {
  166         if (!strcmp(p->type, q->type)) {
  167             result++;
  168         }
  169     }
  170     return result;
  171 }
  172 
  173 static int
  174 is_title(
  175     MYDATA *p)
  176 {
  177     return !strcmp(p->type, "OPT_TITLE");
  178 }
  179 
  180 static int
  181 type_is_int(
  182     MYDATA *p)
  183 {
  184     return strcmp(p->type, "OPT_TITLE")
  185       &&   strcmp(p->type, "OPT_STRING")
  186       &&   strcmp(p->type, "OPT_CHAR")
  187       &&   strcmp(p->type, "OPT_ON_OFF");
  188 }
  189 
  190 static const char *
  191 typename_of(
  192     MYDATA *p)
  193 {
  194     if (!strcmp(p->type, "OPT_STRING") || !strcmp(p->type, "OPT_CHAR"))
  195         return "char *";
  196     if (!strcmp(p->type, "OPT_ON_OFF"))
  197         return "t_bool *";
  198     return "int *";
  199 }
  200 
  201 static void
  202 generate_tbl(
  203     FILE *ofp)
  204 {
  205     static const char *const table_1[] =
  206     {
  207         ""
  208         ,"#define OPT_TITLE     0"
  209         ,"#define OPT_ON_OFF    1"
  210         ,"#define OPT_LIST      2"
  211         ,"#define OPT_STRING    3"
  212         ,"#define OPT_NUM       4"
  213         ,"#define OPT_CHAR      5"
  214         ,""
  215         ,"struct t_option option_table[]={"
  216         ,0
  217     };
  218     static const char *const table_2[] =
  219     {
  220         "};"
  221         ,0
  222     };
  223     static const char prefix[] = "  { ";
  224     static const char suffix[] = "},";
  225     MYDATA *p;
  226     char temp[BUFSIZ];
  227 
  228     /* generate the access table */
  229     write_it(ofp, table_1);
  230     for (p = all_data; p != 0; p = p->link) {
  231         if (p->name[0] == '#')
  232             fprintf(ofp, "%s\n", p->name);
  233         else {
  234             int is_opt = !strncmp(p->type, "OPT_", 4);
  235             int is_int = type_is_int(p);
  236             char *dft_name = p->name;
  237             /* TODO: is this still necessary? */
  238             /* shorten message-variable names */
  239             if (!strncmp(dft_name, "default_", 8))
  240                 dft_name += 8;
  241             else if (!strncmp(dft_name, "attrib_", 7))
  242                 dft_name += 7;
  243 
  244             fprintf(ofp, "%s", prefix);
  245             sprintf(temp, "%s,", is_opt ? p->type : "OPT_LIST");
  246             fprintf(ofp, "%-13s", temp);
  247 
  248             if (is_title(p)) {
  249                 fprintf(ofp, "0, NULL, ");
  250             } else if (!is_int) {
  251                 fprintf(ofp, "OINX_%s, 0, ", p->name);
  252             } else {
  253                 fprintf(ofp, "0, &tinrc.%s, ", p->name);
  254             }
  255 
  256             if (is_opt)
  257                 fprintf(ofp, "NULL, ");
  258             else
  259                 fprintf(ofp, "%s, ", p->type);
  260             fprintf(ofp, "&txt_%s ", dft_name);
  261             fprintf(ofp, "%s\n", suffix);
  262         }
  263     }
  264 
  265     write_it(ofp, table_2);
  266 }
  267 
  268 static void
  269 generate_enum(
  270     FILE *ofp2)
  271 {
  272     MYDATA *p;
  273 
  274     static const char *const table_1[] = {
  275         "enum option_enum {",
  276         0
  277     };
  278     static const char *const table_2[] = {
  279         "\tSIGNAL_HANDLER };",
  280         "",
  281         "#define LAST_OPT (SIGNAL_HANDLER - 1)",
  282         0
  283     };
  284 
  285     /* generate enumerated type */
  286     write_it(ofp2, table_1);
  287     for (p = all_data; p != 0; p = p->link) {
  288         if (p->name[0] == '#')
  289             fprintf(ofp2, "%s\n", p->name);
  290         else {
  291             char *s = p->name;
  292 
  293             fprintf(ofp2, "\tOPT_");
  294             while (*s != '\0') {
  295                 fprintf(ofp2, "%c",
  296                      isalpha ((unsigned char)*s) && islower((unsigned char)*s)
  297                      ? toupper ((unsigned char)*s)
  298                      : *s);
  299                 s++;
  300             }
  301             fprintf(ofp2, ",\n");
  302         }
  303     }
  304     write_it(ofp2, table_2);
  305 }
  306 
  307 static void
  308 generate_ptr(
  309     FILE *ofp,
  310     const char *opt_type,
  311     const char *ptr_type,
  312     int mode)
  313 {
  314     MYDATA *p, *q;
  315     int after;
  316     const char *addr = !strcmp(opt_type, "OPT_STRING") ? "" : "&";
  317 
  318     switch (mode) {
  319     case 0:
  320         fprintf(ofp, "\n%s %s_list[] = %c\n", ptr_type, opt_type, L_CURL);
  321         break;
  322     case 1:
  323         fprintf(ofp, "\ntypedef OTYP %c\n", L_CURL);
  324         break;
  325     case 2:
  326         fprintf(ofp, "\n");
  327         break;
  328     }
  329     after = FALSE;
  330 
  331     for (p = all_data, q = 0; p != 0; p = p->link) {
  332         if (p->name[0] == '#') {
  333             if (!strcmp(p->name, "#endif")) {
  334                 if (after) {
  335                     fprintf(ofp, "%s\n", p->name);
  336                     after = FALSE;
  337                 }
  338                 q = 0;
  339             } else {
  340                 q = p;
  341             }
  342         } else if (!strcmp(p->type, opt_type)) {
  343             if (q != 0) {
  344                 fprintf(ofp, "%s\n", q->name);
  345                 q = 0;
  346                 after = TRUE;
  347             }
  348             switch (mode) {
  349             case 0:
  350                 fprintf(ofp, "\t%stinrc.%s,%*s/* %2d: %s__ */\n",
  351                     addr,
  352                     p->name,
  353                     MAXNAME - (int)(strlen(addr) + strlen(p->name)),
  354                     " ",
  355                     index_of(p),
  356                     p->name);
  357                 break;
  358             case 1:
  359                 fprintf(ofp, "\tOVAL(oinx_%.*s, %s__)\n",
  360                     MAXTYPE, opt_type,
  361                     p->name);
  362                 break;
  363             case 2:
  364                 fprintf(ofp, "#define OINX_%-*.*s OINX(oinx_%.*s, %s__)\n",
  365                     MAXNAME, MAXNAME,
  366                     p->name,
  367                     MAXTYPE, opt_type,
  368                     p->name);
  369                 break;
  370             }
  371         }
  372     }
  373 
  374     switch (mode) {
  375     case 0:
  376         fprintf(ofp, "%c;\n", R_CURL);
  377         break;
  378     case 1:
  379         fprintf(ofp, "\tOVAL(oinx_%.*s, s_MAX)\n", MAXTYPE, opt_type);
  380         fprintf(ofp, "\tOEND(oinx_%.*s, Q1)\n", MAXTYPE, opt_type);
  381         fprintf(ofp, "%c oinx_%.*s;\n", R_CURL, MAXTYPE, opt_type);
  382         break;
  383     case 2:
  384         break;
  385     }
  386 }
  387 
  388 static void
  389 makecfg(
  390     FILE *ifp,
  391     FILE *ofp,
  392     FILE *ofp2)
  393 {
  394     char buffer[BUFSIZ];
  395     MYDATA *p, *q;
  396 
  397     static const char *const table_1[] =
  398     {
  399         "/* This file is generated by MAKECFG */"
  400         ,""
  401         ,"#ifndef TINCFG_H"
  402         ,"#define TINCFG_H 1"
  403         ,""
  404         ,"/* Macros for defining symbolic offsets that can be ifdef'd */"
  405         ,"#undef OINX"
  406         ,"#undef OVAL"
  407         ,"#undef OEND"
  408         ,"#undef OTYP"
  409         ,""
  410         ,"#ifdef lint"
  411         ,"#\tdefine OINX(T, M) 0 /* 'lint -c' cannot be appeased */"
  412         ,"#\tdefine OVAL(T, M) char M;"
  413         ,"#\tdefine OEND(T, M) char M;"
  414         ,"#\tdefine OTYP struct"
  415         ,"#else"
  416         ,"#\tifdef CPP_DOES_CONCAT"
  417         ,"#\t\tdefine OINX(T, M) T ## M"
  418         ,"#\t\tdefine OVAL(T, M) T ## M,"
  419         ,"#\t\tdefine OEND(T, M) T ## M"
  420         ,"#\t\tdefine OTYP enum"
  421         ,"#\telse"
  422         ,"#\t\tdefine OINX(T, M) \\"
  423         ,"\t\t\t(((int)&(((T*)0)->M))/ \\"
  424         ,"\t\t\t ((int)&(((T*)0)->Q1) - (int)&(((T*)0)->s_MAX)))"
  425         ,"#\t\tdefine OVAL(T, M) char M;"
  426         ,"#\t\tdefine OEND(T, M) char M;"
  427         ,"#\t\tdefine OTYP struct"
  428         ,"#\tendif /* CPP_DOES_CONCAT */"
  429         ,"#endif /* lint */"
  430         ,0
  431     };
  432     static const char *const table_2[] =
  433     {
  434          ""
  435         ,"/* We needed these only to make the table compile */"
  436         ,"#undef OINX"
  437         ,"#undef OVAL"
  438         ,"#undef OEND"
  439         ,"#undef OTYP"
  440         ,""
  441         ,"#endif /* TINCFG_H */"
  442         ,0
  443     };
  444     static const char *const table_3[] = {
  445         "/* This file is generated by MAKECFG */",
  446         "",
  447         "#ifndef OPTIONS_MENU_H",
  448         "#define OPTIONS_MENU_H 1",
  449         "",
  450         0
  451     };
  452     static const char *const table_4[] = {
  453         "",
  454         "#endif /* OPTIONS_MENU_H */",
  455         0
  456     };
  457 
  458     /*
  459      * Process the input file.
  460      */
  461     line_no = 0;
  462     while (fgets(buffer, sizeof(buffer) - 1, ifp))
  463         parse_tbl(buffer);
  464     fclose(ifp);
  465 
  466     /*
  467      * Generate the output file
  468      */
  469     write_it(ofp, table_1);
  470 
  471     /*
  472      * For each type used in the table, generate a list of pointers to
  473      * that type.
  474      */
  475     for (p = all_data; p != 0; p = p->link) {
  476         int found = FALSE;
  477 
  478         if (p->name[0] == '#')
  479             continue;
  480         if (type_is_int(p) || is_title(p))
  481             continue;
  482 
  483         for (q = all_data; p != q; q = q->link) {
  484             if (!strcmp(p->type, q->type)) {
  485                 found = TRUE;
  486                 break;
  487             }
  488         }
  489         if (!found
  490          && !strncmp(p->type, "OPT_", 4)) {
  491             generate_ptr (ofp, p->type, typename_of(p), 0);
  492             generate_ptr (ofp, p->type, typename_of(p), 1);
  493             generate_ptr (ofp, p->type, typename_of(p), 2);
  494         }
  495     }
  496     generate_tbl(ofp);
  497 
  498     write_it(ofp, table_2);
  499 
  500     fclose(ofp);
  501 
  502     if (ofp2) {
  503         write_it(ofp2, table_3);
  504 
  505         generate_enum(ofp2);
  506 
  507         write_it(ofp2, table_4);
  508 
  509         fclose(ofp2);
  510     }
  511 }
  512 
  513 int
  514 main(
  515     int argc,
  516     char *argv[])
  517 {
  518     FILE *input = stdin;
  519     FILE *output = stdout;
  520     FILE *output2 = open_it("options_menu.h", "w");
  521     MYDATA *m, *n;
  522 
  523     if (argc > 1)
  524         input = open_it(argv[1], "r");
  525     if (argc > 2)
  526         output = open_it(argv[2], "w");
  527     makecfg(input, output, output2);
  528 
  529     m = all_data;
  530     while (m) {
  531         n = m->link;
  532         FreeIfNeeded(m->name);
  533         FreeIfNeeded(m->type);
  534         free(m);
  535         m = n;
  536     }
  537 
  538     return (0);
  539 }