tokline.c revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Copyright (c) 1985-2007 AT&T Knowledge Ventures *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* by AT&T Knowledge Ventures *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return an Sfio_t* to a file or string that
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * splices \\n to single lines
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * checks for "..." and '...' spanning newlines
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * drops #...\n comments
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <arg> is a file and first line matches
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * #!!! <level> <message> !!!
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * then error(<lev>,"%s: %s",<arg>,<msg>) called
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * NOTE: seek disabled and string disciplines cannot be composed
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * quoted \n translated to \r
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <error.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <tok.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfdisc_t disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int quote;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int* line;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Splice_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the splicer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinspliceline(Sfio_t* s, int op, void* val, Sfdisc_t* ad)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Splice_t* d = (Splice_t*)ad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int q;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int j;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(val);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_CLOSING:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(d->sp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_DPOP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(d);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_READ:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(buf = sfgetr(d->sp, '\n', 0)) && !(buf = sfgetr(d->sp, '\n', -1)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sfvalue(d->sp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = d->quote;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin j = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*d->line)++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n > 1 && buf[n - 2] == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin j = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n -= 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (q == '#')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (q == '#')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = (b = buf) + n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (b < e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = *b++) == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin b++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == q)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!q)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\'' || c == '"')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '#' && (b == (buf + 1) || (c = *(b - 2)) == ' ' || c == '\t'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (buf[n - 1] != '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = '#';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = b - buf - 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n = b - buf - 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin buf[n - 1] = '\n';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!j && buf[n - 1] != '\n' && (s->_flags & SF_STRING))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin buf[n++] = '\n';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (q && buf[n - 1] == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin buf[n - 1] = '\r';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (n <= 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(s, buf, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d->quote = q;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * open a stream to parse lines
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flags: 0 arg: open Sfio_t*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flags: SF_READ arg: file name
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flags: SF_STRING arg: null terminated char*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if line!=0 then it points to a line count that starts at 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and is incremented for each input line
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintokline(const char* arg, int flags, int* line)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Splice_t* d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int hidden;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(d = newof(0, Splice_t, 1, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(s = sfopen(NiL, NiL, "s")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(d);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(flags & (SF_STRING|SF_READ)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (Sfio_t*)arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(f = sfopen(NiL, arg, (flags & SF_STRING) ? "s" : "r")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(d);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((p = sfreserve(f, 0, 0)) && sfvalue(f) > 11 && strmatch(p, "#!!! +([-0-9]) *([!\n]) !!!\n*") && (e = strchr(p, '\n')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags = strtol(p + 5, &p, 10);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(flags, "%s:%-.*s", arg, e - p - 4, p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d->disc.exceptf = spliceline;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d->sp = f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(d->line = line ? line : &hidden) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfdisc(s, (Sfdisc_t*)d);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}