diff -Nru /n/sources/plan9/sys/src/cmd/rc/code.c /sys/src/cmd/rc/code.c
--- /n/sources/plan9/sys/src/cmd/rc/code.c Thu Aug 14 18:37:56 2008
+++ /sys/src/cmd/rc/code.c Wed Aug 17 00:00:00 2016
@@ -2,7 +2,7 @@
#include "io.h"
#include "exec.h"
#include "fns.h"
-#include "getflags.h"
+
#define c0 t->child[0]
#define c1 t->child[1]
#define c2 t->child[2]
diff -Nru /n/sources/plan9/sys/src/cmd/rc/exec.c /sys/src/cmd/rc/exec.c
--- /n/sources/plan9/sys/src/cmd/rc/exec.c Thu Jun 13 23:21:27 2013
+++ /sys/src/cmd/rc/exec.c Wed Aug 17 00:00:00 2016
@@ -1,12 +1,15 @@
#include "rc.h"
-#include "getflags.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
+
+char flagset[] = "<flag>"; /* anything non-nil will do */
+char *flag[NFLAG];
+
/*
* Start executing the given code at the given pc with the given redirection
*/
-char *argv0="rc";
+char *argv0;
void
start(code *c, int pc, var *local)
@@ -113,6 +116,8 @@
newvar(char *name, var *next)
{
var *v = new(var);
+
+ assert(name != nil);
v->name = name;
v->val = 0;
v->fn = 0;
@@ -121,62 +126,99 @@
v->next = next;
return v;
}
+
+/* fabricate bootstrap code (*=(argv);. /rc/lib/rcmain $*; exit) */
+static void
+loadboot(code *base, int nel, char *rcmain)
+{
+ code *bs;
+
+ bs = base;
+ bs++->i = 1; /* reference count */
+ bs++->f = Xmark; /* "* = $*" */
+ bs++->f = Xword;
+ bs++->s="*";
+ bs++->f = Xassign;
+ bs++->f = Xmark;
+ bs++->f = Xmark;
+ bs++->f = Xword;
+ bs++->s="*";
+ bs++->f = Xdol;
+ bs++->f = Xword;
+ bs++->s = rcmain; /* ". /rc/lib/rcmain $*" */
+ bs++->f = Xword;
+ bs++->s=".";
+ bs++->f = Xsimple;
+ bs++->f = Xexit; /* exit */
+ bs++->i = 0; /* not reached */
+ if (bs > base + nel)
+ panic("bootstrap array too small", 0);
+}
+
+void
+usage(void)
+{
+ pfmt(err, "Usage: rc [-srdiIlxepvV] [-c arg] [-m command] "
+ "[file [arg ...]]\n");
+ Exit("bad flags");
+}
+
/*
* get command line flags, initialize keywords & traps.
* get values from environment.
* set $pid, $cflag, $*
- * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*)
+ * fabricate bootstrap code and start it
* start interpreting code
*/
-
void
main(int argc, char *argv[])
{
code bootstrap[17];
- char num[12], *rcmain;
+ char num[12];
int i;
- argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
- if(argc==-1)
- usage("[file [arg ...]]");
- if(argv[0][0]=='-')
+
+ err = openfd(2);
+ ARGBEGIN {
+ case 'd': case 'e': case 'i': case 'l':
+ case 'p': case 'r': case 's': case 'v':
+ case 'x': case 'I': case 'V':
+ flag[ARGC()] = flagset;
+ break;
+ case 'c':
+ case 'm':
+ if (flag[ARGC()])
+ usage();
+ flag[ARGC()] = EARGF(usage());
+ break;
+ default:
+ usage();
+ break;
+ } ARGEND
+ if(argc < 0)
+ usage();
+ if(argv0 == nil)
+ argv0 = "rc";
+ if(argv0[0]=='-') /* login shell? */
flag['l'] = flagset;
if(flag['I'])
flag['i'] = 0;
- else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
- rcmain = flag['m']?flag['m'][0]:Rcmain;
- err = openfd(2);
+ else if(flag['i']==0 && argc==0 && Isatty(0))
+ flag['i'] = flagset; /* force interactive */
+
kinit();
Trapinit();
Vinit();
inttoascii(num, mypid = getpid());
setvar("pid", newword(num, (word *)0));
- setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
- :(word *)0);
- setvar("rcname", newword(argv[0], (word *)0));
- i = 0;
- memset(bootstrap, 0, sizeof bootstrap);
- bootstrap[i++].i = 1;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f = Xassign;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xmark;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f = Xdol;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s = rcmain;
- bootstrap[i++].f = Xword;
- bootstrap[i++].s=".";
- bootstrap[i++].f = Xsimple;
- bootstrap[i++].f = Xexit;
- bootstrap[i].i = 0;
+ setvar("cflag", flag['c']? newword(flag['c'], (word *)0): (word *)0);
+ setvar("rcname", newword(argv0, (word *)0));
+
+ loadboot(bootstrap, nelem(bootstrap), (flag['m']? flag['m']: Rcmain));
start(bootstrap, 1, (var *)0);
/* prime bootstrap argv */
pushlist();
- argv0 = strdup(argv[0]);
- for(i = argc-1;i!=0;--i) pushword(argv[i]);
+ for(i = argc-1; i >= 0; --i)
+ pushword(argv[i]);
for(;;){
if(flag['r'])
pfnc(err, runq);
@@ -186,6 +228,7 @@
dotrap();
}
}
+
/*
* Opcode routines
* Arguments on stack (...)
@@ -226,13 +269,14 @@
* Xpipewait
* Xpopm(value) pop value from stack
* Xpopredir
+ * Xqdol(name) concatenate variable components
* Xrdcmds
* Xrdfn
* Xrdwr(file)[fd] open file for reading and writing
* Xread(file)[fd] open file to read
- * Xqdol(name) concatenate variable components
* Xreturn kill thread
* Xsimple(args) run command and wait
+ * Xsettrue
* Xsub
* Xsubshell{... Xexit} execute {} in a subshell and wait
* Xtrue{...} execute {} if true
@@ -263,7 +307,7 @@
Xerror("can't open");
return;
}
- Seek(f, 0L, 2);
+ seek(f, 0, 2);
pushredir(ROPEN, f, runq->code[runq->pc].i);
runq->pc++;
poplist();
@@ -692,7 +736,7 @@
copynwords(word *a, word *tail, int n)
{
word *v, **end;
-
+
v = 0;
end = &v;
while(n-- > 0){
@@ -930,24 +974,45 @@
}
void
-Xerror(char *s)
+pargv0(io *f)
{
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc: %s: %r\n", s);
+ pfmt(f, "rc: ");
else
- pfmt(err, "rc (%s): %s: %r\n", argv0, s);
+ pfmt(f, "rc (%s): ", argv0);
+}
+
+void
+hisfault(io *f)
+{
+ thread *t;
+
+ for(t = runq; !t->cmdfile && t->ret != 0; t = t->ret)
+ ;
+ if(t->cmdfile && !t->iflag)
+ pfmt(f, "%s:%d ", t->cmdfile, t->lineno);
+}
+
+void
+Xerror(char *s)
+{
+ io *msg = openstr();
+
+ pargv0(msg);
+ hisfault(msg); /* capture errstr before another sys call */
+ pfmt(err, "%s%s: %r\n", (char *)msg->strp, s);
+ closeio(msg);
flush(err);
setstatus("error");
while(!runq->iflag) Xreturn();
}
void
-Xerror1(char *s)
+Xerror1(char *s) /* omit errstr */
{
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc: %s\n", s);
- else
- pfmt(err, "rc (%s): %s\n", argv0, s);
+ pargv0(err);
+ hisfault(err);
+ pfmt(err, "%s\n", s);
flush(err);
setstatus("error");
while(!runq->iflag) Xreturn();
diff -Nru /n/sources/plan9/sys/src/cmd/rc/fns.h /sys/src/cmd/rc/fns.h
--- /n/sources/plan9/sys/src/cmd/rc/fns.h Tue Jun 26 23:18:59 2007
+++ /sys/src/cmd/rc/fns.h Wed Aug 17 00:00:00 2016
@@ -15,7 +15,6 @@
int Opendir(char*);
long Read(int, void*, long);
int Readdir(int, void*, int);
-long Seek(int, long, long);
void Trapinit(void);
void Unlink(char*);
void Updenv(void);
@@ -23,7 +22,7 @@
int Waitfor(int, int);
long Write(int, void*, long);
void addwaitpid(int);
-int advance(void);
+Rune advance(void);
int back(int);
void cleanhere(char*);
void codefree(code*);
@@ -37,7 +36,7 @@
void freewords(word*);
void globlist(void);
int havewaitpid(int);
-int idchr(int);
+int idchr(Rune);
void inttoascii(char*, long);
void kinit(void);
int mapfd(int);
@@ -60,8 +59,8 @@
void skipnl(void);
void start(code*, int, var*);
int truestatus(void);
-void usage(char*);
-int wordchr(int);
+void usage(void);
+int wordchr(Rune);
void yyerror(char*);
int yylex(void);
int yyparse(void);
diff -Nru /n/sources/plan9/sys/src/cmd/rc/getflags.c /sys/src/cmd/rc/getflags.c
--- /n/sources/plan9/sys/src/cmd/rc/getflags.c Wed Jun 27 04:19:59 2007
+++ /sys/src/cmd/rc/getflags.c Thu Jan 1 00:00:00 1970
@@ -1,233 +0,0 @@
-#include "rc.h"
-#include "getflags.h"
-#include "fns.h"
-char *flagset[] = {"<flag>"};
-char **flag[NFLAG];
-char *cmdname;
-static char *flagarg="";
-static void reverse(char**, char**);
-static int scanflag(int, char*);
-static void errn(char*, int);
-static void errs(char*);
-static void errc(int);
-static int reason;
-#define RESET 1
-#define FEWARGS 2
-#define FLAGSYN 3
-#define BADFLAG 4
-static int badflag;
-
-int
-getflags(int argc, char *argv[], char *flags, int stop)
-{
- char *s;
- int i, j, c, count;
- flagarg = flags;
- if(cmdname==0)
- cmdname = argv[0];
-
- i = 1;
- while(i!=argc){
- if(argv[i][0] != '-' || argv[i][1] == '\0'){
- if(stop) /* always true in rc */
- return argc;
- i++;
- continue;
- }
- s = argv[i]+1;
- while(*s){
- c=*s++;
- count = scanflag(c, flags);
- if(count==-1)
- return -1;
- if(flag[c]){ reason = RESET; badflag = c; return -1; }
- if(count==0){
- flag[c] = flagset;
- if(*s=='\0'){
- for(j = i+1;j<=argc;j++)
- argv[j-1] = argv[j];
- --argc;
- }
- }
- else{
- if(*s=='\0'){
- for(j = i+1;j<=argc;j++)
- argv[j-1] = argv[j];
- --argc;
- s = argv[i];
- }
- if(argc-i<count){
- reason = FEWARGS;
- badflag = c;
- return -1;
- }
- reverse(argv+i, argv+argc);
- reverse(argv+i, argv+argc-count);
- reverse(argv+argc-count+1, argv+argc);
- argc-=count;
- flag[c] = argv+argc+1;
- flag[c][0] = s;
- s="";
- }
- }
- }
- return argc;
-}
-
-static void
-reverse(char **p, char **q)
-{
- char *t;
- for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
-}
-
-static int
-scanflag(int c, char *f)
-{
- int fc, count;
- if(0<=c && c<NFLAG)
- while(*f){
- if(*f==' '){
- f++;
- continue;
- }
- fc=*f++;
- if(*f==':'){
- f++;
- if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
- count = 0;
- while('0'<=*f && *f<='9') count = count*10+*f++-'0';
- }
- else
- count = 0;
- if(*f=='['){
- do{
- f++;
- if(*f=='\0'){ reason = FLAGSYN; return -1; }
- }while(*f!=']');
- f++;
- }
- if(c==fc)
- return count;
- }
- reason = BADFLAG;
- badflag = c;
- return -1;
-}
-
-void
-usage(char *tail)
-{
- char *s, *t, c;
- int count, nflag = 0;
- switch(reason){
- case RESET:
- errs("Flag -");
- errc(badflag);
- errs(": set twice\n");
- break;
- case FEWARGS:
- errs("Flag -");
- errc(badflag);
- errs(": too few arguments\n");
- break;
- case FLAGSYN:
- errs("Bad argument to getflags!\n");
- break;
- case BADFLAG:
- errs("Illegal flag -");
- errc(badflag);
- errc('\n');
- break;
- }
- errs("Usage: ");
- errs(cmdname);
- for(s = flagarg;*s;){
- c=*s;
- if(*s++==' ')
- continue;
- if(*s==':'){
- s++;
- count = 0;
- while('0'<=*s && *s<='9') count = count*10+*s++-'0';
- }
- else count = 0;
- if(count==0){
- if(nflag==0)
- errs(" [-");
- nflag++;
- errc(c);
- }
- if(*s=='['){
- s++;
- while(*s!=']' && *s!='\0') s++;
- if(*s==']')
- s++;
- }
- }
- if(nflag)
- errs("]");
- for(s = flagarg;*s;){
- c=*s;
- if(*s++==' ')
- continue;
- if(*s==':'){
- s++;
- count = 0;
- while('0'<=*s && *s<='9') count = count*10+*s++-'0';
- }
- else count = 0;
- if(count!=0){
- errs(" [-");
- errc(c);
- if(*s=='['){
- s++;
- t = s;
- while(*s!=']' && *s!='\0') s++;
- errs(" ");
- errn(t, s-t);
- if(*s==']')
- s++;
- }
- else
- while(count--) errs(" arg");
- errs("]");
- }
- else if(*s=='['){
- s++;
- while(*s!=']' && *s!='\0') s++;
- if(*s==']')
- s++;
- }
- }
- if(tail){
- errs(" ");
- errs(tail);
- }
- errs("\n");
- Exit("bad flags");
-}
-
-static void
-errn(char *s, int count)
-{
- while(count){ errc(*s++); --count; }
-}
-
-static void
-errs(char *s)
-{
- while(*s) errc(*s++);
-}
-#define NBUF 80
-static char buf[NBUF], *bufp = buf;
-
-static void
-errc(int c)
-{
- *bufp++=c;
- if(bufp==&buf[NBUF] || c=='\n'){
- Write(2, buf, bufp-buf);
- bufp = buf;
- }
-}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/getflags.h /sys/src/cmd/rc/getflags.h
--- /n/sources/plan9/sys/src/cmd/rc/getflags.h Tue Jun 26 19:41:42 2007
+++ /sys/src/cmd/rc/getflags.h Thu Jan 1 00:00:00 1970
@@ -1,7 +0,0 @@
-#define NFLAG 128
-
-extern char **flag[NFLAG];
-extern char *cmdname;
-extern char *flagset[];
-
-int getflags(int, char*[], char*, int);
diff -Nru /n/sources/plan9/sys/src/cmd/rc/glob.c /sys/src/cmd/rc/glob.c
--- /n/sources/plan9/sys/src/cmd/rc/glob.c Tue Apr 23 23:15:45 2013
+++ /sys/src/cmd/rc/glob.c Wed Aug 17 00:00:00 2016
@@ -111,47 +111,21 @@
else
globsort(globv, svglobv);
}
-
/*
* Do p and q point at equal utf codes
*/
+
int
-equtf(uchar *p, uchar *q)
+equtf(char *p, char *q)
{
Rune pr, qr;
+
if(*p!=*q)
return 0;
-
- chartorune(&pr, (char*)p);
- chartorune(&qr, (char*)q);
+ chartorune(&pr, p);
+ chartorune(&qr, q);
return pr == qr;
}
-
-/*
- * Return a pointer to the next utf code in the string,
- * not jumping past nuls in broken utf codes!
- */
-
-uchar*
-nextutf(uchar *p)
-{
- Rune dummy;
- return p + chartorune(&dummy, (char*)p);
-}
-
-/*
- * Convert the utf code at *p to a unicode value
- */
-
-int
-unicode(uchar *p)
-{
- Rune r;
-
- chartorune(&r, (char*)p);
- return r;
-}
-
/*
* Does the string s match the pattern p
* . and .. are only matched by patterns starting with .
@@ -173,10 +147,11 @@
int
match(void *as, void *ap, int stop)
{
- int compl, hit, lo, hi, t, c;
- uchar *s = as, *p = ap;
+ int compl, hit;
+ Rune c, lo, hi, t;
+ char *s = as, *p = ap, *q;
- for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){
+ for(; *p!=stop && *p!='\0'; s += chartorune(&t, s), p += chartorune(&t, p)){
if(*p!=GLOB){
if(!equtf(p, s)) return 0;
}
@@ -186,12 +161,12 @@
return 0;
break;
case '*':
- for(;;){
- if(match(s, nextutf(p), stop)) return 1;
- if(!*s)
+ /* set q to next utf seq after p */
+ for(q = p + chartorune(&t, p); ; s += chartorune(&t, s))
+ if(match(s, q, stop))
+ return 1;
+ else if(*s == '\0')
break;
- s = nextutf(s);
- }
return 0;
case '?':
if(*s=='\0')
@@ -200,7 +175,7 @@
case '[':
if(*s=='\0')
return 0;
- c = unicode(s);
+ chartorune(&c, s);
p++;
compl=*p=='~';
if(compl)
@@ -209,16 +184,14 @@
while(*p!=']'){
if(*p=='\0')
return 0; /* syntax error */
- lo = unicode(p);
- p = nextutf(p);
+ p += chartorune(&lo, p);
if(*p!='-')
hi = lo;
else{
p++;
if(*p=='\0')
return 0; /* syntax error */
- hi = unicode(p);
- p = nextutf(p);
+ p += chartorune(&hi, p);
if(hi<lo){ t = lo; lo = hi; hi = t; }
}
if(lo<=c && c<=hi)
diff -Nru /n/sources/plan9/sys/src/cmd/rc/havefork.c /sys/src/cmd/rc/havefork.c
--- /n/sources/plan9/sys/src/cmd/rc/havefork.c Wed May 15 18:53:33 2013
+++ /sys/src/cmd/rc/havefork.c Wed Aug 17 00:00:00 2016
@@ -1,9 +1,7 @@
#include "rc.h"
-#include "getflags.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
-#include <String.h>
int havefork = 1;
@@ -83,11 +81,10 @@
int pfd[2];
char *stop;
char utf[UTFmax+1];
- struct io *f;
+ io *f, *wd;
var *ifs = vlook("ifs");
word *v, *nextv;
Rune r;
- String *word;
stop = ifs->val? ifs->val->word: "";
if(pipe(pfd)<0){
@@ -110,26 +107,26 @@
addwaitpid(pid);
close(pfd[PWR]);
f = openfd(pfd[PRD]);
- word = s_new();
+ wd = openstr();
v = nil;
/* rutf requires at least UTFmax+1 bytes in utf */
while((n = rutf(f, utf, &r)) != EOF){
utf[n] = '\0';
if(utfutf(stop, utf) == nil)
- s_nappend(word, utf, n);
+ pstr(wd, utf); /* append utf to word */
else
/*
* utf/r is an ifs rune (e.g., \t, \n), thus
* ends the current word, if any.
*/
- if(s_len(word) > 0){
- v = newword(s_to_c(word), v);
- s_reset(word);
+ if(*(char *)wd->strp != '\0'){
+ v = newword((char *)wd->strp, v);
+ rewind(wd);
}
}
- if(s_len(word) > 0)
- v = newword(s_to_c(word), v);
- s_free(word);
+ if(*(char *)wd->strp != '\0')
+ v = newword((char *)wd->strp, v);
+ closeio(wd);
closeio(f);
Waitfor(pid, 0);
/* v points to reversed arglist -- reverse it onto argv */
@@ -229,4 +226,4 @@
}
addwaitpid(pid);
return pid;
-}
+}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/haventfork.c /sys/src/cmd/rc/haventfork.c
--- /n/sources/plan9/sys/src/cmd/rc/haventfork.c Tue May 14 22:06:03 2013
+++ /sys/src/cmd/rc/haventfork.c Wed Aug 17 00:00:00 2016
@@ -1,5 +1,4 @@
#include "rc.h"
-#include "getflags.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
@@ -47,7 +46,7 @@
}
runq->pc++;
- sprint(buf, "%d", pid);
+ snprint(buf, sizeof buf, "%d", pid);
setvar("apid", newword(buf, (word *)0));
}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/io.c /sys/src/cmd/rc/io.c
--- /n/sources/plan9/sys/src/cmd/rc/io.c Tue May 14 22:30:51 2013
+++ /sys/src/cmd/rc/io.c Wed Aug 17 00:00:00 2016
@@ -23,7 +23,7 @@
if(*++fmt == '\0') /* "blah%"? */
break;
switch(*fmt){
- case 'c':
+ case 'c': /* char, not Rune */
pchr(f, va_arg(ap, int));
break;
case 'd':
@@ -64,7 +64,7 @@
}
void
-pchr(io *b, int c)
+pchr(io *b, int c) /* print a char, not a Rune */
{
if(b->bufp==b->ebuf)
fullbuf(b, c);
@@ -79,31 +79,39 @@
return *b->bufp++;
}
+/*
+ * read next utf sequence from b into buf, and convert it to Rune *r.
+ * return EOF or number of bytes consumed.
+ */
int
rutf(io *b, char *buf, Rune *r)
{
- int n, i, c;
+ int i, c;
c = rchr(b);
- if(c == EOF)
+ if(c == EOF) {
+ buf[0] = 0;
+ *r = EOF;
return EOF;
+ }
*buf = c;
- if(c < Runesync){
+ if(c < Runeself){ /* ascii? */
+ buf[1] = 0;
*r = c;
return 1;
}
- for(i = 1; (c = rchr(b)) != EOF; ){
+
+ /* multi-byte utf sequence */
+ for(i = 1; i <= UTFmax && (c = rchr(b)) != EOF && c >= Runeself; ){
buf[i++] = c;
buf[i] = 0;
- if(fullrune(buf, i)){
- n = chartorune(r, buf);
- b->bufp -= i - n; /* push back unconsumed bytes */
- assert(b->fd == -1 || b->bufp > b->buf);
- return n;
- }
+ if(fullrune(buf, i))
+ return chartorune(r, buf);
}
- /* at eof */
- b->bufp -= i - 1; /* consume 1 byte */
+
+ /* bad utf sequence: too long, or unexpected ascii or EOF */
+ if (c != EOF && c < Runeself && b->bufp > b->buf)
+ b->bufp--; /* push back ascii */
*r = Runeerror;
return runetochar(buf, r);
}
@@ -123,10 +131,14 @@
pwrd(io *f, char *s)
{
char *t;
- for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break;
- if(t==s || *t)
+
+ for (t = s; *t; t++)
+ if (*(uchar *)t < Runeself && needsrcquote(*t))
+ break;
+ if (t == s || *t)
pquo(f, s);
- else pstr(f, s);
+ else
+ pstr(f, s);
}
void
@@ -134,12 +146,14 @@
{
int n;
uintptr p;
+ static char uphex[] = "0123456789ABCDEF";
p = (uintptr)v;
- if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
- for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
-
- for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
+ if (sizeof(uintptr) == sizeof(uvlong) && p >> 32)
+ for (n = 60; n >= 32; n -= 4)
+ pchr(f, uphex[(p>>n)&0xF]);
+ for (n = 28; n >= 0; n -= 4)
+ pchr(f, uphex[(p>>n)&0xF]);
}
void
@@ -244,6 +258,7 @@
f->fd = -1;
f->bufp = f->strp = emalloc(Stralloc+1);
f->ebuf = f->bufp + Stralloc;
+ f->output = 1;
memset(f->bufp, '\0', Stralloc+1);
return f;
}
@@ -261,6 +276,7 @@
f->fd = -1 /*open("/dev/null", 0)*/;
f->bufp = f->strp = buf;
f->ebuf = buf+len;
+ f->output = 0;
Memcpy(buf, s, len);
return f;
}
@@ -268,11 +284,13 @@
void
rewind(io *io)
{
- if(io->fd==-1)
+ if(io->fd==-1) {
io->bufp = io->strp;
- else{
+ if (io->output)
+ memset(io->strp, 0, io->ebuf - io->strp);
+ }else{
io->bufp = io->ebuf = io->buf;
- Seek(io->fd, 0L, 0);
+ seek(io->fd, 0, 0);
}
}
@@ -290,7 +308,9 @@
emptybuf(io *f)
{
int n;
- if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
+
+ if(f->fd == -1 || (n = Read(f->fd, f->buf, NBUF))<=0)
+ return EOF;
f->bufp = f->buf;
f->ebuf = f->buf + n;
return *f->bufp++;
diff -Nru /n/sources/plan9/sys/src/cmd/rc/io.h /sys/src/cmd/rc/io.h
--- /n/sources/plan9/sys/src/cmd/rc/io.h Tue May 14 22:30:51 2013
+++ /sys/src/cmd/rc/io.h Wed Aug 17 00:00:00 2016
@@ -5,6 +5,7 @@
int fd;
uchar *bufp, *ebuf, *strp;
uchar buf[NBUF];
+ uchar output; /* flag */
};
io *err;
@@ -13,6 +14,7 @@
void pchr(io*, int);
int rchr(io*);
int rutf(io*, char*, Rune*);
+void rewind(io*);
void closeio(io*);
void flush(io*);
int fullbuf(io*, int);
diff -Nru /n/sources/plan9/sys/src/cmd/rc/lex.c /sys/src/cmd/rc/lex.c
--- /n/sources/plan9/sys/src/cmd/rc/lex.c Thu Jun 13 23:22:59 2013
+++ /sys/src/cmd/rc/lex.c Wed Aug 17 00:00:00 2016
@@ -1,35 +1,43 @@
#include "rc.h"
#include "exec.h"
#include "io.h"
-#include "getflags.h"
#include "fns.h"
-int getnext(void);
+
+Rune getnext(void);
int
-wordchr(int c)
+wordchr(Rune c) /* is c in the alphabet of words (non-delimiters)? */
{
- return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
+ return c != EOF &&
+ (c >= Runeself || strchr("\n \t#;&|^$=`'{}()<>", c) == nil);
}
+/*
+ * is c in the alphabet of identifiers? as in the c compiler, treat
+ * non-ascii as alphabetic.
+ */
int
-idchr(int c)
+idchr(Rune c)
{
/*
* Formerly:
* return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'
* || c=='_' || c=='*';
*/
- return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
+ return c != EOF && (c >= Runeself ||
+ c > ' ' &&
+ strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c) == nil);
}
-int future = EOF;
+
+Rune future = EOF;
int doprompt = 1;
-int inquote;
-int incomm;
+int inquote; /* are we processing a quoted word ('...')? */
+int incomm; /* are we ignoring input in a comment (#...\n)? */
/*
* Look ahead in the input stream
*/
-int
+Rune
nextc(void)
{
if(future==EOF)
@@ -40,23 +48,26 @@
* Consume the lookahead character.
*/
-int
+Rune
advance(void)
{
- int c = nextc();
+ Rune c = nextc();
+
lastc = future;
future = EOF;
return c;
}
/*
* read a character from the input stream
- */
+ */
-int
+Rune
getnext(void)
{
- int c;
- static int peekc = EOF;
+ Rune c;
+ char buf[UTFmax+1];
+ static Rune peekc = EOF;
+
if(peekc!=EOF){
c = peekc;
peekc = EOF;
@@ -66,9 +77,9 @@
return EOF;
if(doprompt)
pprompt();
- c = rchr(runq->cmdfd);
+ rutf(runq->cmdfd, buf, &c);
if(!inquote && c=='\\'){
- c = rchr(runq->cmdfd);
+ rutf(runq->cmdfd, buf, &c);
if(c=='\n' && !incomm){ /* don't continue a comment */
doprompt = 1;
c=' ';
@@ -105,7 +116,8 @@
void
skipwhite(void)
{
- int c;
+ Rune c;
+
for(;;){
c = nextc();
/* Why did this used to be if(!inquote && c=='#') ?? */
@@ -129,18 +141,22 @@
void
skipnl(void)
{
- int c;
- for(;;){
+ Rune c, c0;
+
+ for(c0 = nextc(); ; c0 = c){
skipwhite();
c = nextc();
+ if(c != c0)
+ lastword = 0; /* change of whitespace or c is not ws */
if(c!='\n')
return;
+ lastword = 0; /* new line; continue */
advance();
}
}
int
-nextis(int c)
+nextis(Rune c)
{
if(nextc()==c){
advance();
@@ -150,38 +166,16 @@
}
char*
-addtok(char *p, int val)
+addutf(char *p, Rune c)
{
if(p==0)
return 0;
- if(p >= &tok[NTOK]){
+ if(p >= &tok[NTOK-1-UTFmax*2]){
*p = 0;
yyerror("token buffer too short");
return 0;
}
- *p++=val;
- return p;
-}
-
-char*
-addutf(char *p, int c)
-{
- uchar b, m;
- int i;
-
- p = addtok(p, c); /* 1-byte UTF runes are special */
- if(c < Runeself)
- return p;
-
- m = 0xc0;
- b = 0x80;
- for(i=1; i < UTFmax; i++){
- if((c&m) == b)
- break;
- p = addtok(p, advance());
- b = m;
- m = (m >> 1)|0x80;
- }
+ p += runetochar(p, &c);
return p;
}
@@ -191,16 +185,17 @@
int
yylex(void)
{
- int c, d = nextc();
+ Rune c, d = nextc();
char *w = tok;
struct tree *t;
+
yylval.tree = 0;
/*
- * Embarassing sneakiness: if the last token read was a quoted or unquoted
- * WORD then we alter the meaning of what follows. If the next character
- * is `(', we return SUB (a subscript paren) and consume the `('. Otherwise,
- * if the next character is the first character of a simple or compound word,
- * we insert a `^' before it.
+ * Embarrassing sneakiness: if the last token read was a quoted or
+ * unquoted WORD then we alter the meaning of what follows. If the
+ * next character is `(', we return SUB (a subscript paren) and
+ * consume the `('. Otherwise, if the next character is the first
+ * character of a simple or compound word, we insert a `^' before it.
*/
if(lastword){
lastword = 0;
@@ -214,7 +209,6 @@
return '^';
}
}
- inquote = 0;
skipwhite();
switch(c = advance()){
case EOF:
@@ -357,23 +351,22 @@
t = token(tok, WORD);
t->quoted = 1;
yylval.tree = t;
+ inquote = 0;
return t->type;
}
if(!wordchr(c)){
lastdol = 0;
- tok[0] = c;
- tok[1]='\0';
+ addutf(tok, c);
return c;
}
for(;;){
if(c=='*' || c=='[' || c=='?' || c==GLOB)
- w = addtok(w, GLOB);
+ w = addutf(w, GLOB);
w = addutf(w, c);
c = nextc();
if(lastdol?!idchr(c):!wordchr(c)) break;
advance();
}
-
lastword = 1;
lastdol = 0;
if(w!=0)
diff -Nru /n/sources/plan9/sys/src/cmd/rc/mkfile /sys/src/cmd/rc/mkfile
--- /n/sources/plan9/sys/src/cmd/rc/mkfile Tue Jun 26 20:46:37 2007
+++ /sys/src/cmd/rc/mkfile Wed Aug 17 00:00:00 2016
@@ -4,7 +4,6 @@
COMMONOFILES=\
code.$O\
exec.$O\
- getflags.$O\
glob.$O\
here.$O\
io.$O\
@@ -29,7 +28,6 @@
io.h\
exec.h\
fns.h\
- getflags.h\
YFILES=syn.y
diff -Nru /n/sources/plan9/sys/src/cmd/rc/pfnc.c /sys/src/cmd/rc/pfnc.c
--- /n/sources/plan9/sys/src/cmd/rc/pfnc.c Thu Jun 13 23:22:17 2013
+++ /sys/src/cmd/rc/pfnc.c Wed Aug 17 00:00:00 2016
@@ -63,14 +63,14 @@
list *a;
pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc);
- for (i = 0; fname[i].f; i++)
+ for (i = 0; fname[i].f; i++)
if (fname[i].f == fn) {
pstr(fd, fname[i].name);
break;
}
if (!fname[i].f)
pfmt(fd, "%p", fn);
- for (a = t->argv; a; a = a->next)
+ for (a = t->argv; a; a = a->next)
pfmt(fd, " (%v)", a->words);
pchr(fd, '\n');
flush(fd);
diff -Nru /n/sources/plan9/sys/src/cmd/rc/plan9.c /sys/src/cmd/rc/plan9.c
--- /n/sources/plan9/sys/src/cmd/rc/plan9.c Thu Jun 13 23:21:10 2013
+++ /sys/src/cmd/rc/plan9.c Wed Aug 17 00:00:00 2016
@@ -7,11 +7,6 @@
#include "exec.h"
#include "io.h"
#include "fns.h"
-#include "getflags.h"
-
-enum {
- Maxenvname = 256, /* undocumented limit */
-};
char *Signame[] = {
"sigexit", "sighup", "sigint", "sigquit",
@@ -63,27 +58,28 @@
break;
case 2:
arg = 0;
- for(s = runq->argv->words->next->word;*s;s++) switch(*s){
- default:
- goto Usage;
- case 'n':
- arg|=RFNAMEG; break;
- case 'N':
- arg|=RFCNAMEG;
- break;
- case 'm':
- arg|=RFNOMNT; break;
- case 'e':
- arg|=RFENVG; break;
- case 'E':
- arg|=RFCENVG; break;
- case 's':
- arg|=RFNOTEG; break;
- case 'f':
- arg|=RFFDG; break;
- case 'F':
- arg|=RFCFDG; break;
- }
+ for(s = runq->argv->words->next->word;*s;s++)
+ switch(*s){
+ default:
+ goto Usage;
+ case 'n':
+ arg|=RFNAMEG; break;
+ case 'N':
+ arg|=RFCNAMEG;
+ break;
+ case 'm':
+ arg|=RFNOMNT; break;
+ case 'e':
+ arg|=RFENVG; break;
+ case 'E':
+ arg|=RFCENVG; break;
+ case 's':
+ arg|=RFNOTEG; break;
+ case 'f':
+ arg|=RFFDG; break;
+ case 'F':
+ arg|=RFCFDG; break;
+ }
break;
default:
Usage:
@@ -101,12 +97,40 @@
poplist();
}
+int
+openenv(char *shortname)
+{
+ int f;
+ io *envname;
+
+ envname = openstr();
+ pfmt(envname, "/env/%s", shortname);
+ f = open((char *)envname->strp, OREAD);
+ closeio(envname);
+ return f;
+}
+
+int
+createenv(char *pfx, char *shortname)
+{
+ int f;
+ io *envname;
+
+ envname = openstr();
+ pfmt(envname, "/env/%s%s", pfx, shortname);
+ f = Creat((char *)envname->strp);
+ if (f < 0)
+ pfmt(err, "rc: can't create %s: %r\n", (char *)envname->strp);
+ closeio(envname);
+ return f;
+}
+
void
Vinit(void)
{
int dir, f, len, i, n, nent;
- char *buf, *s;
- char envname[Maxenvname];
+ char *buf, *s, *name;
+ var *namevar;
word *val;
Dir *ent;
@@ -116,52 +140,52 @@
return;
}
ent = nil;
- for(;;){
- nent = dirread(dir, &ent);
- if(nent <= 0)
- break;
+ while ((nent = dirread(dir, &ent)) > 0) {
for(i = 0; i<nent; i++){
len = ent[i].length;
- if(len && strncmp(ent[i].name, "fn#", 3)!=0){
- snprint(envname, sizeof envname, "/env/%s", ent[i].name);
- if((f = open(envname, 0))>=0){
- buf = emalloc(len+1);
- n = readn(f, buf, len);
- if (n <= 0)
- buf[0] = '\0';
- else
- buf[n] = '\0';
- val = 0;
- /* Charitably add a 0 at the end if need be */
- if(buf[len-1])
- buf[len++]='\0';
- s = buf+len-1;
- for(;;){
- while(s!=buf && s[-1]!='\0') --s;
- val = newword(s, val);
- if(s==buf)
- break;
- --s;
- }
- setvar(ent[i].name, val);
- vlook(ent[i].name)->changed = 0;
- close(f);
- efree(buf);
- }
+ name = ent[i].name;
+ if(len <= 0 || strncmp(name, "fn#", 3) == 0)
+ continue;
+ if((f = openenv(name)) < 0)
+ continue;
+ buf = emalloc(len+1);
+ n = readn(f, buf, len);
+ if (n <= 0)
+ buf[0] = '\0';
+ else
+ buf[n] = '\0';
+ val = 0;
+ /* Charitably add a 0 at the end if need be */
+ if(buf[len-1])
+ buf[len++]='\0';
+ s = buf+len-1;
+ for(;;){
+ while(s!=buf && s[-1]!='\0')
+ --s;
+ val = newword(s, val);
+ if(s==buf)
+ break;
+ --s;
}
+ setvar(name, val);
+ namevar = vlook(name);
+ assert(namevar != nil);
+ namevar->changed = 0;
+ close(f);
+ efree(buf);
}
free(ent);
}
close(dir);
}
+
int envdir;
void
Xrdfn(void)
{
- int f, len;
+ int f;
Dir *e;
- char envname[Maxenvname];
static Dir *ent, *allocent;
static int nent;
@@ -176,10 +200,8 @@
while(nent){
e = ent++;
nent--;
- len = e->length;
- if(len && strncmp(e->name, "fn#", 3)==0){
- snprint(envname, sizeof envname, "/env/%s", e->name);
- if((f = open(envname, 0))>=0){
+ if(e->length && strncmp(e->name, "fn#", 3)==0){
+ if((f = openenv(e->name)) >= 0){
execcmds(openfd(f));
return;
}
@@ -189,6 +211,7 @@
close(envdir);
Xreturn();
}
+
union code rdfns[4];
void
@@ -222,6 +245,9 @@
return 0;
while((w = wait()) != nil){
+ /* this would otherwise go unreported by rc */
+ if(strstr(w->msg, "error in demand load") != nil)
+ pfmt(err, "rc: %s\n", w->msg);
delwaitpid(w->pid);
if(w->pid==pid){
setstatus(w->msg);
@@ -254,27 +280,20 @@
void
addenv(var *v)
{
- char envname[Maxenvname];
word *w;
int f;
io *fd;
if(v->changed){
v->changed = 0;
- snprint(envname, sizeof envname, "/env/%s", v->name);
- if((f = Creat(envname))<0)
- pfmt(err, "rc: can't open %s: %r\n", envname);
- else{
+ if((f = createenv("", v->name)) >= 0) {
for(w = v->val;w;w = w->next)
- write(f, w->word, strlen(w->word)+1L);
+ write(f, w->word, strlen(w->word)+1);
close(f);
}
}
if(v->fnchanged){
v->fnchanged = 0;
- snprint(envname, sizeof envname, "/env/fn#%s", v->name);
- if((f = Creat(envname))<0)
- pfmt(err, "rc: can't open %s: %r\n", envname);
- else{
+ if((f = createenv("fn#", v->name)) >= 0) {
if(v->fn){
fd = openfd(f);
pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
@@ -339,43 +358,48 @@
Execute(word *args, word *path)
{
char **argv = mkargv(args);
- char file[1024], errstr[1024];
+ char file[1024], errstr[ERRMAX+1];
int nc;
Updenv();
errstr[0] = '\0';
for(;path;path = path->next){
nc = strlen(path->word);
- if(nc < sizeof file - 1){ /* 1 for / */
- strcpy(file, path->word);
- if(file[0]){
- strcat(file, "/");
- nc++;
- }
- if(nc + strlen(argv[1]) < sizeof file){
- strcat(file, argv[1]);
- exec(file, argv+1);
- rerrstr(errstr, sizeof errstr);
- /*
- * if file exists and is executable, exec should
- * have worked, unless it's a directory or an
- * executable for another architecture. in
- * particular, if it failed due to lack of
- * swap/vm (e.g., arg. list too long) or other
- * allocation failure, stop searching and print
- * the reason for failure.
- */
- if (strstr(errstr, " allocat") != nil ||
- strstr(errstr, " full") != nil)
- break;
- }
- else werrstr("command name too long");
+ if(nc >= sizeof file - 1){ /* 1 for / */
+ werrstr("path component too long");
+ continue;
}
+ strcpy(file, path->word);
+ if(file[0]){
+ strcat(file, "/");
+ nc++;
+ }
+ if(nc + strlen(argv[1]) >= sizeof file){
+ werrstr("command name too long");
+ continue;
+ }
+ strcat(file, argv[1]);
+ exec(file, argv+1);
+ /*
+ * if file exists and is executable, exec should have worked,
+ * unless it's a directory or an executable for another
+ * architecture. in particular, if it failed due to lack of
+ * swap/vm (e.g., arg. list too long) or other allocation or
+ * i/o failure, stop searching and print the reason for failure.
+ */
+ rerrstr(errstr, sizeof errstr);
+ if (strstr(errstr, " allocat") != nil ||
+ strstr(errstr, " full") != nil ||
+ strstr(errstr, "i/o error") != nil)
+ break;
}
+ if(errstr[0] == '\0') /* pick up any werrstr "too long"s */
+ rerrstr(errstr, sizeof errstr);
pfmt(err, "%s: %s\n", argv[1], errstr);
efree((char *)argv);
}
-#define NDIR 256 /* shoud be a better way */
+
+#define NDIR 256 /* should be a better way */
int
Globsize(char *p)
@@ -438,7 +462,7 @@
* onlydirs is advisory -- it means you only
* need to return the directories. it's okay to
* return files too (e.g., on unix where you can't
- * tell during the readdir), but that just makes
+ * tell during the readdir), but that just makes
* the globber work harder.
*/
int
@@ -458,7 +482,7 @@
n = trimdirs(dir[f].dbuf, n);
if(n == 0)
goto Again;
- }
+ }
dir[f].n = n;
}else
dir[f].n = 0;
@@ -482,24 +506,29 @@
}
close(f);
}
+
int interrupted = 0;
+
void
notifyf(void*, char *s)
{
int i;
- for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
- if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
- goto Out;
- }
+
+ for (i = 0; syssigname[i]; i++)
+ if (strncmp(s, syssigname[i], strlen(syssigname[i])) == 0) {
+ if (strncmp(s, "sys: ", 5) != 0)
+ interrupted = 1;
+ goto Out;
+ }
pfmt(err, "rc: note: %s\n", s);
noted(NDFLT);
return;
Out:
- if(strcmp(s, "interrupt")!=0 || trap[i]==0){
+ if (strcmp(s, "interrupt") != 0 || trap[i] == 0) {
trap[i]++;
ntrap++;
}
- if(ntrap>=32){ /* rc is probably in a trap loop */
+ if (ntrap >= 32) { /* rc is probably in a trap loop */
pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
abort();
}
@@ -530,12 +559,6 @@
return read(fd, buf, cnt);
}
-long
-Seek(int fd, long cnt, long whence)
-{
- return seek(fd, cnt, whence);
-}
-
int
Executable(char *file)
{
@@ -553,7 +576,7 @@
int
Creat(char *file)
{
- return create(file, 1, 0666L);
+ return create(file, 1, 0666);
}
int
@@ -640,7 +663,7 @@
delwaitpid(int pid)
{
int r, w;
-
+
for(r=w=0; r<nwaitpids; r++)
if(waitpids[r] != pid)
waitpids[w++] = waitpids[r];
@@ -669,4 +692,4 @@
_efgfmt(Fmt *)
{
return -1;
-}
+}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/rc.h /sys/src/cmd/rc/rc.h
--- /n/sources/plan9/sys/src/cmd/rc/rc.h Thu Jun 13 23:14:33 2013
+++ /sys/src/cmd/rc/rc.h Wed Aug 17 00:00:00 2016
@@ -1,28 +1,38 @@
/*
* Assume plan 9 by default; if Unix is defined, assume unix.
- * Please don't litter the code with ifdefs. The five below should be enough.
+ * Please don't litter the code with ifdefs. The three below should be enough.
*/
+typedef struct tree tree;
+typedef struct word word;
+typedef struct io io;
+typedef union code code;
+typedef struct var var;
+typedef struct list list;
+typedef struct redir redir;
+typedef struct thread thread;
+typedef struct builtin builtin;
+
+#define isdigit(c) ((c) >= '0' && (c) <= '9') /* NB: unsafe macro */
+
#ifndef Unix
/* plan 9 */
#include <u.h>
#include <libc.h>
+#pragma incomplete word
+#pragma incomplete io
+
+/* unix compatibility */
+#define unixclsexec(wdirfd)
+
#define NSIG 32
#define SIGINT 2
#define SIGQUIT 3
-
-#define fcntl(fd, op, arg) /* unix compatibility */
-#define F_SETFD
-#define FD_CLOEXEC
#else
#include "unix.h"
#endif
-#ifndef ERRMAX
-#define ERRMAX 128
-#endif
-
#define YYMAXDEPTH 500
#ifndef YYPREFIX
#ifndef PAREN
@@ -30,21 +40,6 @@
#endif
#endif
-typedef struct tree tree;
-typedef struct word word;
-typedef struct io io;
-typedef union code code;
-typedef struct var var;
-typedef struct list list;
-typedef struct redir redir;
-typedef struct thread thread;
-typedef struct builtin builtin;
-
-#ifndef Unix
-#pragma incomplete word
-#pragma incomplete io
-#endif
-
struct tree{
int type;
int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */
@@ -147,5 +142,10 @@
*/
int ndot;
char *getstatus(void);
-int lastc;
+Rune lastc;
int lastword;
+
+#define NFLAG 128 /* limited to ascii */
+
+extern char *flag[NFLAG];
+extern char flagset[];
diff -Nru /n/sources/plan9/sys/src/cmd/rc/rune.c /sys/src/cmd/rc/rune.c
--- /n/sources/plan9/sys/src/cmd/rc/rune.c Thu Jan 1 00:00:00 1970
+++ /sys/src/cmd/rc/rune.c Wed Aug 17 00:00:00 2016
@@ -0,0 +1,165 @@
+#include "rc.h"
+
+#define Bit(i) (7-(i))
+/* N 0's preceded by i 1's, T(Bit(2)) is 1100 0000 */
+#define T(i) (((1 << (Bit(i)+1))-1) ^ 0xFF)
+/* 0000 0000 0000 0111 1111 1111 */
+#define RuneX(i) ((1 << (Bit(i) + ((i)-1)*Bitx))-1)
+
+enum
+{
+ Bitx = Bit(1),
+
+ Tx = T(1), /* 1000 0000 */
+ Rune1 = (1<<(Bit(0)+0*Bitx))-1, /* 0000 0000 0000 0000 0111 1111 */
+
+ Maskx = (1<<Bitx)-1, /* 0011 1111 */
+ Testx = Maskx ^ 0xFF, /* 1100 0000 */
+
+ SurrogateMin = 0xD800,
+ SurrogateMax = 0xDFFF,
+
+ Bad = Runeerror,
+};
+
+int
+chartorune(Rune *rune, char *str)
+{
+ int c[UTFmax], i;
+ Rune l;
+
+ /*
+ * N character sequence
+ * 00000-0007F => T1
+ * 00080-007FF => T2 Tx
+ * 00800-0FFFF => T3 Tx Tx
+ * 10000-10FFFF => T4 Tx Tx Tx
+ */
+
+ c[0] = *(uchar*)(str);
+ if(c[0] < Tx){
+ *rune = c[0];
+ return 1;
+ }
+ l = c[0];
+
+ for(i = 1; i < UTFmax; i++) {
+ c[i] = *(uchar*)(str+i);
+ c[i] ^= Tx;
+ if(c[i] & Testx)
+ goto bad;
+ l = (l << Bitx) | c[i];
+ if(c[0] < T(i + 2)) {
+ l &= RuneX(i + 1);
+ if(i == 1) {
+ if(c[0] < T(2) || l <= Rune1)
+ goto bad;
+ } else if(l <= RuneX(i) || l > Runemax)
+ goto bad;
+ if (i == 2 && SurrogateMin <= l && l <= SurrogateMax)
+ goto bad;
+ *rune = l;
+ return i + 1;
+ }
+ }
+
+ /*
+ * bad decoding
+ */
+bad:
+ *rune = Bad;
+ return 1;
+}
+
+int
+runetochar(char *str, Rune *rune)
+{
+ int i, j;
+ Rune c;
+
+ c = *rune;
+ if(c <= Rune1) {
+ str[0] = c;
+ return 1;
+ }
+
+ /*
+ * one character sequence
+ * 00000-0007F => 00-7F
+ * two character sequence
+ * 0080-07FF => T2 Tx
+ * three character sequence
+ * 0800-FFFF => T3 Tx Tx
+ * four character sequence (21-bit value)
+ * 10000-1FFFFF => T4 Tx Tx Tx
+ * If the Rune is out of range or a surrogate half,
+ * convert it to the error rune.
+ * Do this test when i==3 because the error rune encodes to three bytes.
+ * Doing it earlier would duplicate work, since an out of range
+ * Rune wouldn't have fit in one or two bytes.
+ */
+ for(i = 2; i < UTFmax + 1; i++){
+ if(i == 3){
+ if(c > Runemax)
+ c = Runeerror;
+ if(SurrogateMin <= c && c <= SurrogateMax)
+ c = Runeerror;
+ }
+ if (c <= RuneX(i) || i == UTFmax ) {
+ str[0] = T(i) | (c >> (i - 1)*Bitx);
+ for(j = 1; j < i; j++)
+ str[j] = Tx | ((c >> (i - j - 1)*Bitx) & Maskx);
+ return i;
+ }
+ }
+ return UTFmax;
+}
+
+int
+runelen(long c)
+{
+ Rune rune;
+ char str[10];
+
+ rune = c;
+ return runetochar(str, &rune);
+}
+
+int
+runenlen(Rune *r, int nrune)
+{
+ int nb, i;
+ Rune c;
+
+ nb = 0;
+ while(nrune--) {
+ c = *r++;
+ if(c <= Rune1){
+ nb++;
+ } else {
+ for(i = 2; i < UTFmax + 1; i++)
+ if(c <= RuneX(i) || i == UTFmax){
+ nb += i;
+ break;
+ }
+ }
+ }
+ return nb;
+}
+
+int
+fullrune(char *str, int n)
+{
+ int i;
+ Rune c;
+
+ if(n <= 0)
+ return 0;
+ c = *(uchar*)str;
+ if(c < Tx)
+ return 1;
+ for(i = 3; i < UTFmax + 1; i++)
+ if(c < T(i))
+ return n >= i - 1;
+ return n >= UTFmax;
+}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/simple.c /sys/src/cmd/rc/simple.c
--- /n/sources/plan9/sys/src/cmd/rc/simple.c Thu Jun 13 23:21:01 2013
+++ /sys/src/cmd/rc/simple.c Wed Aug 17 00:00:00 2016
@@ -2,7 +2,6 @@
* Maybe `simple' is a misnomer.
*/
#include "rc.h"
-#include "getflags.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
@@ -10,7 +9,8 @@
* Search through the following code to see if we're just going to exit.
*/
int
-exitnext(void){
+exitnext(void)
+{
union code *c=&runq->code[runq->pc];
while(c->f==Xpopredir) c++;
return c->f==Xexit;
@@ -146,7 +146,7 @@
if(wdirfd==-2) /* try only once */
wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
if(wdirfd>=0) {
- fcntl(wdirfd, F_SETFD, FD_CLOEXEC);
+ unixclsexec(wdirfd);
write(wdirfd, word, strlen(word));
}
}
@@ -264,15 +264,6 @@
}
int
-octal(char *s)
-{
- int n = 0;
- while(*s==' ' || *s=='\t' || *s=='\n') s++;
- while('0'<=*s && *s<='7') n = n*8+*s++-'0';
- return n;
-}
-
-int
mapfd(int fd)
{
redir *rp;
@@ -447,7 +438,8 @@
}
void
-execwhatis(void){ /* mildly wrong -- should fork before writing */
+execwhatis(void) /* mildly wrong -- should fork before writing */
+{
word *a, *b, *path;
var *v;
struct builtin *bp;
diff -Nru /n/sources/plan9/sys/src/cmd/rc/syn.y /sys/src/cmd/rc/syn.y
--- /n/sources/plan9/sys/src/cmd/rc/syn.y Sun Dec 12 01:11:23 1999
+++ /sys/src/cmd/rc/syn.y Wed Aug 17 00:00:00 2016
@@ -45,7 +45,7 @@
| IF NOT {skipnl();} cmd {$$=mung1($2, $4);}
| FOR '(' word IN words ')' {skipnl();} cmd
/*
- * if ``words'' is nil, we need a tree element to distinguish between
+ * if ``words'' is nil, we need a tree element to distinguish between
* for(i in ) and for(i), the former being a loop over the empty set
* and the latter being the implicit argument loop. so if $5 is nil
* (the empty set), we represent it as "()". don't parenthesize non-nil
@@ -73,7 +73,7 @@
simple: first
| simple word {$$=tree2(ARGLIST, $1, $2);}
| simple redir {$$=tree2(ARGLIST, $1, $2);}
-first: comword
+first: comword
| first '^' word {$$=tree2('^', $1, $3);}
word: keyword {lastword=1; $1->type=WORD;}
| comword
diff -Nru /n/sources/plan9/sys/src/cmd/rc/tree.c /sys/src/cmd/rc/tree.c
--- /n/sources/plan9/sys/src/cmd/rc/tree.c Tue Jun 26 22:52:20 2007
+++ /sys/src/cmd/rc/tree.c Wed Aug 17 00:00:00 2016
@@ -138,7 +138,7 @@
freetree(tree *p)
{
if(p==0)
- return;
+ return;
freetree(p->child[0]);
freetree(p->child[1]);
freetree(p->child[2]);
diff -Nru /n/sources/plan9/sys/src/cmd/rc/unix.c /sys/src/cmd/rc/unix.c
--- /n/sources/plan9/sys/src/cmd/rc/unix.c Fri Mar 1 22:25:23 2013
+++ /sys/src/cmd/rc/unix.c Wed Aug 17 00:00:00 2016
@@ -6,7 +6,6 @@
#include "rc.h"
#include "io.h"
#include "exec.h"
-#include "getflags.h"
#include <errno.h>
char *Rcmain = "/usr/lib/rcmain";
@@ -431,11 +430,6 @@
{
return read(fd, buf, cnt);
}
-Seek(fd, cnt, whence)
-long cnt;
-{
- return lseek(fd, cnt, whence);
-}
Executable(file)
char *file;
{
@@ -489,6 +483,15 @@
abort();
}
+int
+octal(char *s)
+{
+ int n = 0;
+ while(*s==' ' || *s=='\t' || *s=='\n') s++;
+ while('0'<=*s && *s<='7') n = n*8+*s++-'0';
+ return n;
+}
+
void
execumask(void) /* wrong -- should fork before writing */
{
@@ -549,6 +552,12 @@
rfork(int bits)
{
return fork();
+}
+
+void
+unixclsexec(int fd)
+{
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
}
int *waitpids;
diff -Nru /n/sources/plan9/sys/src/cmd/rc/unix.h /sys/src/cmd/rc/unix.h
--- /n/sources/plan9/sys/src/cmd/rc/unix.h Fri Mar 1 22:55:48 2013
+++ /sys/src/cmd/rc/unix.h Wed Aug 17 00:00:00 2016
@@ -1,3 +1,5 @@
+/* mostly plan 9 compatibility */
+
#undef _BSD_EXTENSION /* avoid multiple def'n if predefined */
#undef _PLAN9_SOURCE
#undef _POSIX_SOURCE
@@ -22,17 +24,29 @@
#define NSIG 32
#endif
-/* plan 9 compatibility */
#define RFPROC 1
#define RFFDG 1
#define RFNOTEG 1
-#define uintptr uintptr_t
+#define OREAD O_RDONLY
+#define OWRITE O_WRONLY
+#define ORDWR O_RDWR
+#define OCEXEC 0
-char *strdup(const char *);
+#define ERRMAX 128
+#define uintptr uintptr_t
#define nil ((void*)0)
+#define assert(cond)
+#define seek lseek
+#define print printf
+#define fprint fprintf
+#define snprint snprintf
+
+char *strdup(const char *);
+void unixclsexec(int);
+
/* in case uchar, etc. are built-in types */
#define uchar _fmtuchar
#define ushort _fmtushort
@@ -47,7 +61,52 @@
typedef unsigned long ulong;
typedef unsigned long long uvlong;
-#define OREAD O_RDONLY
-#define OWRITE O_WRONLY
-#define ORDWR O_RDWR
-#define OCEXEC 0
+typedef ulong Rune;
+
+enum
+{
+ UTFmax = 4, /* maximum bytes per rune */
+ Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
+ Runeself = 0x80, /* rune and UTF sequences are the same (<) */
+ Runeerror = 0xFFFD, /* decoding error in UTF */
+ Runemax = 0x10FFFF, /* 21-bit rune */
+ Runemask = 0x1FFFFF, /* bits used by runes (see grep) */
+};
+
+/*
+ * rune routines
+ */
+extern int runetochar(char*, Rune*);
+extern int chartorune(Rune*, char*);
+extern int runelen(long);
+extern int runenlen(Rune*, int);
+extern int fullrune(char*, int);
+extern int utflen(char*);
+extern int utfnlen(char*, long);
+extern char* utfrune(char*, long);
+extern char* utfrrune(char*, long);
+extern char* utfutf(char*, char*);
+extern char* utfecpy(char*, char*, char*);
+
+extern char *argv0;
+#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
+ argv[0] && argv[0][0]=='-' && argv[0][1];\
+ argc--, argv++) {\
+ char *_args, *_argt;\
+ Rune _argc;\
+ _args = &argv[0][1];\
+ if(_args[0]=='-' && _args[1]==0){\
+ argc--; argv++; break;\
+ }\
+ _argc = 0;\
+ while(*_args && (_args += chartorune(&_argc, _args)))\
+ switch(_argc)
+#define ARGEND SET(_argt);USED(_argt,_argc,_args);}USED(argv, argc);
+#define ARGF() (_argt=_args, _args="",\
+ (*_argt? _argt: argv[1]? (argc--, *++argv): 0))
+#define EARGF(x) (_argt=_args, _args="",\
+ (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
+
+#define ARGC() _argc
+
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
diff -Nru /n/sources/plan9/sys/src/cmd/rc/utfrune.c /sys/src/cmd/rc/utfrune.c
--- /n/sources/plan9/sys/src/cmd/rc/utfrune.c Thu Jan 1 00:00:00 1970
+++ /sys/src/cmd/rc/utfrune.c Wed Aug 17 00:00:00 2016
@@ -0,0 +1,28 @@
+#include "rc.h"
+
+char*
+utfrune(char *s, long c)
+{
+ long c1;
+ Rune r;
+ int n;
+
+ if(c < Runesync) /* not part of utf sequence */
+ return strchr(s, c);
+
+ for(;;) {
+ c1 = *(uchar*)s;
+ if(c1 < Runeself) { /* one byte rune */
+ if(c1 == 0)
+ return 0;
+ if(c1 == c)
+ return s;
+ s++;
+ continue;
+ }
+ n = chartorune(&r, s);
+ if(r == c)
+ return s;
+ s += n;
+ }
+}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/utfutf.c /sys/src/cmd/rc/utfutf.c
--- /n/sources/plan9/sys/src/cmd/rc/utfutf.c Thu Jan 1 00:00:00 1970
+++ /sys/src/cmd/rc/utfutf.c Wed Aug 17 00:00:00 2016
@@ -0,0 +1,24 @@
+#include "rc.h"
+
+/*
+ * Return pointer to first occurrence of s2 in s1,
+ * 0 if none
+ */
+char*
+utfutf(char *s1, char *s2)
+{
+ char *p;
+ long 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;
+}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/var.c /sys/src/cmd/rc/var.c
--- /n/sources/plan9/sys/src/cmd/rc/var.c Thu Jun 13 23:22:45 2013
+++ /sys/src/cmd/rc/var.c Wed Aug 17 00:00:00 2016
@@ -67,7 +67,10 @@
{
int h = hash(name, NVAR);
var *v;
- for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
+
+ for (v = gvar[h]; v; v = v->next)
+ if (strcmp(v->name, name) == 0)
+ return v;
return gvar[h] = newvar(strdup(name), gvar[h]);
}
@@ -75,9 +78,11 @@
vlook(char *name)
{
var *v;
- if(runq)
- for(v = runq->local;v;v = v->next)
- if(strcmp(v->name, name)==0) return v;
+
+ if (runq)
+ for (v = runq->local; v; v = v->next)
+ if (strcmp(v->name, name) == 0)
+ return v;
return gvlook(name);
}
diff -Nru /n/sources/plan9/sys/src/cmd/rc/win32.c /sys/src/cmd/rc/win32.c
--- /n/sources/plan9/sys/src/cmd/rc/win32.c Fri Mar 1 19:53:47 2013
+++ /sys/src/cmd/rc/win32.c Wed Aug 17 00:00:00 2016
@@ -7,7 +7,6 @@
#include "exec.h"
#include "io.h"
#include "fns.h"
-#include "getflags.h"
char *Signame[] = {
"sigexit", "sighup", "sigint", "sigquit",
"sigalrm", "sigkill", "sigfpe", "sigterm",
@@ -456,12 +455,6 @@
Read(int fd, void *buf, long cnt)
{
return read(fd, buf, cnt);
-}
-
-long
-Seek(int fd, long cnt, long whence)
-{
- return seek(fd, cnt, whence);
}
int
|