import less(1)
[unleashed/tickless.git] / usr / src / lib / libast / common / string / tokline.c
blobe7b3024b9ad7cb8fa9d9ce748252c479ddff33aa
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
24 * Glenn Fowler
25 * AT&T Research
27 * return an Sfio_t* to a file or string that
29 * splices \\n to single lines
30 * checks for "..." and '...' spanning newlines
31 * drops #...\n comments
33 * if <arg> is a file and first line matches
34 * #!!! <level> <message> !!!
35 * then error(<lev>,"%s: %s",<arg>,<msg>) called
37 * NOTE: seek disabled and string disciplines cannot be composed
38 * quoted \n translated to \r
41 #include <ast.h>
42 #include <error.h>
43 #include <tok.h>
45 typedef struct
47 Sfdisc_t disc;
48 Sfio_t* sp;
49 int quote;
50 int* line;
51 } Splice_t;
54 * the splicer
57 static int
58 spliceline(Sfio_t* s, int op, void* val, Sfdisc_t* ad)
60 Splice_t* d = (Splice_t*)ad;
61 register char* b;
62 register int c;
63 register int n;
64 register int q;
65 register int j;
66 register char* e;
67 char* buf;
69 NoP(val);
70 switch (op)
72 case SF_CLOSING:
73 sfclose(d->sp);
74 return 0;
75 case SF_DPOP:
76 free(d);
77 return 0;
78 case SF_READ:
81 if (!(buf = sfgetr(d->sp, '\n', 0)) && !(buf = sfgetr(d->sp, '\n', -1)))
82 return 0;
83 n = sfvalue(d->sp);
84 q = d->quote;
85 j = 0;
86 (*d->line)++;
87 if (n > 1 && buf[n - 2] == '\\')
89 j = 1;
90 n -= 2;
91 if (q == '#')
93 n = 0;
94 continue;
97 else if (q == '#')
99 q = 0;
100 n = 0;
101 continue;
103 if (n > 0)
105 e = (b = buf) + n;
106 while (b < e)
108 if ((c = *b++) == '\\')
109 b++;
110 else if (c == q)
111 q = 0;
112 else if (!q)
114 if (c == '\'' || c == '"')
115 q = c;
116 else if (c == '#' && (b == (buf + 1) || (c = *(b - 2)) == ' ' || c == '\t'))
118 if (buf[n - 1] != '\n')
120 q = '#';
121 n = b - buf - 2;
123 else if (n = b - buf - 1)
124 buf[n - 1] = '\n';
125 break;
129 if (n > 0)
131 if (!j && buf[n - 1] != '\n' && (s->_flags & SF_STRING))
132 buf[n++] = '\n';
133 if (q && buf[n - 1] == '\n')
134 buf[n - 1] = '\r';
137 } while (n <= 0);
138 sfsetbuf(s, buf, n);
139 d->quote = q;
140 return 1;
141 default:
142 return 0;
147 * open a stream to parse lines
149 * flags: 0 arg: open Sfio_t*
150 * flags: SF_READ arg: file name
151 * flags: SF_STRING arg: null terminated char*
153 * if line!=0 then it points to a line count that starts at 0
154 * and is incremented for each input line
157 Sfio_t*
158 tokline(const char* arg, int flags, int* line)
160 Sfio_t* f;
161 Sfio_t* s;
162 Splice_t* d;
163 char* p;
164 char* e;
166 static int hidden;
168 if (!(d = newof(0, Splice_t, 1, 0)))
169 return 0;
170 if (!(s = sfopen(NiL, NiL, "s")))
172 free(d);
173 return 0;
175 if (!(flags & (SF_STRING|SF_READ)))
176 f = (Sfio_t*)arg;
177 else if (!(f = sfopen(NiL, arg, (flags & SF_STRING) ? "s" : "r")))
179 free(d);
180 sfclose(s);
181 return 0;
183 else if ((p = sfreserve(f, 0, 0)) && sfvalue(f) > 11 && strmatch(p, "#!!! +([-0-9]) *([!\n]) !!!\n*") && (e = strchr(p, '\n')))
185 flags = strtol(p + 5, &p, 10);
186 error(flags, "%s:%-.*s", arg, e - p - 4, p);
188 d->disc.exceptf = spliceline;
189 d->sp = f;
190 *(d->line = line ? line : &hidden) = 0;
191 sfdisc(s, (Sfdisc_t*)d);
192 return s;