1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Eclipse Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.eclipse.org/org/documents/epl-v10.html * 11* (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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 45typedef 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 57static int 58spliceline(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 157Sfio_t* 158tokline(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