/* From Plan 9 to Unix */ char* exportname(char* name) { Rune r; int nr; char *uxname; char *up; if (name == 0 || (utfrune(name, altspc) == 0 && utfrune(name,altlparen) == 0 && utfrune(name,altrparen) == 0 && utfrune(name,altamp) == 0 && utfrune(name,altquote) == 0)) return name; up = uxname = emalloc(strlen(name) + 1); names[nnames++] = uxname; while(*name != 0){ nr = chartorune(&r, name); if (r == altspc) r = ' '; if (r == altlparen) r = '('; if (r == altrparen) r = ')'; if (r == altamp) r = '&'; if (r == altquote) r = '\''; up += runetochar(up, &r); name += nr; } *up = 0; return uxname; }
int main (int argc, char *argu[]) { int n; #include "argPrae.c" #include "argPost.c" findFSRS (0); for (;;) { char *x, *y, *z, **argv; int ii; n = afgetln (&x, stdin); if (n == 0) break; if (n < 0) { if (errno) eprintf ("%s:", argu[0]); else return 0; } z = x; argv = malloc (sizeof (char *) * (argc + 1)); if (!argv) eprintf ("%s:", argu[0]); for (ii = 0; ii < argc - 1; ii++) argv[ii] = argu[ii + 1]; if (ii == 0) argv[ii++] = "echo"; /* ii now index of xargument in argv */ for (; x; x = y) { int pid, c; y = utfrune (x, fs); if (y) { Rune _; int l = chartorune (&_, y); y[0] = 0; y += l; } else { y = utfrune (x, rs); if (y) y[0] = 0; y = 0; } argv[ii] = x; argv[ii + 1] = 0; pid = fork (); if (pid == 0) { execvp (argv[0], argv); eprintf ("%s: %s:", argu[0], argv[0]); } waitpid (pid, &c, 0); if (c != 0) return 1; } } }
int assemble(char *file) { char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } of = create(outfile, OWRITE, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; pinit(file); Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); if(nerrors) { cclean(); return nerrors; } Bprint(&obuf, "\n!\n"); pass = 2; outhist(); pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); return nerrors; }
static char* etoken(char *t, char *sep) { int quoting; /* move to end of next token */ quoting = 0; while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){ if(*t != '\''){ t++; continue; } /* *t is a quote */ if(!quoting){ quoting = 1; t++; continue; } /* quoting and we're on a quote */ if(t[1] != '\''){ /* end of quoted section; absorb closing quote */ t++; quoting = 0; continue; } /* doubled quote; fold one quote into two */ t += 2; } return t; }
/* * Return a tube for name segmentname!tubename, * creating any of them if mkit is true and it is not found. */ Tube* namedtube(char *name, ulong msz, int n, int mkit) { char *dir, *tname; Tdir *tl; Tube *t; dumpdir("dir before namedtube"); name = strdup(name); if(name == nil) return nil; tname = utfrune(name, '!'); if(tname == nil){ dir = "tubes"; tname = name; }else{ dir = name; *tname++ = 0; } t = nil; tl = dirlookup(dir, mkit); if(tl != nil) t = tubelookup(tl, tname, msz, n, mkit); free(name); return t; }
int getfields(char *str, char **args, int max, int mflag, char *set) { Rune r; int nr, intok, narg; if(max <= 0) return 0; narg = 0; args[narg] = str; if(!mflag) narg++; intok = 0; for(;; str += nr) { nr = chartorune(&r, str); if(r == 0) break; if(utfrune(set, r)) { if(narg >= max) break; *str = 0; intok = 0; args[narg] = str + nr; if(!mflag) narg++; } else { if(!intok && mflag) narg++; intok = 1; } } return narg; }
/* * convert command to run properly on the remote machine * need to escape the quotes so they don't get stripped */ int mkcmd(char *cmd, char *buf, int len) { char *p; int n, m; n = sizeof "exec rc -c '" -1; if(n >= len) return 0; strcpy(buf, "exec rc -c '"); while(p = utfrune(cmd, L'\'')){ p++; m = p - cmd; if(n + m + 1 >= len) return 0; strncpy(&buf[n], cmd, m); n += m; buf[n++] = '\''; cmd = p; } m = strlen(cmd); if(n + m + sizeof "'</dev/null>/dev/null>[2=1]" >= len) return 0; strcpy(&buf[n], cmd); strcpy(&buf[n+m], "'</dev/null>/dev/null>[2=1]"); return 1; }
int call(char *host) { char *na, *p; na = netmkaddr(host, 0, "rexexec"); p = utfrune(na, L'!'); if(!p) return -1; p = utfrune(p+1, L'!'); if(!p) return -1; if(strcmp(p, "!rexexec") != 0) return -2; return dial(na, 0, 0, 0); }
int needsrcquote(int c) { if(c <= ' ') return 1; if(utfrune("`^#*[]=|\\?${}()'<>&;", c)) return 1; return 0; }
/* * search a string for unescaped characters in a pattern set */ static char * shcharin(char *cp, char *pat) { Rune r; int n, vargen; vargen = 0; while(*cp){ n = chartorune(&r, cp); switch(r){ case '\\': /* skip escaped char */ cp += n; n = chartorune(&r, cp); break; case '\'': /* skip quoted string */ case '"': cp = squote(cp+1, r); /* n must = 1 */ if(!cp) return 0; break; case '$': if(*(cp+1) == '{') vargen = 1; break; case '}': if(vargen) vargen = 0; else if(utfrune(pat, r)) return cp; break; default: if(vargen == 0 && utfrune(pat, r)) return cp; break; } cp += n; } if(vargen){ SYNERR(-1); fprint(2, "missing closing } in pattern generator\n"); } return 0; }
int validUserName(char* name) { Rune *r; static Rune invalid[] = L"#:,()"; for(r = invalid; *r != '\0'; r++){ if(utfrune(name, *r)) return 0; } return 1; }
static void outzfile(Biobuf *b, char *p) { char *q, *q2; while(p) { q = utfrune(p, '/'); if(windows) { q2 = utfrune(p, '\\'); if(q2 && (!q || q2 < q)) q = q2; } if(!q) { zfile(b, p, strlen(p)); return; } if(q > p) zfile(b, p, q-p); p = q + 1; } }
void touch(char *name) { Bprint(&bout, "touch(%s)\n", name); if(nflag) return; if(utfrune(name, '(')) atouch(name); /* archive */ else if(chgtime(name) < 0) { perror(name); Exit(); } }
int cmdexec(File *f, Cmd *cp) { int i; Addr *ap; Address a; if(f && f->unread) load(f); if(f==0 && (cp->addr==0 || cp->addr->type!='"') && !utfrune("bBnqUXY!", cp->cmdc) && cp->cmdc!=('c'|0x100) && !(cp->cmdc=='D' && cp->ctext)) error(Enofile); i = lookup(cp->cmdc); if(i >= 0 && cmdtab[i].defaddr != aNo){ if((ap=cp->addr)==0 && cp->cmdc!='\n'){ cp->addr = ap = newaddr(); ap->type = '.'; if(cmdtab[i].defaddr == aAll) ap->type = '*'; }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){ ap->next = newaddr(); ap->next->type = '.'; if(cmdtab[i].defaddr == aAll) ap->next->type = '*'; } if(cp->addr){ /* may be false for '\n' (only) */ static Address none = {0,0,0}; if(f) addr = address(ap, f->dot, 0); else /* a " */ addr = address(ap, none, 0); f = addr.f; } } current(f); switch(cp->cmdc){ case '{': a = cp->addr? address(cp->addr, f->dot, 0): f->dot; for(cp = cp->ccmd; cp; cp = cp->next){ a.f->dot = a; cmdexec(a.f, cp); } break; default: i=(*cmdtab[i].fn)(f, cp); return i; } return 1; }
String * collecttoken(char *end) { String *s = newstring(0); int c; while((c=nextc())==' ' || c=='\t') Straddc(s, getch()); /* blanks significant for getname() */ while((c=getch())>0 && utfrune(end, c)==0) Straddc(s, c); if(c != '\n') atnl(); return s; }
char* getword(char *buf, Rune delim, char *error, int line) { char *p; p = utfrune(buf, delim); if(p == 0) { if(error) print("cmd_users: %s line %d\n", error, line); return 0; } *p = '\0'; return p+1; }
/* Return false if 'c' is obviously not an alphanumeric character, * or if it is in the stoplist. */ static Bool okchar(int c, char *stoplist) { /* * Hard to get absolutely right. Use what we know about ASCII * and assume anything above the Latin control characters is * potentially an alphanumeric. */ if(c <= ' ') return false; if(0x7F<=c && c<=0xA0) return false; if(utfrune(stoplist, c)) return false; return 1; }
int tokenize(char *s, char **args, int maxargs) { int nargs; for(nargs=0; nargs<maxargs; nargs++){ while(*s!='\0' && utfrune(qsep, *s)!=nil) s++; if(*s == '\0') break; args[nargs] = s; s = qtoken(s, qsep); } return nargs; }
void mkdirs(char *name, char *namep) { char buf[2*LEN], *p; int fd; strcpy(buf, name); for(p = &buf[namep - name]; p = utfrune(p, '/'); p++){ if(p[1] == '\0') return; *p = 0; fd = create(buf, OREAD, 0775|DMDIR); close(fd); *p = '/'; } }
int alnum(int c) { /* * Hard to get absolutely right. Use what we know about ASCII * and assume anything above the Latin control characters is * potentially an alphanumeric. */ if(c<=' ') return 0; if(0x7F<=c && c<=0xA0) return 0; if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) return 0; return 1; }
int gettokens(char *s, char **args, int maxargs, char *sep) { int nargs; for(nargs=0; nargs<maxargs; nargs++){ while(*s!='\0' && utfrune(sep, *s)!=nil) *s++ = '\0'; if(*s == '\0') break; args[nargs] = s; s = etoken(s, sep); } return nargs; }
/* * Return pointer to first occurrence of s2 in s1, * 0 if none */ char* utfutf(char *s1, char *s2) { char *p; int32_t f, n1, n2; Rune r; n1 = chartorune(&r, s2); f = r; if(f <= Runesync) /* represents self */ return strstr(s1, s2); n2 = strlen(s2); for(p=s1; p=utfrune(p, f); p+=n1) if(strncmp(p, s2, n2) == 0) return p; return 0; }
char * utfutf(const char *s, const char *t) { const char *p, *q; Rune r0, r1, r2; int n, m; for(chartorune(&r0, t); (s = utfrune(s, r0)); s++) { for(p = s, q = t; *q && *p; p += n, q += m) { n = chartorune(&r1, p); m = chartorune(&r2, q); if(r1 != r2) break; } if(!*q) return (char *)s; } return NULL; }
int isalnum(Rune c) { /* * Hard to get absolutely right. Use what we know about ASCII * and assume anything above the Latin control characters is * potentially an alphanumeric. * * Treat 0xA0 (non-breaking space) as a special alphanumeric * character [sape] */ if(c <= ' ') return FALSE; if(0x7F<=c && c<0xA0) return FALSE; if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) return FALSE; return TRUE; }
void outhist(Biobuf *b) { Hist *h; char *p, *q, *op; int n; for(h = hist; h != H; h = h->link) { p = h->name; op = 0; if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') { op = p; p = pathname; } while(p) { q = utfrune(p, '/'); if(q) { n = q-p; if(n == 0) n = 1; // leading "/" q++; } else { n = strlen(p); q = 0; } if(n) zfile(b, p, n); p = q; if(p == 0 && op) { p = op; op = 0; } } zhist(b, h->line, h->offset); } }
ulong timeof(char *name, int force) { Symtab *sym; ulong t; if(utfrune(name, '(')) return atimeof(force, name); /* archive */ if(force) return mtime(name); sym = symlook(name, S_TIME, 0); if (sym) return sym->u.value; /* uggh */ t = mkmtime(name, 0); if(t == 0) return 0; symlook(name, S_TIME, (void*)t); /* install time in cache */ return t; }
static char* qtoken(char *s, char *sep) { int quoting; char *t; quoting = 0; t = s; /* s is output string, t is input string */ while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){ if(*t != '\''){ *s++ = *t++; continue; } /* *t is a quote */ if(!quoting){ quoting = 1; t++; continue; } /* quoting and we're on a quote */ if(t[1] != '\''){ /* end of quoted section; absorb closing quote */ t++; quoting = 0; continue; } /* doubled quote; fold one quote into two */ t++; *s++ = *t++; } if(*s != '\0'){ *s = '\0'; if(t == s) t++; } return t; }
int inmesg(Tmesg type) { Rune buf[1025]; char cbuf[64]; int i, m; short s; long l, l1; vlong v; File *f; Posn p0, p1, p; Range r; String *str; char *c, *wdir; Rune *rp; Plumbmsg *pm; if(type > TMAX) panic("inmesg"); journal(0, tname[type]); inp = indata; switch(type){ case -1: panic("rcv error"); default: fprint(2, "unknown type %d\n", type); panic("rcv unknown"); case Tversion: tversion = inshort(); journaln(0, tversion); break; case Tstartcmdfile: v = invlong(); /* for 64-bit pointers */ journaln(0, v); Strdupl(&genstr, samname); cmd = newfile(); cmd->unread = 0; outTsv(Hbindname, cmd->tag, v); outTs(Hcurrent, cmd->tag); logsetname(cmd, &genstr); cmd->rasp = listalloc('P'); cmd->mod = 0; if(cmdstr.n){ loginsert(cmd, 0L, cmdstr.s, cmdstr.n); Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); } fileupdate(cmd, FALSE, TRUE); outT0(Hunlock); break; case Tcheck: /* go through whichfile to check the tag */ outTs(Hcheck, whichfile(inshort())->tag); break; case Trequest: f = whichfile(inshort()); p0 = inlong(); p1 = p0+inshort(); journaln(0, p0); journaln(0, p1-p0); if(f->unread) panic("Trequest: unread"); if(p1>f->b.nc) p1 = f->b.nc; if(p0>f->b.nc) /* can happen e.g. scrolling during command */ p0 = f->b.nc; if(p0 == p1){ i = 0; r.p1 = r.p2 = p0; }else{ r = rdata(f->rasp, p0, p1-p0); i = r.p2-r.p1; bufread(&f->b, r.p1, buf, i); } buf[i]=0; outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); break; case Torigin: s = inshort(); l = inlong(); l1 = inlong(); journaln(0, l1); lookorigin(whichfile(s), l, l1); break; case Tstartfile: termlocked++; f = whichfile(inshort()); if(!f->rasp) /* this might be a duplicate message */ f->rasp = listalloc('P'); current(f); outTsv(Hbindname, f->tag, invlong()); /* for 64-bit pointers */ outTs(Hcurrent, f->tag); journaln(0, f->tag); if(f->unread) load(f); else{ if(f->b.nc>0){ rgrow(f->rasp, 0L, f->b.nc); outTsll(Hgrow, f->tag, 0L, f->b.nc); } outTs(Hcheck0, f->tag); moveto(f, f->dot.r); } break; case Tworkfile: i = inshort(); f = whichfile(i); current(f); f->dot.r.p1 = inlong(); f->dot.r.p2 = inlong(); f->tdot = f->dot.r; journaln(0, i); journaln(0, f->dot.r.p1); journaln(0, f->dot.r.p2); break; case Ttype: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); journal(0, (char*)inp); str = tmpcstr((char*)inp); i = str->n; loginsert(f, p0, str->s, str->n); if(fileupdate(f, FALSE, FALSE)) seq++; if(f==cmd && p0==f->b.nc-i && i>0 && str->s[i-1]=='\n'){ freetmpstr(str); termlocked++; termcommand(); }else freetmpstr(str); f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */ f->tdot = f->dot.r; break; case Tcut: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); logdelete(f, p0, p1); if(fileupdate(f, FALSE, FALSE)) seq++; f->dot.r.p1 = f->dot.r.p2 = p0; f->tdot = f->dot.r; /* terminal knows the value of dot already */ break; case Tpaste: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); for(l=0; l<snarfbuf.nc; l+=m){ m = snarfbuf.nc-l; if(m>BLOCKSIZE) m = BLOCKSIZE; bufread(&snarfbuf, l, genbuf, m); loginsert(f, p0, tmprstr(genbuf, m)->s, m); } if(fileupdate(f, FALSE, TRUE)) seq++; f->dot.r.p1 = p0; f->dot.r.p2 = p0+snarfbuf.nc; f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */ telldot(f); outTs(Hunlockfile, f->tag); break; case Tsnarf: i = inshort(); p0 = inlong(); p1 = inlong(); snarf(whichfile(i), p0, p1, &snarfbuf, 0); break; case Tstartnewfile: v = invlong(); Strdupl(&genstr, empty); f = newfile(); f->rasp = listalloc('P'); outTsv(Hbindname, f->tag, v); logsetname(f, &genstr); outTs(Hcurrent, f->tag); current(f); load(f); break; case Twrite: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); addr.r.p1 = 0; addr.r.p2 = f->b.nc; if(f->name.s[0] == 0) error(Enoname); Strduplstr(&genstr, &f->name); writef(f); break; case Tclose: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); current(f); trytoclose(f); /* if trytoclose fails, will error out */ delete(f); break; case Tlook: f = whichfile(inshort()); termlocked++; p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); setgenstr(f, p0, p1); for(l = 0; l<genstr.n; l++){ i = genstr.s[l]; if(utfrune(".*+?(|)\\[]^$", i)){ str = tmpcstr("\\"); Strinsert(&genstr, str, l++); freetmpstr(str); } } Straddc(&genstr, '\0'); nextmatch(f, &genstr, p1, 1); moveto(f, sel.p[0]); break; case Tsearch: termlocked++; if(curfile == 0) error(Enofile); if(lastpat.s[0] == 0) panic("Tsearch"); nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); moveto(curfile, sel.p[0]); break; case Tsend: termlocked++; inshort(); /* ignored */ p0 = inlong(); p1 = inlong(); setgenstr(cmd, p0, p1); bufreset(&snarfbuf); bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n); outTl(Hsnarflen, genstr.n); if(genstr.s[genstr.n-1] != '\n') Straddc(&genstr, '\n'); loginsert(cmd, cmd->b.nc, genstr.s, genstr.n); fileupdate(cmd, FALSE, TRUE); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->b.nc; telldot(cmd); termcommand(); break; case Tdclick: f = whichfile(inshort()); p1 = inlong(); doubleclick(f, p1); f->tdot.p1 = f->tdot.p2 = p1; telldot(f); outTs(Hunlockfile, f->tag); break; case Tstartsnarf: if (snarfbuf.nc <= 0) { /* nothing to export */ outTs(Hsetsnarf, 0); break; } c = 0; i = 0; m = snarfbuf.nc; if(m > SNARFSIZE) { m = SNARFSIZE; dprint("?warning: snarf buffer truncated\n"); } rp = malloc(m*sizeof(Rune)); if(rp){ bufread(&snarfbuf, 0, rp, m); c = Strtoc(tmprstr(rp, m)); free(rp); i = strlen(c); } outTs(Hsetsnarf, i); if(c){ Write(1, c, i); free(c); } else dprint("snarf buffer too long\n"); break; case Tsetsnarf: m = inshort(); if(m > SNARFSIZE) error(Etoolong); c = malloc(m+1); if(c){ for(i=0; i<m; i++) c[i] = rcvchar(); c[m] = 0; str = tmpcstr(c); free(c); bufreset(&snarfbuf); bufinsert(&snarfbuf, (Posn)0, str->s, str->n); freetmpstr(str); outT0(Hunlock); } break; case Tack: waitack = 0; break; case Tplumb: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); pm = emalloc(sizeof(Plumbmsg)); pm->src = strdup("sam"); pm->dst = 0; /* construct current directory */ c = Strtoc(&f->name); if(c[0] == '/') pm->wdir = c; else{ wdir = emalloc(1024); getwd(wdir, 1024); pm->wdir = emalloc(1024); snprint(pm->wdir, 1024, "%s/%s", wdir, c); cleanname(pm->wdir); free(wdir); free(c); } c = strrchr(pm->wdir, '/'); if(c) *c = '\0'; pm->type = strdup("text"); if(p1 > p0) pm->attr = nil; else{ p = p0; while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i!='\t' && i!='\n') p0--; while(p1<f->b.nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n') p1++; sprint(cbuf, "click=%ld", p-p0); pm->attr = plumbunpackattr(cbuf); } if(p0==p1 || p1-p0>=BLOCKSIZE){ plumbfree(pm); break; } setgenstr(f, p0, p1); pm->data = Strtoc(&genstr); pm->ndata = strlen(pm->data); c = plumbpack(pm, &i); if(c != 0){ outTs(Hplumb, i); Write(1, c, i); free(c); } plumbfree(pm); break; case Texit: exits(0); } return TRUE; }
int assemble(char *file) { char ofile[100], incfile[20], *p; int i, of; strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } p = getenv("INCLUDE"); if(p) { setinclude(p); } else { if(systemtype(Plan9)) { sprint(incfile,"/%s/include", thestring); setinclude(strdup(incfile)); } } of = mycreat(outfile, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); if(nerrors) { cclean(); return nerrors; } pass = 2; outhist(); pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); return nerrors; }
/* * return 0 if no match * >0 if a match * <0 if we ran out of _relist space */ static int regexec1(Reprog *progp, /* program to run */ char *bol, /* string to run machine on */ Resub *mp, /* subexpression elements */ int ms, /* number of elements at mp */ Reljunk *j ) { int flag=0; Reinst *inst; Relist *tlp; char *s; int i, checkstart; Rune r, *rp, *ep; int n; Relist* tl; /* This list, next list */ Relist* nl; Relist* tle; /* ends of this and next list */ Relist* nle; int match; char *p; match = 0; checkstart = j->starttype; if(mp) for(i=0; i<ms; i++) { mp[i].s.sp = 0; mp[i].e.ep = 0; } j->relist[0][0].inst = 0; j->relist[1][0].inst = 0; /* Execute machine once for each character, including terminal NUL */ s = j->starts; do{ /* fast check for first char */ if(checkstart) { switch(j->starttype) { case RUNE: p = utfrune(s, j->startchar); if(p == 0 || s == j->eol) return match; s = p; break; case BOL: if(s == bol) break; p = utfrune(s, '\n'); if(p == 0 || s == j->eol) return match; s = p+1; break; } } r = *(uchar*)s; if(r < Runeself) n = 1; else n = chartorune(&r, s); /* switch run lists */ tl = j->relist[flag]; tle = j->reliste[flag]; nl = j->relist[flag^=1]; nle = j->reliste[flag]; nl->inst = 0; /* Add first instruction to current list */ if(match == 0) _renewemptythread(tl, progp->startinst, ms, s); /* Execute machine until current list is empty */ for(tlp=tl; tlp->inst; tlp++){ /* assignment = */ for(inst = tlp->inst; ; inst = inst->u2.next){ switch(inst->type){ case RUNE: /* regular character */ if(inst->u1.r == r){ if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) return -1; } break; case LBRA: tlp->se.m[inst->u1.subid].s.sp = s; continue; case RBRA: tlp->se.m[inst->u1.subid].e.ep = s; continue; case ANY: if(r != '\n') if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) return -1; break; case ANYNL: if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) return -1; break; case BOL: if(s == bol || *(s-1) == '\n') continue; break; case EOL: if(s == j->eol || r == 0 || r == '\n') continue; break; case CCLASS: ep = inst->u1.cp->end; for(rp = inst->u1.cp->spans; rp < ep; rp += 2) if(r >= rp[0] && r <= rp[1]){ if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) return -1; break; } break; case NCCLASS: ep = inst->u1.cp->end; for(rp = inst->u1.cp->spans; rp < ep; rp += 2) if(r >= rp[0] && r <= rp[1]) break; if(rp == ep) if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) return -1; break; case OR: /* evaluate right choice later */ if(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle) return -1; /* efficiency: advance and re-evaluate */ continue; case END: /* Match! */ match = 1; tlp->se.m[0].e.ep = s; if(mp != 0) _renewmatch(mp, ms, &tlp->se); break; } break; } } if(s == j->eol) break; checkstart = j->starttype && nl->inst==0; s += n; }while(r); return match; }