003ec2bc6461cb0b77a09e544addef8bf8b52e9e
[mmh] / sbr / fmt_new.c
1
2 /*
3  * fmt_new.c -- read format file/string and normalize
4  *
5  * $Id$
6  */
7
8 #include <h/mh.h>
9
10 #define QUOTE '\\'
11
12 static char *formats = 0;
13
14 /*
15  * static prototypes
16  */
17 static void normalize (char *);
18
19
20 /*
21  * Get new format string
22  */
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     if (form) {
34         if ((fp = fopen (etcpath (form), "r")) == NULL)
35             adios (form, "unable to open format file");
36
37         if (fstat (fileno (fp), &st) == -1)
38             adios (form, "unable to stat format file");
39
40         if (!(formats = malloc ((size_t) st.st_size + 1)))
41             adios (form, "unable to allocate space for format");
42
43         if (read (fileno(fp), formats, (int) st.st_size) != st.st_size)
44             adios (form, "error reading format file");
45
46         formats[st.st_size] = '\0';
47
48         fclose (fp);
49     } else {
50         formats = getcpy (format ? format : default_fs);
51     }
52
53     normalize (formats);        /* expand escapes */
54
55     return formats;
56 }
57
58
59 /*
60  * Expand escapes in format strings
61  */
62
63 static void
64 normalize (char *cp)
65 {
66     char *dp;
67
68     for (dp = cp; *cp; cp++) {
69         if (*cp != QUOTE) {
70             *dp++ = *cp;
71         } else {
72             switch (*++cp) {
73                 case 'b':
74                     *dp++ = '\b';
75                     break;
76
77                 case 'f':
78                     *dp++ = '\f';
79                     break;
80
81                 case 'n':
82                     *dp++ = '\n';
83                     break;
84
85                 case 'r':
86                     *dp++ = '\r';
87                     break;
88
89                 case 't':
90                     *dp++ = '\t';
91                     break;
92
93                 case '\n':
94                     break;
95
96                 case 0: 
97                     cp--;       /* fall */
98                 default: 
99                     *dp++ = *cp;
100                     break;
101             }
102         }
103     }
104     *dp = '\0';
105 }