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