|
Packit |
992a25 |
/***********************************************************************
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* This software is part of the ast package *
|
|
Packit |
992a25 |
* Copyright (c) 1985-2011 AT&T Intellectual Property *
|
|
Packit |
992a25 |
* and is licensed under the *
|
|
Packit |
992a25 |
* Eclipse Public License, Version 1.0 *
|
|
Packit |
992a25 |
* by AT&T Intellectual Property *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* A copy of the License is available at *
|
|
Packit |
992a25 |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit |
992a25 |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* Information and Software Systems Research *
|
|
Packit |
992a25 |
* AT&T Research *
|
|
Packit |
992a25 |
* Florham Park NJ *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
* Glenn Fowler <gsf@research.att.com> *
|
|
Packit |
992a25 |
* David Korn <dgk@research.att.com> *
|
|
Packit |
992a25 |
* Phong Vo <kpv@research.att.com> *
|
|
Packit |
992a25 |
* *
|
|
Packit |
992a25 |
***********************************************************************/
|
|
Packit |
992a25 |
#pragma prototyped
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* Glenn Fowler
|
|
Packit |
992a25 |
* AT&T Research
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* scan s for tokens in fmt
|
|
Packit |
992a25 |
* s modified in place and not restored
|
|
Packit |
992a25 |
* if nxt!=0 then it will point to the first unread char in s
|
|
Packit |
992a25 |
* the number of scanned tokens is returned
|
|
Packit |
992a25 |
* -1 returned if s was not empty and fmt failed to match
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* ' ' in fmt matches 0 or more {space,tab}
|
|
Packit |
992a25 |
* '\n' in fmt eats remainder of current line
|
|
Packit |
992a25 |
* "..." and '...' quotes interpreted
|
|
Packit |
992a25 |
* newline is equivalent to end of buf except when quoted
|
|
Packit |
992a25 |
* \\ quotes following char
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* message support for %s and %v data
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* (5:12345) fixed length strings, ) may be \t
|
|
Packit |
992a25 |
* (null) NiL
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* "..." and '...' may span \n, and \\n is the line splice
|
|
Packit |
992a25 |
* quoted '\r' translated to '\n'
|
|
Packit |
992a25 |
* otherwise tokenizing is unconditionally terminated by '\n'
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* a null arg pointer skips that arg
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* %c char
|
|
Packit |
992a25 |
* %[hl]d [short|int|long] base 10
|
|
Packit |
992a25 |
* %f double
|
|
Packit |
992a25 |
* %g double
|
|
Packit |
992a25 |
* %[hl]n [short|int|long] C-style base
|
|
Packit |
992a25 |
* %[hl]o [short|int|long] base 8
|
|
Packit |
992a25 |
* %s string
|
|
Packit |
992a25 |
* %[hl]u same as %[hl]n
|
|
Packit |
992a25 |
* %v argv, elements
|
|
Packit |
992a25 |
* %[hl]x [short|int|long] base 16
|
|
Packit |
992a25 |
*
|
|
Packit |
992a25 |
* unmatched char args are set to "", int args to 0
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
#include <ast.h>
|
|
Packit |
992a25 |
#include <tok.h>
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static char empty[1];
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* get one string token into p
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
static char*
|
|
Packit |
992a25 |
lextok(register char* s, register int c, char** p, int* n)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register char* t;
|
|
Packit |
992a25 |
register int q;
|
|
Packit |
992a25 |
char* b;
|
|
Packit |
992a25 |
char* u;
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
if (*s == '(' && (!c || c == ' ' || c == '\n'))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
q = strtol(s + 1, &b, 10);
|
|
Packit |
992a25 |
if (*b == ':')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (*(t = ++b + q) == ')' || *t == '\t')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
s = t;
|
|
Packit |
992a25 |
*s++ = 0;
|
|
Packit |
992a25 |
goto end;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if (strneq(b, "null)", 5))
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
s = b + 5;
|
|
Packit |
992a25 |
b = 0;
|
|
Packit |
992a25 |
goto end;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
b = s;
|
|
Packit |
992a25 |
q = 0;
|
|
Packit |
992a25 |
t = 0;
|
|
Packit |
992a25 |
for (;;)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (!*s || !q && *s == '\n')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (!q)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (!c || c == ' ' || c == '\n') (*n)++;
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
s = b;
|
|
Packit |
992a25 |
b = empty;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (t) *t = 0;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if (*s == '\\')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
u = s;
|
|
Packit |
992a25 |
if (!*++s || *s == '\n' && (!*++s || *s == '\n')) continue;
|
|
Packit |
992a25 |
if (p)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (b == u) b = s;
|
|
Packit |
992a25 |
else if (!t) t = u;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if (q)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (*s == q)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
q = 0;
|
|
Packit |
992a25 |
if (!t) t = s;
|
|
Packit |
992a25 |
s++;
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if (*s == '\r') *s = '\n';
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if (*s == '"' || *s == '\'')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
q = *s++;
|
|
Packit |
992a25 |
if (p)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (b == (s - 1)) b = s;
|
|
Packit |
992a25 |
else if (!t) t = s - 1;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else if (*s == c || c == ' ' && *s == '\t')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
*s++ = 0;
|
|
Packit |
992a25 |
if (t) *t = 0;
|
|
Packit |
992a25 |
end:
|
|
Packit |
992a25 |
if (c == ' ') while (*s == ' ' || *s == '\t') s++;
|
|
Packit |
992a25 |
(*n)++;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (t) *t++ = *s;
|
|
Packit |
992a25 |
s++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (p) *p = b;
|
|
Packit |
992a25 |
return(s);
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
/*
|
|
Packit |
992a25 |
* scan entry
|
|
Packit |
992a25 |
*/
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
int
|
|
Packit |
992a25 |
tokscan(register char* s, char** nxt, const char* fmt, ...)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
register int c;
|
|
Packit |
992a25 |
register char* f;
|
|
Packit |
992a25 |
int num = 0;
|
|
Packit |
992a25 |
char* skip = 0;
|
|
Packit |
992a25 |
int q;
|
|
Packit |
992a25 |
int onum;
|
|
Packit |
992a25 |
long val;
|
|
Packit |
992a25 |
double dval;
|
|
Packit |
992a25 |
va_list ap;
|
|
Packit |
992a25 |
char* p_char;
|
|
Packit |
992a25 |
double* p_double;
|
|
Packit |
992a25 |
int* p_int;
|
|
Packit |
992a25 |
long* p_long;
|
|
Packit |
992a25 |
short* p_short;
|
|
Packit |
992a25 |
char** p_string;
|
|
Packit |
992a25 |
char* prv_f = 0;
|
|
Packit |
992a25 |
va_list prv_ap;
|
|
Packit |
992a25 |
|
|
Packit |
992a25 |
va_start(ap, fmt);
|
|
Packit |
992a25 |
if (!*s || *s == '\n')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
skip = s;
|
|
Packit |
992a25 |
s = empty;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
f = (char*)fmt;
|
|
Packit |
992a25 |
for (;;) switch (c = *f++)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
case 0:
|
|
Packit |
992a25 |
if (f = prv_f)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
prv_f = 0;
|
|
Packit |
992a25 |
/* prv_ap value is guarded by prv_f */
|
|
Packit |
992a25 |
va_copy(ap, prv_ap);
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
goto done;
|
|
Packit |
992a25 |
case ' ':
|
|
Packit |
992a25 |
while (*s == ' ' || *s == '\t') s++;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case '%':
|
|
Packit |
992a25 |
onum = num;
|
|
Packit |
992a25 |
switch (c = *f++)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
case 'h':
|
|
Packit |
992a25 |
case 'l':
|
|
Packit |
992a25 |
q = c;
|
|
Packit |
992a25 |
c = *f++;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
default:
|
|
Packit |
992a25 |
q = 0;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
switch (c)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
case 0:
|
|
Packit |
992a25 |
case '%':
|
|
Packit |
992a25 |
f--;
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
case ':':
|
|
Packit |
992a25 |
prv_f = f;
|
|
Packit |
992a25 |
f = va_arg(ap, char*);
|
|
Packit |
992a25 |
va_copy(prv_ap, ap);
|
|
Packit |
992a25 |
va_copy(ap, va_listval(va_arg(ap, va_listarg)));
|
|
Packit |
992a25 |
continue;
|
|
Packit |
992a25 |
case 'c':
|
|
Packit |
992a25 |
p_char = va_arg(ap, char*);
|
|
Packit |
992a25 |
if (!(c = *s) || c == '\n')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (p_char) *p_char = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (p_char) *p_char = c;
|
|
Packit |
992a25 |
s++;
|
|
Packit |
992a25 |
num++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'd':
|
|
Packit |
992a25 |
case 'n':
|
|
Packit |
992a25 |
case 'o':
|
|
Packit |
992a25 |
case 'u':
|
|
Packit |
992a25 |
case 'x':
|
|
Packit |
992a25 |
switch (c)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
case 'd':
|
|
Packit |
992a25 |
c = 10;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'n':
|
|
Packit |
992a25 |
case 'u':
|
|
Packit |
992a25 |
c = 0;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'o':
|
|
Packit |
992a25 |
c = 8;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'x':
|
|
Packit |
992a25 |
c = 16;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (!*s || *s == '\n')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
val = 0;
|
|
Packit |
992a25 |
p_char = s;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else val = strtol(s, &p_char, c);
|
|
Packit |
992a25 |
switch (q)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
case 'h':
|
|
Packit |
992a25 |
if (p_short = va_arg(ap, short*)) *p_short = (short)val;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'l':
|
|
Packit |
992a25 |
if (p_long = va_arg(ap, long*)) *p_long = val;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
default:
|
|
Packit |
992a25 |
if (p_int = va_arg(ap, int*)) *p_int = (int)val;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (s != p_char)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
s = p_char;
|
|
Packit |
992a25 |
num++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'f':
|
|
Packit |
992a25 |
case 'g':
|
|
Packit |
992a25 |
if (!*s || *s == '\n')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
dval = 0;
|
|
Packit |
992a25 |
p_char = s;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else dval = strtod(s, &p_char);
|
|
Packit |
992a25 |
if (p_double = va_arg(ap, double*)) *p_double = dval;
|
|
Packit |
992a25 |
if (s != p_char)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
s = p_char;
|
|
Packit |
992a25 |
num++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 's':
|
|
Packit |
992a25 |
p_string = va_arg(ap, char**);
|
|
Packit |
992a25 |
if (q = *f) f++;
|
|
Packit |
992a25 |
if (!*s || *s == '\n')
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (p_string) *p_string = s;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
else s = lextok(s, q, p_string, &num);
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case 'v':
|
|
Packit |
992a25 |
p_string = va_arg(ap, char**);
|
|
Packit |
992a25 |
c = va_arg(ap, int);
|
|
Packit |
992a25 |
if (q = *f) f++;
|
|
Packit |
992a25 |
if ((!*s || *s == '\n') && p_string)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
*p_string = 0;
|
|
Packit |
992a25 |
p_string = 0;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
while (*s && *s != '\n' && --c > 0)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
s = lextok(s, q, p_string, &num);
|
|
Packit |
992a25 |
if (p_string) p_string++;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (p_string) *p_string = 0;
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
if (skip) num = onum;
|
|
Packit |
992a25 |
else if (num == onum)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
if (!num) num = -1;
|
|
Packit |
992a25 |
skip = s;
|
|
Packit |
992a25 |
s = empty;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
case '\n':
|
|
Packit |
992a25 |
goto done;
|
|
Packit |
992a25 |
default:
|
|
Packit |
992a25 |
if ((*s++ != c) && !skip)
|
|
Packit |
992a25 |
{
|
|
Packit |
992a25 |
skip = s - 1;
|
|
Packit |
992a25 |
s = empty;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
break;
|
|
Packit |
992a25 |
}
|
|
Packit |
992a25 |
done:
|
|
Packit |
992a25 |
va_end(ap);
|
|
Packit |
992a25 |
if (*s == '\n') *s++ = 0;
|
|
Packit |
992a25 |
if (nxt) *nxt = skip ? skip : s;
|
|
Packit |
992a25 |
return(num);
|
|
Packit |
992a25 |
}
|