home · contact · privacy
Make server config files more readable, their parsing more lenient.
[plomrogue] / src / common / err_try_fgets.c
1 /* err_try_fgets.c */
2
3 #include <stdint.h> /* uint8_t, uint32_t, UINT8_MAX */
4 #include <stdio.h> /* FILE, sprintf() */
5 #include <stdlib.h> /* atoi() */
6 #include <string.h> /* strlen(), strchr(), strcmp() */
7 #include "../common/readwrite.h" /* try_fgets() */
8 #include "../common/rexit.h" /* exit_err() */
9 #include "../common/try_malloc.h" /* try_malloc() */
10
11
12
13 /* Increments by one on each err_try_fgets() call, servers as a line counter. */
14 static uint32_t err_try_fgets_counter = 0;
15
16 /* Delimiter to use for err_try_fgets()' 'd' test. */
17 char * err_try_fgets_delim = "";
18
19
20
21 extern void reset_err_try_fgets_counter()
22 {
23     err_try_fgets_counter = 0;
24 }
25
26
27
28 extern void set_err_try_fgets_delim(char * delim)
29 {
30     err_try_fgets_delim = delim;
31 }
32
33
34
35 extern void err_line(uint8_t test, char * line, char * intro, char * msg)
36 {
37     if (!test)
38     {
39         return;
40     }
41     char * f_name = "err_line()";
42     char * line_intro = " Offending line ";
43     char * err = try_malloc(strlen(intro) + strlen(msg) + strlen(line_intro) +
44                             10 + 1 + 1 + strlen(line) + 1, f_name);
45     sprintf(err, "%s%s%s%d:\n%s", intro, msg, line_intro, err_try_fgets_counter,
46                                  line);
47     exit_err(1, err);
48 }
49
50
51
52 extern char *  err_try_fgets(char * line, uint32_t linemax, FILE * file,
53                              char * context, char * test)
54 {
55     char * err_end   = "File ended unexpectedly.";
56     char * err_empty = "Hit empty line where non-empty line was expected.";
57     char * err_many  = "Too many characters; expected only one.";
58     char * err_int   = "Expected valid positive or negative integer number.";
59     char * err_full  = "Hit non-empty line where empty line was expected.";
60     char * err_delim = "Expected proper delimiter, found something else.";
61     char * err_uint8 = "Value is too large. Must be 255 or less.";
62     char * f_name = "err_try_fgets()";
63     line[0] = '\0';
64     char * fgets_return = try_fgets(line, linemax + 1, file, f_name);
65     err_try_fgets_counter++;
66     err_line(strchr(test, '0') && !(strlen(line)), line, context, err_end);
67     err_line(strchr(test, 'n') && line[strlen(line) - 1] != '\n', line, context,
68              err_end);
69     err_line(strchr(test, 'e') && '\n' != line[0], line, context, err_full);
70     err_line(strchr(test, 'f') && '\n' == line[0], line, context, err_empty);
71     err_line(strchr(test, 's') && strlen(line) > 2, line, context, err_many);
72     err_line(strchr(test, 'd') && strcmp(line, err_try_fgets_delim), line,
73              context, err_delim);
74     if (strchr(test, 'i') || strchr(test, '8'))
75     {
76         err_line(!(strchr(test, 'f')) && strlen(line) < 2, line, context,
77                  err_int);
78         uint8_t i;
79         for (i = 0; '\n' != line[i] && '\0' != line[i]; i++)
80         {
81             uint8_t test =    (0 == i && ('-' == line[i] || '+' == line[i]))
82                            || ('0' <= line[i] && line[i] <= '9');
83             err_line(!test, line, context, err_int);
84         }
85         err_line(strlen(line) < 2 && ('-' == line[i] || '+' == line[i]),
86                  line, context, err_int);
87     }
88     err_line(strchr(test, '8') && atoi(line) > UINT8_MAX, line, context,
89              err_uint8);
90     return fgets_return;
91 }