"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/makecfg.c" (9 Dec 2022, 11250 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


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.6.1_vs_2.6.2.

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