tin  2.4.5
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.4.5.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

makecfg.c
Go to the documentation of this file.
1 /*
2  * Project : tin - a Usenet reader
3  * Module : makecfg.c
4  * Author : Thomas E. Dickey
5  * Created : 1997-08-23
6  * Updated : 2020-08-15
7  * Notes : #defines and structs for options_menu.c
8  *
9  * Copyright (c) 1997-2021 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
56  char *name;
57  char *type;
58 };
59 
60 static MYDATA *all_data;
61 static int line_no;
62 
63 static void
65  const char *message)
66 {
67  perror(message);
68  exit(EXIT_FAILURE);
69 }
70 
71 static FILE *
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 *
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
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
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
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
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  }
178  return result;
179 }
180 
181 static int
183  MYDATA *p)
184 {
185  return !strcmp(p->type, "OPT_TITLE");
186 }
187 
188 static int
190  MYDATA *p)
191 {
192  return strcmp(p->type, "OPT_TITLE")
193  && strcmp(p->type, "OPT_STRING")
194  && strcmp(p->type, "OPT_CHAR")
195  && strcmp(p->type, "OPT_ON_OFF");
196 }
197 
198 static const char *
200  MYDATA *p)
201 {
202  if (!strcmp(p->type, "OPT_STRING") || !strcmp(p->type, "OPT_CHAR"))
203  return "char *";
204  if (!strcmp(p->type, "OPT_ON_OFF"))
205  return "t_bool *";
206  return "int *";
207 }
208 
209 static void
211  FILE *ofp)
212 {
213  static const char *const table_1[] =
214  {
215  ""
216  ,"#define OPT_TITLE 0"
217  ,"#define OPT_ON_OFF 1"
218  ,"#define OPT_LIST 2"
219  ,"#define OPT_STRING 3"
220  ,"#define OPT_NUM 4"
221  ,"#define OPT_CHAR 5"
222  ,""
223  ,"struct t_option option_table[]={"
224  ,0
225  };
226  static const char *const table_2[] =
227  {
228  "};"
229  ,0
230  };
231  static const char prefix[] = " { ";
232  static const char suffix[] = "},";
233  MYDATA *p;
234  char temp[BUFSIZ];
235 
236  /* generate the access table */
237  write_it(ofp, table_1);
238  for (p = all_data; p != NULL; p = p->link) {
239  if (p->name[0] == '#')
240  fprintf(ofp, "%s\n", p->name);
241  else {
242  int is_opt = !strncmp(p->type, "OPT_", 4);
243  int is_int = type_is_int(p);
244  char *dft_name = p->name;
245  /* TODO: is this still necessary? */
246  /* shorten message-variable names */
247  if (!strncmp(dft_name, "default_", 8))
248  dft_name += 8;
249  else if (!strncmp(dft_name, "attrib_", 7))
250  dft_name += 7;
251 
252  fprintf(ofp, "%s", prefix);
253  sprintf(temp, "%s,", is_opt ? p->type : "OPT_LIST");
254  fprintf(ofp, "%-13s", temp);
255 
256  if (is_title(p)) {
257  fprintf(ofp, "0, NULL, ");
258  } else if (!is_int) {
259  fprintf(ofp, "OINX_%s, 0, ", p->name);
260  } else {
261  fprintf(ofp, "0, &tinrc.%s, ", p->name);
262  }
263 
264  if (is_opt)
265  fprintf(ofp, "NULL, ");
266  else
267  fprintf(ofp, "%s, ", p->type);
268  fprintf(ofp, "&txt_%s ", dft_name);
269  fprintf(ofp, "%s\n", suffix);
270  }
271  }
272 
273  write_it(ofp, table_2);
274 }
275 
276 static void
278  FILE *ofp2)
279 {
280  MYDATA *p;
281 
282  static const char *const table_1[] = {
283  "enum option_enum {",
284  0
285  };
286  static const char *const table_2[] = {
287  "\tSIGNAL_HANDLER };",
288  "",
289  "#define LAST_OPT (SIGNAL_HANDLER - 1)",
290  0
291  };
292 
293  /* generate enumerated type */
294  write_it(ofp2, table_1);
295  for (p = all_data; p != NULL; p = p->link) {
296  if (p->name[0] == '#')
297  fprintf(ofp2, "%s\n", p->name);
298  else {
299  char *s = p->name;
300 
301  fprintf(ofp2, "\tOPT_");
302  while (*s != '\0') {
303  fprintf(ofp2, "%c",
304  (*s >= 'a' && *s <= 'z')
305  ? ((unsigned char) ((*s) -'a' + 'A'))
306  : *s);
307  s++;
308  }
309  fprintf(ofp2, ",\n");
310  }
311  }
312  write_it(ofp2, table_2);
313 }
314 
315 static void
317  FILE *ofp,
318  const char *opt_type,
319  const char *ptr_type,
320  int mode)
321 {
322  MYDATA *p, *q;
323  int after;
324  const char *addr = !strcmp(opt_type, "OPT_STRING") ? "" : "&";
325 
326  switch (mode) {
327  case 0:
328  fprintf(ofp, "\n%s %s_list[] = %c\n", ptr_type, opt_type, L_CURL);
329  break;
330  case 1:
331  fprintf(ofp, "\ntypedef OTYP %c\n", L_CURL);
332  break;
333  case 2:
334  fprintf(ofp, "\n");
335  break;
336  }
337  after = FALSE;
338 
339  for (p = all_data, q = NULL; p != NULL; p = p->link) {
340  if (p->name[0] == '#') {
341  if (!strcmp(p->name, "#endif")) {
342  if (after) {
343  fprintf(ofp, "%s\n", p->name);
344  after = FALSE;
345  }
346  q = NULL;
347  } else {
348  q = p;
349  }
350  } else if (!strcmp(p->type, opt_type)) {
351  if (q != NULL) {
352  fprintf(ofp, "%s\n", q->name);
353  q = NULL;
354  after = TRUE;
355  }
356  switch (mode) {
357  case 0:
358  fprintf(ofp, "\t%stinrc.%s,%*s/* %2d: %s__ */\n",
359  addr,
360  p->name,
361  MAXNAME - (int)(strlen(addr) + strlen(p->name)),
362  " ",
363  index_of(p),
364  p->name);
365  break;
366  case 1:
367  fprintf(ofp, "\tOVAL(oinx_%.*s, %s__)\n",
368  MAXTYPE, opt_type,
369  p->name);
370  break;
371  case 2:
372  fprintf(ofp, "#define OINX_%-*.*s OINX(oinx_%.*s, %s__)\n",
373  MAXNAME, MAXNAME,
374  p->name,
375  MAXTYPE, opt_type,
376  p->name);
377  break;
378  }
379  }
380  }
381 
382  switch (mode) {
383  case 0:
384  fprintf(ofp, "%c;\n", R_CURL);
385  break;
386  case 1:
387  fprintf(ofp, "\tOVAL(oinx_%.*s, s_MAX)\n", MAXTYPE, opt_type);
388  fprintf(ofp, "\tOEND(oinx_%.*s, Q1)\n", MAXTYPE, opt_type);
389  fprintf(ofp, "%c oinx_%.*s;\n", R_CURL, MAXTYPE, opt_type);
390  break;
391  case 2:
392  break;
393  }
394 }
395 
396 static void
398  FILE *ifp,
399  FILE *ofp,
400  FILE *ofp2)
401 {
402  char buffer[BUFSIZ];
403  MYDATA *p, *q;
404 
405  static const char *const table_1[] =
406  {
407  "/* This file is generated by MAKECFG */"
408  ,""
409  ,"#ifndef TINCFG_H"
410  ,"#define TINCFG_H 1"
411  ,""
412  ,"/* Macros for defining symbolic offsets that can be ifdef'd */"
413  ,"#undef OINX"
414  ,"#undef OVAL"
415  ,"#undef OEND"
416  ,"#undef OTYP"
417  ,""
418  ,"#ifdef lint"
419  ,"#\tdefine OINX(T, M) 0 /* 'lint -c' cannot be appeased */"
420  ,"#\tdefine OVAL(T, M) char M;"
421  ,"#\tdefine OEND(T, M) char M;"
422  ,"#\tdefine OTYP struct"
423  ,"#else"
424  ,"#\tifdef CPP_DOES_CONCAT"
425  ,"#\t\tdefine OINX(T, M) T ## M"
426  ,"#\t\tdefine OVAL(T, M) T ## M,"
427  ,"#\t\tdefine OEND(T, M) T ## M"
428  ,"#\t\tdefine OTYP enum"
429  ,"#\telse"
430  ,"#\t\tdefine OINX(T, M) \\"
431  ,"\t\t\t(((int)&(((T*)0)->M))/ \\"
432  ,"\t\t\t ((int)&(((T*)0)->Q1) - (int)&(((T*)0)->s_MAX)))"
433  ,"#\t\tdefine OVAL(T, M) char M;"
434  ,"#\t\tdefine OEND(T, M) char M;"
435  ,"#\t\tdefine OTYP struct"
436  ,"#\tendif /* CPP_DOES_CONCAT */"
437  ,"#endif /* lint */"
438  ,0
439  };
440  static const char *const table_2[] =
441  {
442  ""
443  ,"/* We needed these only to make the table compile */"
444  ,"#undef OINX"
445  ,"#undef OVAL"
446  ,"#undef OEND"
447  ,"#undef OTYP"
448  ,""
449  ,"#endif /* TINCFG_H */"
450  ,0
451  };
452  static const char *const table_3[] = {
453  "/* This file is generated by MAKECFG */",
454  "",
455  "#ifndef OPTIONS_MENU_H",
456  "#define OPTIONS_MENU_H 1",
457  "",
458  0
459  };
460  static const char *const table_4[] = {
461  "",
462  "#endif /* OPTIONS_MENU_H */",
463  0
464  };
465 
466  /*
467  * Process the input file.
468  */
469  line_no = 0;
470  while (fgets(buffer, sizeof(buffer) - 1, ifp))
471  parse_tbl(buffer);
472  fclose(ifp);
473 
474  /*
475  * Generate the output file
476  */
477  write_it(ofp, table_1);
478 
479  /*
480  * For each type used in the table, generate a list of pointers to
481  * that type.
482  */
483  for (p = all_data; p != NULL; p = p->link) {
484  int found = FALSE;
485 
486  if (p->name[0] == '#')
487  continue;
488  if (type_is_int(p) || is_title(p))
489  continue;
490 
491  for (q = all_data; p != q; q = q->link) {
492  if (!strcmp(p->type, q->type)) {
493  found = TRUE;
494  break;
495  }
496  }
497  if (!found
498  && !strncmp(p->type, "OPT_", 4)) {
499  generate_ptr (ofp, p->type, typename_of(p), 0);
500  generate_ptr (ofp, p->type, typename_of(p), 1);
501  generate_ptr (ofp, p->type, typename_of(p), 2);
502  }
503  }
504  generate_tbl(ofp);
505 
506  write_it(ofp, table_2);
507 
508  fclose(ofp);
509 
510  if (ofp2) {
511  write_it(ofp2, table_3);
512 
513  generate_enum(ofp2);
514 
515  write_it(ofp2, table_4);
516 
517  fclose(ofp2);
518  }
519 }
520 
521 int
523  int argc,
524  char *argv[])
525 {
526  FILE *input = stdin;
527  FILE *output = stdout;
528  FILE *output2 = open_it("options_menu.h", "w");
529  MYDATA *m, *n;
530 
531  if (argc > 1)
532  input = open_it(argv[1], "r");
533  if (argc > 2)
534  output = open_it(argv[2], "w");
535  makecfg(input, output, output2);
536 
537  m = all_data;
538  while (m) {
539  n = m->link;
540  FreeIfNeeded(m->name);
541  FreeIfNeeded(m->type);
542  free(m);
543  m = n;
544  }
545 
546  return (0);
547 }
#define TRUE
Definition: bool.h:74
#define FALSE
Definition: bool.h:70
static struct t_hashnode * table[222199]
Definition: hashstr.c:56
static char buf[16]
Definition: langinfo.c:50
int main(int argc, char *argv[])
Definition: makecfg.c:522
#define R_CURL
Definition: makecfg.c:48
static void parse_tbl(char *buffer)
Definition: makecfg.c:119
static int type_is_int(struct mydata *p)
Definition: makecfg.c:189
static int index_of(struct mydata *p)
Definition: makecfg.c:167
static const char * typename_of(struct mydata *p)
Definition: makecfg.c:199
static void failed(const char *message)
Definition: makecfg.c:64
static void write_it(FILE *ofp, const char *const *table)
Definition: makecfg.c:156
static void store_data(const char *name, const char *type)
Definition: makecfg.c:96
#define MYDATA
Definition: makecfg.c:53
static int is_title(struct mydata *p)
Definition: makecfg.c:182
static int line_no
Definition: makecfg.c:61
static FILE * open_it(const char *filename, const char *mode)
Definition: makecfg.c:72
static struct mydata * all_data
Definition: makecfg.c:60
static void generate_ptr(FILE *ofp, const char *opt_type, const char *ptr_type, int mode)
Definition: makecfg.c:316
static char * string_dup(const char *string)
Definition: makecfg.c:84
#define MAXNAME
Definition: makecfg.c:50
static void makecfg(FILE *ifp, FILE *ofp, FILE *ofp2)
Definition: makecfg.c:397
#define L_CURL
Definition: makecfg.c:47
static void generate_enum(FILE *ofp2)
Definition: makecfg.c:277
#define MAXTYPE
Definition: makecfg.c:51
static void generate_tbl(FILE *ofp)
Definition: makecfg.c:210
static const char * suffix[]
Definition: pcregrep.c:222
static const char * prefix[]
Definition: pcregrep.c:219
static uschar * buffer
Definition: pcretest.c:154
static char * output
Definition: plp_snprintf.c:204
const char * name
Definition: signal.c:117
char * name
Definition: makecfg.c:56
struct mydata * link
Definition: makecfg.c:55
char * type
Definition: makecfg.c:57
#define FreeIfNeeded(p)
Definition: tin.h:2214
#define EXIT_FAILURE
Definition: tin.h:1280