tin  2.6.1
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.6.1.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 : 2021-07-02
7 * Notes : #defines and structs for options_menu.c
8 *
9 * Copyright (c) 1997-2022 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
61static int line_no;
62
63static void
65 const char *message)
66{
67 perror(message);
68 exit(EXIT_FAILURE);
69}
70
71static 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
83static 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
95static 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
118static 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
155static 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
166static 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 return result;
178}
179
180static int
182 MYDATA *p)
183{
184 return !strcmp(p->type, "OPT_TITLE");
185}
186
187static 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
197static const char *
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
214static void
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
281static void
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
320static void
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",
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
401static void
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
526int
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}
#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:527
static const char * typename_of(struct mydata *p)
Definition: makecfg.c:198
#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:188
static int index_of(struct mydata *p)
Definition: makecfg.c:167
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
static char * string_dup(const char *string)
Definition: makecfg.c:84
#define MYDATA
Definition: makecfg.c:53
static int is_title(struct mydata *p)
Definition: makecfg.c:181
static int line_no
Definition: makecfg.c:61
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:321
#define MAXNAME
Definition: makecfg.c:50
static void makecfg(FILE *ifp, FILE *ofp, FILE *ofp2)
Definition: makecfg.c:402
static FILE * open_it(const char *filename, const char *mode)
Definition: makecfg.c:72
#define L_CURL
Definition: makecfg.c:47
static void generate_enum(FILE *ofp2)
Definition: makecfg.c:282
#define MAXTYPE
Definition: makecfg.c:51
static void generate_tbl(FILE *ofp)
Definition: makecfg.c:215
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:2252
#define EXIT_FAILURE
Definition: tin.h:1302