Rework addition of Symbian splash screen to reduce the source impact (uses SVG from Bug 2414)
Notes: by using the OPTION SOURCEDIR parameter in the mifconv extension instructions, I can
arrange to use the same source file name in sfimage, without having to export over the original
Nokia file. This means that the name inside splashscreen.mbg is the same, which removes the need
for the conditional compilation in SplashScreen.cpp, and gets rid of sf_splashscreen.mmp.
#ifndef __SYMBIAN32__
/*
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
/*
* This file is part of zsh, the Z shell.
*
* Copyright (c) 1999 Sven Wischnowsky
* All rights reserved.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and to distribute modified versions of this software for any
* purpose, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* In no event shall Sven Wischnowsky or the Zsh Development Group be liable
* to any party for direct, indirect, special, incidental, or consequential
* damages arising out of the use of this software and its documentation,
* even if Sven Wischnowsky and the Zsh Development Group have been advised of
* the possibility of such damage.
*
* Sven Wischnowsky and the Zsh Development Group specifically disclaim any
* warranties, including, but not limited to, the implied warranties of
* merchantability and fitness for a particular purpose. The software
* provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
* Zsh Development Group have no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
*/
#include "zutil.mdh"
#include "zutil.pro"
#ifdef __SYMBIAN32__
#ifdef __WINSCW__
#pragma warn_unusedarg off
#pragma warn_possunwant off
#endif//__WINSCW__
#endif//__SYMBIAN32__
/* Style stuff. */
typedef struct stypat *Stypat;
typedef struct style *Style;
/* A pattern and the styles for it. */
struct style {
Style next; /* next in stypat list */
Stypat pats; /* patterns */
char *name;
};
struct stypat {
Stypat next;
char *pat; /* pattern string */
Patprog prog; /* compiled pattern */
int weight; /* how specific is the pattern? */
Eprog eval; /* eval-on-retrieve? */
char **vals;
};
/* List of styles. */
static Style zstyles, zlstyles;
/* Memory stuff. */
static void
freestypat(Stypat p)
{
zsfree(p->pat);
freepatprog(p->prog);
if (p->vals)
freearray(p->vals);
if (p->eval)
freeeprog(p->eval);
zfree(p, sizeof(*p));
}
static void
freeallstyles(void)
{
Style s, sn;
Stypat p, pn;
for (s = zstyles; s; s = sn) {
sn = s->next;
for (p = s->pats; p; p = pn) {
pn = p->next;
freestypat(p);
}
zsfree(s->name);
zfree(s, sizeof(*s));
}
zstyles = zlstyles = NULL;
}
/* Get the style struct for a name. */
static Style
getstyle(char *name)
{
Style s;
for (s = zstyles; s; s = s->next)
if (!strcmp(name, s->name))
return s;
return NULL;
}
/* Store a value for a style. */
static int
setstypat(Style s, char *pat, Patprog prog, char **vals, int eval)
{
int weight, tmp, first;
char *str;
Stypat p, q, qq;
Eprog eprog = NULL;
if (eval) {
int ef = errflag;
eprog = parse_string(zjoin(vals, ' ', 1));
errflag = ef;
if (!eprog)
{
freepatprog(prog);
return 1;
}
eprog = dupeprog(eprog, 0);
}
for (p = s->pats; p; p = p->next)
if (!strcmp(pat, p->pat)) {
/* Exists -> replace. */
if (p->vals)
freearray(p->vals);
if (p->eval)
freeeprog(p->eval);
p->vals = zarrdup(vals);
p->eval = eprog;
freepatprog(prog);
return 0;
}
/* New pattern. */
p = (Stypat) zalloc(sizeof(*p));
p->pat = ztrdup(pat);
p->prog = prog;
p->vals = zarrdup(vals);
p->eval = eprog;
p->next = NULL;
/* Calculate the weight. */
for (weight = 0, tmp = 2, first = 1, str = pat; *str; str++) {
if (first && *str == '*' && (!str[1] || str[1] == ':')) {
/* Only `*' in this component. */
tmp = 0;
continue;
}
first = 0;
if (*str == '(' || *str == '|' || *str == '*' || *str == '[' ||
*str == '<' || *str == '?' || *str == '#' || *str == '^')
/* Is pattern. */
tmp = 1;
if (*str == ':') {
/* Yet another component. */
first = 1;
weight += tmp;
tmp = 2;
}
}
p->weight = (weight += tmp);
for (qq = NULL, q = s->pats; q && q->weight >= weight;
qq = q, q = q->next);
p->next = q;
if (qq)
qq->next = p;
else
s->pats = p;
return 0;
}
/* Add a new style. */
static Style
addstyle(char *name)
{
Style s;
s = (Style) zalloc(sizeof(*s));
s->next = NULL;
s->pats = NULL;
s->name = ztrdup(name);
if (zlstyles)
zlstyles->next = s;
else
zstyles = s;
zlstyles = s;
return s;
}
static char **
evalstyle(Stypat p)
{
int ef = errflag;
char **ret, *str;
unsetparam("reply");
execode(p->eval, 1, 0);
if (errflag) {
errflag = ef;
return NULL;
}
errflag = ef;
queue_signals();
if ((ret = getaparam("reply")))
ret = arrdup(ret);
else if ((str = getsparam("reply"))) {
ret = (char **) hcalloc(2 * sizeof(char *));
ret[0] = dupstring(str);
}
unqueue_signals();
unsetparam("reply");
return ret;
}
/* Look up a style for a context pattern. This does the matching. */
static char **
lookupstyle(char *ctxt, char *style)
{
Style s;
Stypat p;
for (s = zstyles; s; s = s->next)
if (!strcmp(s->name, style))
for (p = s->pats; p; p = p->next)
if (pattry(p->prog, ctxt))
return (p->eval ? evalstyle(p) : p->vals);
return NULL;
}
static int
bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
int min, max, n, add = 0, list = 0, eval = 0;
if (!args[0])
list = 1;
else if (args[0][0] == '-') {
char oc;
if ((oc = args[0][1]) && oc != '-') {
if (args[0][2]) {
zwarnnam(nam, "invalid argument: %s", args[0], 0);
return 1;
}
if (oc == 'L')
list = 2;
else if (oc == 'e') {
eval = add = 1;
args++;
}
} else {
add = 1;
args++;
}
} else
add = 1;
if (add) {
Style s;
Patprog prog;
char *pat;
if (arrlen(args) < 2) {
zwarnnam(nam, "not enough arguments", NULL, 0);
return 1;
}
pat = dupstring(args[0]);
tokenize(pat);
if (!(prog = patcompile(pat, PAT_ZDUP, NULL))) {
zwarnnam(nam, "invalid pattern: %s", args[0], 0);
return 1;
}
if (!(s = getstyle(args[1])))
s = addstyle(args[1]);
return setstypat(s, args[0], prog, args + 2, eval);
}
if (list) {
Style s;
Stypat p;
char **v;
for (s = zstyles; s; s = s->next) {
if (list == 1) {
quotedzputs(s->name, stdout);
putchar('\n');
}
for (p = s->pats; p; p = p->next) {
if (list == 1)
printf("%s %s", (p->eval ? "(eval)" : " "), p->pat);
else {
printf("zstyle %s", (p->eval ? "-e " : ""));
quotedzputs(p->pat, stdout);
printf(" %s", s->name);
}
for (v = p->vals; *v; v++) {
putchar(' ');
quotedzputs(*v, stdout);
}
putchar('\n');
}
}
return 0;
}
switch (args[0][1]) {
case 'd': min = 0; max = -1; break;
case 's': min = 3; max = 4; break;
case 'b': min = 3; max = 3; break;
case 'a': min = 3; max = 3; break;
case 't': min = 2; max = -1; break;
case 'T': min = 2; max = -1; break;
case 'm': min = 3; max = 3; break;
case 'g': min = 1; max = 3; break;
default:
zwarnnam(nam, "invalid option: %s", args[0], 0);
return 1;
}
n = arrlen(args) - 1;
if (n < min) {
zwarnnam(nam, "not enough arguments", NULL, 0);
return 1;
} else if (max >= 0 && n > max) {
zwarnnam(nam, "too many arguments", NULL, 0);
return 1;
}
switch (args[0][1]) {
case 'd':
{
Style s;
if (args[1]) {
if (args[2]) {
char *pat = args[1];
for (args += 2; *args; args++) {
if ((s = getstyle(*args))) {
Stypat p, q;
for (q = NULL, p = s->pats; p;
q = p, p = p->next) {
if (!strcmp(p->pat, pat)) {
if (q)
q->next = p->next;
else
s->pats = p->next;
freestypat(p);
break;
}
}
}
}
} else {
Stypat p, q;
for (s = zstyles; s; s = s->next) {
for (q = NULL, p = s->pats; p; q = p, p = p->next) {
if (!strcmp(p->pat, args[1])) {
if (q)
q->next = p->next;
else
s->pats = p->next;
freestypat(p);
break;
}
}
}
}
} else
freeallstyles();
}
break;
case 's':
{
char **vals, *ret;
int val;
if ((vals = lookupstyle(args[1], args[2])) && vals[0]) {
ret = sepjoin(vals, (args[4] ? args[4] : " "), 0);
val = 0;
} else {
ret = ztrdup("");
val = 1;
}
setsparam(args[3], ret);
return val;
}
break;
case 'b':
{
char **vals, *ret;
int val;
if ((vals = lookupstyle(args[1], args[2])) &&
vals[0] && !vals[1] &&
(!strcmp(vals[0], "yes") ||
!strcmp(vals[0], "true") ||
!strcmp(vals[0], "on") ||
!strcmp(vals[0], "1"))) {
ret = "yes";
val = 0;
} else {
ret = "no";
val = 1;
}
setsparam(args[3], ztrdup(ret));
return val;
}
break;
case 'a':
{
char **vals, **ret;
int val;
if ((vals = lookupstyle(args[1], args[2]))) {
ret = zarrdup(vals);
val = 0;
} else {
char *dummy = NULL;
ret = zarrdup(&dummy);
val = 1;
}
setaparam(args[3], ret);
return val;
}
break;
case 't':
case 'T':
{
char **vals;
if ((vals = lookupstyle(args[1], args[2])) && vals[0]) {
if (args[3]) {
char **ap = args + 3, **p;
while (*ap) {
p = vals;
while (*p)
if (!strcmp(*ap, *p++))
return 0;
ap++;
}
return 1;
} else
return !(!strcmp(vals[0], "true") ||
!strcmp(vals[0], "yes") ||
!strcmp(vals[0], "on") ||
!strcmp(vals[0], "1"));
}
return (args[0][1] == 't' ? (vals ? 1 : 2) : 0);
}
break;
case 'm':
{
char **vals;
Patprog prog;
tokenize(args[3]);
if ((vals = lookupstyle(args[1], args[2])) &&
(prog = patcompile(args[3], PAT_STATIC, NULL))) {
while (*vals)
if (pattry(prog, *vals++))
return 0;
}
return 1;
}
break;
case 'g':
{
LinkList l = newlinklist();
int ret = 1;
Style s;
Stypat p;
if (args[2]) {
if (args[3]) {
if ((s = getstyle(args[3]))) {
for (p = s->pats; p; p = p->next) {
if (!strcmp(args[2], p->pat)) {
char **v = p->vals;
while (*v)
addlinknode(l, *v++);
ret = 0;
break;
}
}
}
} else {
for (s = zstyles; s; s = s->next)
for (p = s->pats; p; p = p->next)
if (!strcmp(args[2], p->pat)) {
addlinknode(l, s->name);
break;
}
ret = 0;
}
} else {
LinkNode n;
for (s = zstyles; s; s = s->next)
for (p = s->pats; p; p = p->next) {
for (n = firstnode(l); n; incnode(n))
if (!strcmp(p->pat, (char *) getdata(n)))
break;
if (!n)
addlinknode(l, p->pat);
}
ret = 0;
}
set_list_array(args[1], l);
return ret;
}
}
return 0;
}
/* Format stuff. */
/*
* One chunk of text, to allow recursive handling of ternary
* expressions in zformat -f output.
* instr The input string.
* specs The format specifiers, specs[c] is the string from c:string
* outp *outp is the start of the output string
* ousedp (*outp)[*ousedp] is where to write next
* olenp *olenp is the size allocated for *outp
* endchar Terminator character in addition to `\0' (may be '\0')
* skip If 1, don't output, just parse.
*/
static char *zformat_substring(char* instr, char **specs, char **outp,
int *ousedp, int *olenp, int endchar, int skip)
{
char *s;
for (s = instr; *s && *s != endchar; s++) {
if (*s == '%') {
int right, min = -1, max = -1, outl, testit;
char *spec, *start = s;
if ((right = (*++s == '-')))
s++;
if (*s >= '0' && *s <= '9') {
for (min = 0; *s >= '0' && *s <= '9'; s++)
min = (min * 10) + (int) STOUC(*s) - '0';
}
/* Ternary expressions */
testit = (STOUC(*s) == '(');
if (testit && s[1] == '-')
{
/* Allow %(-1... etc. */
right = 1;
s++;
}
if ((*s == '.' || testit) && s[1] >= '0' && s[1] <= '9') {
for (max = 0, s++; *s >= '0' && *s <= '9'; s++)
max = (max * 10) + (int) STOUC(*s) - '0';
}
else if (testit)
s++;
if (testit && STOUC(*s)) {
int actval, testval, endcharl;
/*
* One one number is useful for ternary expressions.
* Remember to put the sign back.
*/
testval = (min >= 0) ? min : (max >= 0) ? max : 0;
if (right)
testval *= -1;
if (specs[STOUC(*s)])
actval = (int)mathevali(specs[STOUC(*s)]);
else
actval = 0;
/* zero means values are equal, i.e. true */
actval -= testval;
/* careful about premature end of string */
if (!(endcharl = *++s))
return NULL;
/*
* Either skip true text and output false text, or
* vice versa... unless we are already skipping.
*/
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
olenp, endcharl, skip || actval)))
return NULL;
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
olenp, ')', skip || !actval)))
return NULL;
} else if (skip) {
continue;
} else if ((spec = specs[STOUC(*s)])) {
int len;
if ((len = strlen(spec)) > max && max >= 0)
len = max;
outl = (min >= 0 ? (min > len ? min : len) : len);
if (*ousedp + outl >= *olenp) {
int nlen = *olenp + outl + 128;
char *tmp = (char *) zhalloc(nlen);
memcpy(tmp, *outp, *olenp);
*olenp = nlen;
*outp = tmp;
}
if (len >= outl) {
memcpy(*outp + *ousedp, spec, outl);
*ousedp += outl;
} else {
int diff = outl - len;
if (right) {
while (diff--)
(*outp)[(*ousedp)++] = ' ';
memcpy(*outp + *ousedp, spec, len);
*ousedp += len;
} else {
memcpy(*outp + *ousedp, spec, len);
*ousedp += len;
while (diff--)
(*outp)[(*ousedp)++] = ' ';
}
}
} else {
int len = s - start + 1;
if (*ousedp + len >= *olenp) {
int nlen = *olenp + len + 128;
char *tmp = (char *) zhalloc(nlen);
memcpy(tmp, *outp, *olenp);
*olenp = nlen;
*outp = tmp;
}
memcpy(*outp + *ousedp, start, len);
*ousedp += len;
}
} else {
if (skip)
continue;
if (*ousedp + 1 >= *olenp) {
char *tmp = (char *) zhalloc((*olenp) << 1);
memcpy(tmp, *outp, *olenp);
*olenp <<= 1;
*outp = tmp;
}
(*outp)[(*ousedp)++] = *s;
}
}
return s;
}
static int
bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
char opt;
if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) {
zwarnnam(nam, "invalid argument: %s", args[0], 0);
return 1;
}
args++;
switch (opt) {
case 'f':
{
char **ap, *specs[256], *out;
int olen, oused = 0;
memset(specs, 0, 256 * sizeof(char *));
specs['%'] = "%";
specs[')'] = ")";
for (ap = args + 2; *ap; ap++) {
if (!ap[0][0] || ap[0][0] == '-' || ap[0][0] == '.' ||
(ap[0][0] >= '0' && ap[0][0] <= '9') ||
ap[0][1] != ':') {
zwarnnam(nam, "invalid argument: %s", *ap, 0);
return 1;
}
specs[STOUC(ap[0][0])] = ap[0] + 2;
}
out = (char *) zhalloc(olen = 128);
zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0);
out[oused] = '\0';
setsparam(args[0], ztrdup(out));
return 0;
}
break;
case 'a':
{
char **ap, *cp;
int nbc = 0, colon = 0, pre = 0, suf = 0;
for (ap = args + 2; *ap; ap++) {
for (nbc = 0, cp = *ap; *cp && *cp != ':'; cp++)
if (*cp == '\\' && cp[1])
cp++, nbc++;
if (*cp == ':' && cp[1]) {
int d;
colon++;
if ((d = cp - *ap - nbc) > pre)
pre = d;
if ((d = strlen(cp + 1)) > suf)
suf = d;
}
}
{
int sl = strlen(args[1]);
VARARR(char, buf, pre + suf + sl + 1);
char **ret, **rp, *copy, *cpp, oldc;
ret = (char **) zalloc((arrlen(args + 2) + 1) *
sizeof(char *));
memcpy(buf + pre, args[1], sl);
suf = pre + sl;
for (rp = ret, ap = args + 2; *ap; ap++) {
copy = dupstring(*ap);
for (cp = cpp = copy; *cp && *cp != ':'; cp++) {
if (*cp == '\\' && cp[1])
cp++;
*cpp++ = *cp;
}
oldc = *cpp;
*cpp = '\0';
if (((cpp == cp && oldc == ':') || *cp == ':') && cp[1]) {
memset(buf, ' ', pre);
memcpy(buf, copy, (cpp - copy));
strcpy(buf + suf, cp + 1);
*rp++ = ztrdup(buf);
} else
*rp++ = ztrdup(copy);
}
*rp = NULL;
setaparam(args[0], ret);
return 0;
}
}
break;
}
zwarnnam(nam, "invalid option: -%c", 0, opt);
return 1;
}
/* Zregexparse stuff. */
typedef struct {
char **match;
char **mbegin;
char **mend;
} MatchData;
static void
savematch(MatchData *m)
{
char **a;
queue_signals();
a = getaparam("match");
m->match = a ? zarrdup(a) : NULL;
a = getaparam("mbegin");
m->mbegin = a ? zarrdup(a) : NULL;
a = getaparam("mend");
m->mend = a ? zarrdup(a) : NULL;
unqueue_signals();
}
static void
restorematch(MatchData *m)
{
if (m->match)
setaparam("match", m->match);
else
unsetparam("match");
if (m->mbegin)
setaparam("mbegin", m->mbegin);
else
unsetparam("mbegin");
if (m->mend)
setaparam("mend", m->mend);
else
unsetparam("mend");
}
static void
freematch(MatchData *m)
{
if (m->match)
freearray(m->match);
if (m->mbegin)
freearray(m->mbegin);
if (m->mend)
freearray(m->mend);
}
typedef struct {
int cutoff;
char *pattern;
Patprog patprog;
char *guard;
char *action;
LinkList branches;
} RParseState;
typedef struct {
RParseState *state;
LinkList actions;
} RParseBranch;
typedef struct {
LinkList nullacts;
LinkList in;
LinkList out;
} RParseResult;
static char **rparseargs;
static LinkList rparsestates;
static int rparsealt(RParseResult *result, jmp_buf *perr);
static void
connectstates(LinkList out, LinkList in)
{
LinkNode outnode, innode, ln;
for (outnode = firstnode(out); outnode; outnode = nextnode(outnode)) {
RParseBranch *outbranch = getdata(outnode);
for (innode = firstnode(in); innode; innode = nextnode(innode)) {
RParseBranch *inbranch = getdata(innode);
RParseBranch *br = hcalloc(sizeof(*br));
br->state = inbranch->state;
br->actions = newlinklist();
for (ln = firstnode(outbranch->actions); ln; ln = nextnode(ln))
addlinknode(br->actions, getdata(ln));
for (ln = firstnode(inbranch->actions); ln; ln = nextnode(ln))
addlinknode(br->actions, getdata(ln));
addlinknode(outbranch->state->branches, br);
}
}
}
static int
rparseelt(RParseResult *result, jmp_buf *perr)
{
int l;
char *s = *rparseargs;
if (!s)
return 1;
switch (s[0]) {
case '/': {
RParseState *st;
RParseBranch *br;
char *pattern, *lookahead;
int patternlen, lookaheadlen = 0;
l = strlen(s);
if (!((2 <= l && s[l - 1] == '/') ||
(3 <= l && s[l - 2] == '/' && (s[l - 1] == '+' ||
s[l - 1] == '-'))))
return 1;
st = hcalloc(sizeof(*st));
st->branches = newlinklist();
st->cutoff = s[l - 1];
if (s[l - 1] == '/') {
pattern = s + 1;
patternlen = l - 2;
} else {
pattern = s + 1;
patternlen = l - 3;
}
rparseargs++;
if ((s = *rparseargs) && s[0] == '%' &&
2 <= (l = strlen(s)) && s[l - 1] == '%') {
rparseargs++;
lookahead = s + 1;
lookaheadlen = l - 2;
} else {
lookahead = NULL;
}
if (patternlen == 2 && !strncmp(pattern, "[]", 2))
st->pattern = NULL;
else {
char *cp;
int l = patternlen + 12; /* (#b)((#B)...)...* */
if(lookahead)
l += lookaheadlen + 4; /* (#B)... */
cp = st->pattern = hcalloc(l);
strcpy(cp, "(#b)((#B)");
cp += 9;
strcpy(cp, pattern);
cp += patternlen;
strcpy(cp, ")");
cp += 1;
if (lookahead) {
strcpy(cp, "(#B)");
cp += 4;
strcpy(cp, lookahead);
cp += lookaheadlen;
}
strcpy(cp, "*");
}
st->patprog = NULL;
if ((s = *rparseargs) && *s == '-') {
rparseargs++;
l = strlen(s);
st->guard = hcalloc(l);
memcpy(st->guard, s + 1, l - 1);
st->guard[l - 1] = '\0';
} else
st->guard = NULL;
if ((s = *rparseargs) && *s == ':') {
rparseargs++;
l = strlen(s);
st->action = hcalloc(l);
memcpy(st->action, s + 1, l - 1);
st->action[l - 1] = '\0';
} else
st->action = NULL;
result->nullacts = NULL;
result->in = newlinklist();
br = hcalloc(sizeof(*br));
br->state = st;
br->actions = newlinklist();
addlinknode(result->in, br);
result->out = newlinklist();
br = hcalloc(sizeof(*br));
br->state = st;
br->actions = newlinklist();
addlinknode(result->out, br);
break;
}
case '(':
if (s[1])
return 1;
rparseargs++;
if (rparsealt(result, perr))
longjmp(*perr, 2);
s = *rparseargs;
if (!s || s[0] != ')' || s[1] != '\0')
longjmp(*perr, 2);
rparseargs++;
break;
default:
return 1;
}
return 0;
}
static int
rparseclo(RParseResult *result, jmp_buf *perr)
{
if (rparseelt(result, perr))
return 1;
if (*rparseargs && !strcmp(*rparseargs, "#")) {
rparseargs++;
while (*rparseargs && !strcmp(*rparseargs, "#"))
rparseargs++;
connectstates(result->out, result->in);
result->nullacts = newlinklist();
}
return 0;
}
static void
prependactions(LinkList acts, LinkList branches)
{
LinkNode aln, bln;
for (bln = firstnode(branches); bln; bln = nextnode(bln)) {
RParseBranch *br = getdata(bln);
for (aln = lastnode(acts); aln != (LinkNode)acts; aln = prevnode(aln))
pushnode(br->actions, getdata(aln));
}
}
static void
appendactions(LinkList acts, LinkList branches)
{
LinkNode aln, bln;
for (bln = firstnode(branches); bln; bln = nextnode(bln)) {
RParseBranch *br = getdata(bln);
for (aln = firstnode(acts); aln; aln = nextnode(aln))
addlinknode(br->actions, getdata(aln));
}
}
static int
rparseseq(RParseResult *result, jmp_buf *perr)
{
int l;
char *s;
RParseResult sub;
result->nullacts = newlinklist();
result->in = newlinklist();
result->out = newlinklist();
while (1) {
if ((s = *rparseargs) && s[0] == '{' && s[(l = strlen(s)) - 1] == '}') {
char *action = hcalloc(l - 1);
LinkNode ln;
rparseargs++;
memcpy(action, s + 1, l - 2);
action[l - 2] = '\0';
if (result->nullacts)
addlinknode(result->nullacts, action);
for (ln = firstnode(result->out); ln; ln = nextnode(ln)) {
RParseBranch *br = getdata(ln);
addlinknode(br->actions, action);
}
}
else if (!rparseclo(&sub, perr)) {
connectstates(result->out, sub.in);
if (result->nullacts) {
prependactions(result->nullacts, sub.in);
insertlinklist(sub.in, lastnode(result->in), result->in);
}
if (sub.nullacts) {
appendactions(sub.nullacts, result->out);
insertlinklist(sub.out, lastnode(result->out), result->out);
} else
result->out = sub.out;
if (result->nullacts && sub.nullacts)
insertlinklist(sub.nullacts, lastnode(result->nullacts),
result->nullacts);
else
result->nullacts = NULL;
}
else
break;
}
return 0;
}
static int
rparsealt(RParseResult *result, jmp_buf *perr)
{
RParseResult sub;
if (rparseseq(result, perr))
return 1;
while (*rparseargs && !strcmp(*rparseargs, "|")) {
rparseargs++;
if (rparseseq(&sub, perr))
longjmp(*perr, 2);
if (!result->nullacts && sub.nullacts)
result->nullacts = sub.nullacts;
insertlinklist(sub.in, lastnode(result->in), result->in);
insertlinklist(sub.out, lastnode(result->out), result->out);
}
return 0;
}
static int
rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
{
LinkNode ln, lnn;
LinkList nexts;
LinkList nextslist;
RParseBranch *br;
RParseState *st = NULL;
int point1 = 0, point2 = 0;
setiparam(var1, point1);
setiparam(var2, point2);
if (!comp && !*subj && sm->nullacts) {
for (ln = firstnode(sm->nullacts); ln; ln = nextnode(ln)) {
char *action = getdata(ln);
if (action)
execstring(action, 1, 0);
}
return 0;
}
nextslist = newlinklist();
nexts = sm->in;
addlinknode(nextslist, nexts);
do {
MatchData match1, match2;
savematch(&match1);
for (ln = firstnode(nexts); ln; ln = nextnode(ln)) {
int i;
RParseState *next;
br = getdata(ln);
next = br->state;
if (next->pattern && !next->patprog) {
tokenize(next->pattern);
if (!(next->patprog = patcompile(next->pattern, 0, NULL)))
return 3;
}
if (next->pattern && pattry(next->patprog, subj) &&
(!next->guard || (execstring(next->guard, 1, 0), !lastval))) {
LinkNode aln;
char **mend;
int len;
queue_signals();
mend = getaparam("mend");
len = atoi(mend[0]);
unqueue_signals();
for (i = len; i; i--)
if (*subj++ == Meta)
subj++;
savematch(&match2);
restorematch(&match1);
for (aln = firstnode(br->actions); aln; aln = nextnode(aln)) {
char *action = getdata(aln);
if (action)
execstring(action, 1, 0);
}
restorematch(&match2);
point2 += len;
setiparam(var2, point2);
st = br->state;
nexts = st->branches;
if (next->cutoff == '-' || (next->cutoff == '/' && len)) {
nextslist = newlinklist();
point1 = point2;
setiparam(var1, point1);
}
addlinknode(nextslist, nexts);
break;
}
}
if (!ln)
freematch(&match1);
} while (ln);
if (!comp && !*subj)
for (ln = firstnode(sm->out); ln; ln = nextnode(ln)) {
br = getdata(ln);
if (br->state == st) {
for (ln = firstnode(br->actions); ln; ln = nextnode(ln)) {
char *action = getdata(ln);
if (action)
execstring(action, 1, 0);
}
return 0;
}
}
for (lnn = firstnode(nextslist); lnn; lnn = nextnode(lnn)) {
nexts = getdata(lnn);
for (ln = firstnode(nexts); ln; ln = nextnode(ln)) {
br = getdata(ln);
if (br->state->action)
execstring(br->state->action, 1, 0);
}
}
return empty(nexts) ? 2 : 1;
}
/*
usage: zregexparse [-c] var1 var2 string regex...
status:
0: matched
1: unmatched (all next state candidates are failed)
2: unmatched (there is no next state candidates)
3: regex parse error
*/
static int
bin_zregexparse(char *nam, char **args, Options ops, UNUSED(int func))
{
int oldextendedglob = opts[EXTENDEDGLOB];
char *var1 = args[0];
char *var2 = args[1];
char *subj = args[2];
int ret;
jmp_buf rparseerr;
RParseResult result;
opts[EXTENDEDGLOB] = 1;
rparseargs = args + 3;
pushheap();
rparsestates = newlinklist();
if (setjmp(rparseerr) || rparsealt(&result, &rparseerr) || *rparseargs) {
if (*rparseargs)
zwarnnam(nam, "invalid regex : %s", *rparseargs, 0);
else
zwarnnam(nam, "not enough regex arguments", NULL, 0);
ret = 3;
} else
ret = 0;
if (!ret)
ret = rmatch(&result, subj, var1, var2, OPT_ISSET(ops,'c'));
popheap();
opts[EXTENDEDGLOB] = oldextendedglob;
return ret;
}
typedef struct zoptdesc *Zoptdesc;
typedef struct zoptarr *Zoptarr;
typedef struct zoptval *Zoptval;
struct zoptdesc {
Zoptdesc next;
char *name;
int flags;
Zoptarr arr;
Zoptval vals, last;
};
#define ZOF_ARG 1
#define ZOF_OPT 2
#define ZOF_MULT 4
#define ZOF_SAME 8
struct zoptarr {
Zoptarr next;
char *name;
Zoptval vals, last;
int num;
};
struct zoptval {
Zoptval next, onext;
char *name;
char *arg;
char *str;
};
static Zoptdesc opt_descs;
static Zoptarr opt_arrs;
static Zoptdesc
get_opt_desc(char *name)
{
Zoptdesc p;
for (p = opt_descs; p; p = p->next)
if (!strcmp(name, p->name))
return p;
return NULL;
}
static Zoptdesc
lookup_opt(char *str)
{
Zoptdesc p;
for (p = opt_descs; p; p = p->next) {
if ((p->flags & ZOF_ARG) ? strpfx(p->name, str) : !strcmp(p->name, str))
return p;
}
return NULL;
}
static Zoptarr
get_opt_arr(char *name)
{
Zoptarr p;
for (p = opt_arrs; p; p = p->next)
if (!strcmp(name, p->name))
return p;
return NULL;
}
static void
add_opt_val(Zoptdesc d, char *arg)
{
Zoptval v = NULL;
char *n = dyncat("-", d->name);
int new = 0;
if (!(d->flags & ZOF_MULT))
v = d->vals;
if (!v) {
v = (Zoptval) zhalloc(sizeof(*v));
v->next = v->onext = NULL;
v->name = n;
new = 1;
}
v->arg = arg;
if ((d->flags & ZOF_ARG) && !(d->flags & (ZOF_OPT | ZOF_SAME))) {
v->str = NULL;
if (d->arr)
d->arr->num += (arg ? 2 : 1);
} else if (arg) {
char *s = (char *) zhalloc(strlen(d->name) + strlen(arg) + 2);
*s = '-';
strcpy(s + 1, d->name);
strcat(s, arg);
v->str = s;
if (d->arr)
d->arr->num += 1;
} else {
v->str = NULL;
if (d->arr)
d->arr->num += 1;
}
if (new) {
if (d->arr) {
if (d->arr->last)
d->arr->last->next = v;
else
d->arr->vals = v;
d->arr->last = v;
}
if (d->last)
d->last->onext = v;
else
d->vals = v;
d->last = v;
}
}
static int
bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
{
char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL, **cp, **np;
int del = 0, f, extract = 0, keep = 0;
Zoptdesc sopts[256], d;
Zoptarr a, defarr = NULL;
Zoptval v;
opt_descs = NULL;
opt_arrs = NULL;
memset(sopts, 0, 256 * sizeof(Zoptdesc));
while ((o = *args++)) {
if (*o == '-') {
switch (o[1]) {
case '\0':
o = NULL;
break;
case '-':
if (o[2])
args--;
o = NULL;
break;
case 'D':
if (o[2]) {
args--;
o = NULL;
break;
}
del = 1;
break;
case 'E':
if (o[2]) {
args--;
o = NULL;
break;
}
extract = 1;
break;
case 'K':
if (o[2]) {
args--;
o = NULL;
break;
}
keep = 1;
break;
case 'a':
if (defarr) {
zwarnnam(nam, "default array given more than once", NULL, 0);
return 1;
}
if (o[2])
n = o + 2;
else if (*args)
n = *args++;
else {
zwarnnam(nam, "missing array name", NULL, 0);
return 1;
}
defarr = (Zoptarr) zhalloc(sizeof(*defarr));
defarr->name = n;
defarr->num = 0;
defarr->vals = defarr->last = NULL;
defarr->next = NULL;
opt_arrs = defarr;
break;
case 'A':
if (o[2])
assoc = o + 2;
else if (*args)
assoc = *args++;
else {
zwarnnam(nam, "missing array name", NULL, 0);
return 1;
}
break;
}
if (!o) {
o = "";
break;
}
} else {
args--;
break;
}
}
if (!o) {
zwarnnam(nam, "missing option descriptions", NULL, 0);
return 1;
}
while ((o = dupstring(*args++))) {
if (!*o) {
zwarnnam(nam, "invalid option description: %s", o, 0);
return 1;
}
f = 0;
for (p = o; *p; p++) {
if (*p == '\\' && p[1])
p++;
else if (*p == '+') {
f |= ZOF_MULT;
*p = '\0';
p++;
break;
} else if (*p == ':' || *p == '=')
break;
}
if (*p == ':') {
f |= ZOF_ARG;
*p = '\0';
if (*++p == ':') {
p++;
f |= ZOF_OPT;
}
if (*p == '-') {
p++;
f |= ZOF_SAME;
}
}
a = NULL;
if (*p == '=') {
*p++ = '\0';
if (!(a = get_opt_arr(p))) {
a = (Zoptarr) zhalloc(sizeof(*a));
a->name = p;
a->num = 0;
a->vals = a->last = NULL;
a->next = opt_arrs;
opt_arrs = a;
}
} else if (*p) {
zwarnnam(nam, "invalid option description: %s", args[-1], 0);
return 1;
} else if (!(a = defarr) && !assoc) {
zwarnnam(nam, "no default array defined: %s", args[-1], 0);
return 1;
}
for (p = n = o; *p; p++) {
if (*p == '\\' && p[1])
p++;
*n++ = *p;
}
if (get_opt_desc(o)) {
zwarnnam(nam, "option defined more than once: %s", o, 0);
return 1;
}
d = (Zoptdesc) zhalloc(sizeof(*d));
d->name = o;
d->flags = f;
d->arr = a;
d->next = opt_descs;
d->vals = d->last = NULL;
opt_descs = d;
if (!o[1])
sopts[STOUC(*o)] = d;
}
np = cp = pp = ((extract && del) ? arrdup(pparams) : pparams);
for (; (o = *pp); pp++) {
if (*o != '-') {
if (extract) {
if (del)
*cp++ = o;
continue;
} else
break;
}
if (!o[1] || (o[1] == '-' && !o[2])) {
if (del && extract)
*cp++ = o;
pp++;
break;
}
if (!(d = lookup_opt(o + 1))) {
while (*++o) {
if (!(d = sopts[STOUC(*o)])) {
o = NULL;
break;
}
if (d->flags & ZOF_ARG) {
if (o[1]) {
add_opt_val(d, o + 1);
break;
} else if (!(d->flags & ZOF_OPT)) {
if (!pp[1]) {
zwarnnam(nam, "missing argument for option: %s",
d->name, 0);
return 1;
}
add_opt_val(d, *++pp);
} else
add_opt_val(d, NULL);
} else
add_opt_val(d, NULL);
}
if (!o) {
if (extract) {
if (del)
*cp++ = *pp;
continue;
} else
break;
}
} else {
if (d->flags & ZOF_ARG) {
char *e = o + strlen(d->name) + 1;
if (*e)
add_opt_val(d, e);
else if (!(d->flags & ZOF_OPT)) {
if (!pp[1]) {
zwarnnam(nam, "missing argument for option: %s",
d->name, 0);
return 1;
}
add_opt_val(d, *++pp);
} else
add_opt_val(d, NULL);
} else
add_opt_val(d, NULL);
}
}
if (extract && del)
while (*pp)
*cp++ = *pp++;
for (a = opt_arrs; a; a = a->next) {
if (!keep || a->num) {
aval = (char **) zalloc((a->num + 1) * sizeof(char *));
for (ap = aval, v = a->vals; v; ap++, v = v->next) {
if (v->str)
*ap = ztrdup(v->str);
else {
*ap = ztrdup(v->name);
if (v->arg)
*++ap = ztrdup(v->arg);
}
}
*ap = NULL;
setaparam(a->name, aval);
}
}
if (assoc) {
int num;
for (num = 0, d = opt_descs; d; d = d->next)
if (d->vals)
num++;
if (!keep || num) {
aval = (char **) zalloc(((num * 2) + 1) * sizeof(char *));
for (ap = aval, d = opt_descs; d; d = d->next) {
if (d->vals) {
*ap++ = n = (char *) zalloc(strlen(d->name) + 2);
*n = '-';
strcpy(n + 1, d->name);
for (num = 1, v = d->vals; v; v = v->onext) {
num += (v->arg ? strlen(v->arg) : 0);
if (v->next)
num++;
}
*ap++ = n = (char *) zalloc(num);
for (v = d->vals; v; v = v->onext) {
if (v->arg) {
strcpy(n, v->arg);
n += strlen(v->arg);
}
*n = ' ';
}
*n = '\0';
}
}
*ap = NULL;
sethparam(assoc, aval);
}
}
if (del) {
if (extract) {
*cp = NULL;
freearray(pparams);
pparams = zarrdup(np);
} else {
pp = zarrdup(pp);
freearray(pparams);
pparams = pp;
}
}
return 0;
}
static struct builtin bintab[] = {
BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL),
BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL),
BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL),
BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, NULL, NULL),
};
/**/
int
setup_(UNUSED(Module m))
{
zstyles = zlstyles = NULL;
return 0;
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
finish_(UNUSED(Module m))
{
freeallstyles();
return 0;
}
#endif //__SYMBIAN32__