52a8e74d0ed62cbe301fa25cc60b3ce29807089b
[mmh] / sbr / vfgets.c
1
2 /*
3  * vfgets.c -- virtual fgets
4  *
5  * $Id$
6  */
7
8 #include <h/mh.h>
9
10 #define QUOTE   '\\'
11
12
13 int
14 vfgets (FILE *in, char **bp)
15 {
16     int toggle;
17     char *cp, *dp, *ep, *fp;
18     static int len = 0;
19     static char *pp = NULL;
20
21     if (pp == NULL)
22         if (!(pp = malloc ((size_t) (len = BUFSIZ))))
23             adios (NULL, "unable to allocate string storage");
24
25     for (ep = (cp = pp) + len - 1;;) {
26         if (fgets (cp, ep - cp + 1, in) == NULL) {
27             if (cp != pp) {
28                 *bp = pp;
29                 return 0;
30             }
31             return (ferror (in) && !feof (in) ? -1 : 1);
32         }
33
34         if ((dp = cp + strlen (cp) - 2) < cp || *dp != QUOTE) {
35 wrong_guess:
36             if (cp > ++dp)
37                 adios (NULL, "vfgets() botch -- you lose big");
38             if (*dp == '\n') {
39                 *bp = pp;
40                 return 0;
41             } else {
42                 cp = ++dp;
43             }
44         } else {
45             for (fp = dp - 1, toggle = 0; fp >= cp; fp--) {
46                 if (*fp != QUOTE)
47                     break;
48                 else
49                     toggle = !toggle;
50             }
51             if (toggle)
52                 goto wrong_guess;
53
54             if (*++dp == '\n') {
55                 *--dp = 0;
56                 cp = dp;
57             } else {
58                 cp = ++dp;
59             }
60         }
61
62         if (cp >= ep) {
63             int curlen = cp - pp;
64
65             if (!(dp = realloc (pp, (size_t) (len += BUFSIZ)))) {
66                 adios (NULL, "unable to allocate string storage");
67             } else {
68                 cp = dp + curlen;
69                 ep = (pp = dp) + len - 1;
70             }
71         }
72     }
73 }