9d818742e8f5c920c60743307d8afa978ff9e80e
[mmh] / sbr / fmt_new.c
1 /*
2 ** fmt_new.c -- read format file/string and normalize
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/utils.h>
11
12 static char *formats = NULL;
13
14 /*
15 ** static prototypes
16 */
17 static void normalize(char *);
18
19
20 /*
21 ** Copy format string (selected by precedence) and store in static memory.
22 ** Normalize it.
23 */
24 char *
25 new_fs(char *form, char *format, char *default_fs)
26 {
27         struct stat st;
28         register FILE *fp;
29
30         if (formats) {
31                 free(formats);
32         }
33
34         if (form) {
35                 if ((fp = fopen(etcpath(form), "r")) == NULL) {
36                         adios(form, "unable to open format file");
37                 }
38                 if (fstat(fileno(fp), &st) == -1) {
39                         adios(form, "unable to stat format file");
40                 }
41                 formats = mh_xmalloc((size_t) st.st_size + 1);
42                 if (read(fileno(fp), formats, (int)st.st_size) != st.st_size) {
43                         adios(form, "error reading format file");
44                 }
45                 formats[st.st_size] = '\0';
46                 fclose(fp);
47
48         } else if (format) {
49                 formats = getcpy(format);
50
51         } else {
52                 formats = getcpy(default_fs);
53         }
54         normalize(formats);  /* expand escapes */
55
56         return formats;
57 }
58
59
60 /*
61 ** Expand escapes in format strings
62 */
63 static void
64 normalize(char *cp)
65 {
66         char *dp;
67
68         for (dp = cp; *cp; cp++) {
69                 if (*cp != '\\') {
70                         *dp++ = *cp;
71                         continue;
72                 }
73
74                 switch (*++cp) {
75                 case 'b':
76                         *dp++ = '\b';
77                         break;
78                 case 'f':
79                         *dp++ = '\f';
80                         break;
81                 case 'n':
82                         *dp++ = '\n';
83                         break;
84                 case 'r':
85                         *dp++ = '\r';
86                         break;
87                 case 't':
88                         *dp++ = '\t';
89                         break;
90                 case '\n':
91                         break;
92                 case '\0':
93                         cp--;
94                         /* fall */
95                 default:
96                         *dp++ = *cp;
97                         break;
98                 }
99         }
100         *dp = '\0';
101 }