4e5637871b3bccc022d2b4e2d2d55d058f1c9479
[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 #define QUOTE '\\'
13
14 static char *formats = 0;
15
16 /*
17 ** static prototypes
18 */
19 static void normalize(char *);
20
21
22 /*
23 ** Get new format string
24 */
25
26 char *
27 new_fs(char *form, char *format, char *default_fs)
28 {
29         struct stat st;
30         register FILE *fp;
31
32         if (formats)
33                 free(formats);
34
35         if (form) {
36                 if ((fp = fopen(etcpath(form), "r")) == NULL)
37                         adios(form, "unable to open format file");
38
39                 if (fstat(fileno(fp), &st) == -1)
40                         adios(form, "unable to stat format file");
41
42                 formats = mh_xmalloc((size_t) st.st_size + 1);
43
44                 if (read(fileno(fp), formats, (int) st.st_size) != st.st_size)
45                         adios(form, "error reading format file");
46
47                 formats[st.st_size] = '\0';
48
49                 fclose(fp);
50         } else {
51                 formats = getcpy(format ? format : default_fs);
52         }
53
54         normalize(formats);  /* expand escapes */
55
56         return formats;
57 }
58
59
60 /*
61 ** Expand escapes in format strings
62 */
63
64 static void
65 normalize(char *cp)
66 {
67         char *dp;
68
69         for (dp = cp; *cp; cp++) {
70                 if (*cp != QUOTE) {
71                         *dp++ = *cp;
72                 } else {
73                         switch (*++cp) {
74                                 case 'b':
75                                         *dp++ = '\b';
76                                         break;
77
78                                 case 'f':
79                                         *dp++ = '\f';
80                                         break;
81
82                                 case 'n':
83                                         *dp++ = '\n';
84                                         break;
85
86                                 case 'r':
87                                         *dp++ = '\r';
88                                         break;
89
90                                 case 't':
91                                         *dp++ = '\t';
92                                         break;
93
94                                 case '\n':
95                                         break;
96
97                                 case 0:
98                                         cp--;  /* fall */
99                                 default:
100                                         *dp++ = *cp;
101                                         break;
102                         }
103                 }
104         }
105         *dp = '\0';
106 }