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 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * return an Sfio_t* to a file or string that 28 * 29 * splices \\n to single lines 30 * checks for "..." and '...' spanning newlines 31 * drops #...\n comments 32 * 33 * if <arg> is a file and first line matches 34 * #!!! <level> <message> !!! 35 * then error(<lev>,"%s: %s",<arg>,<msg>) called 36 * 37 * NOTE: seek disabled and string disciplines cannot be composed 38 * quoted \n translated to \r 39 */ 40 41 #include <ast.h> 42 #include <error.h> 43 #include <tok.h> 44 45 typedef struct 46 { 47 Sfdisc_t disc; 48 Sfio_t* sp; 49 int quote; 50 int* line; 51 } Splice_t; 52 53 /* 54 * the splicer 55 */ 56 57 static int 58 spliceline(Sfio_t* s, int op, void* val, Sfdisc_t* ad) 59 { 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; 68 69 NoP(val); 70 switch (op) 71 { 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: 79 do 80 { 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] == '\\') 88 { 89 j = 1; 90 n -= 2; 91 if (q == '#') 92 { 93 n = 0; 94 continue; 95 } 96 } 97 else if (q == '#') 98 { 99 q = 0; 100 n = 0; 101 continue; 102 } 103 if (n > 0) 104 { 105 e = (b = buf) + n; 106 while (b < e) 107 { 108 if ((c = *b++) == '\\') 109 b++; 110 else if (c == q) 111 q = 0; 112 else if (!q) 113 { 114 if (c == '\'' || c == '"') 115 q = c; 116 else if (c == '#' && (b == (buf + 1) || (c = *(b - 2)) == ' ' || c == '\t')) 117 { 118 if (buf[n - 1] != '\n') 119 { 120 q = '#'; 121 n = b - buf - 2; 122 } 123 else if (n = b - buf - 1) 124 buf[n - 1] = '\n'; 125 break; 126 } 127 } 128 } 129 if (n > 0) 130 { 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'; 135 } 136 } 137 } while (n <= 0); 138 sfsetbuf(s, buf, n); 139 d->quote = q; 140 return 1; 141 default: 142 return 0; 143 } 144 } 145 146 /* 147 * open a stream to parse lines 148 * 149 * flags: 0 arg: open Sfio_t* 150 * flags: SF_READ arg: file name 151 * flags: SF_STRING arg: null terminated char* 152 * 153 * if line!=0 then it points to a line count that starts at 0 154 * and is incremented for each input line 155 */ 156 157 Sfio_t* 158 tokline(const char* arg, int flags, int* line) 159 { 160 Sfio_t* f; 161 Sfio_t* s; 162 Splice_t* d; 163 char* p; 164 char* e; 165 166 static int hidden; 167 168 if (!(d = newof(0, Splice_t, 1, 0))) 169 return 0; 170 if (!(s = sfopen(NiL, NiL, "s"))) 171 { 172 free(d); 173 return 0; 174 } 175 if (!(flags & (SF_STRING|SF_READ))) 176 f = (Sfio_t*)arg; 177 else if (!(f = sfopen(NiL, arg, (flags & SF_STRING) ? "s" : "r"))) 178 { 179 free(d); 180 sfclose(s); 181 return 0; 182 } 183 else if ((p = sfreserve(f, 0, 0)) && sfvalue(f) > 11 && strmatch(p, "#!!! +([-0-9]) *([!\n]) !!!\n*") && (e = strchr(p, '\n'))) 184 { 185 flags = strtol(p + 5, &p, 10); 186 error(flags, "%s:%-.*s", arg, e - p - 4, p); 187 } 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; 193 } 194