diff options
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/bc.y | 983 | ||||
-rw-r--r-- | src/cmd/jpg/mkfile | 4 | ||||
-rw-r--r-- | src/cmd/mkfile | 24 | ||||
-rw-r--r-- | src/cmd/mtime.c | 33 | ||||
-rw-r--r-- | src/cmd/news.c | 231 | ||||
-rw-r--r-- | src/cmd/primes.c | 131 | ||||
-rw-r--r-- | src/cmd/units.y | 795 |
7 files changed, 2195 insertions, 6 deletions
diff --git a/src/cmd/bc.y b/src/cmd/bc.y new file mode 100644 index 00000000..5eddf471 --- /dev/null +++ b/src/cmd/bc.y @@ -0,0 +1,983 @@ +%{ + #include <u.h> + #include <libc.h> + #include <bio.h> + + #define bsp_max 5000 + + Biobuf *in; + Biobuf stdin; + Biobuf stdout; + char cary[1000]; + char* cp = { cary }; + char string[1000]; + char* str = { string }; + int crs = 128; + int rcrs = 128; /* reset crs */ + int bindx = 0; + int lev = 0; + int ln; + int* ttp; + char* ss = ""; + int bstack[10] = { 0 }; + char* numb[15] = + { + " 0", " 1", " 2", " 3", " 4", " 5", + " 6", " 7", " 8", " 9", " 10", " 11", + " 12", " 13", " 14" + }; + int* pre; + int* post; + + long peekc = -1; + int sargc; + int ifile; + char** sargv; + + char *funtab[] = + { + "<1>","<2>","<3>","<4>","<5>", + "<6>","<7>","<8>","<9>","<10>", + "<11>","<12>","<13>","<14>","<15>", + "<16>","<17>","<18>","<19>","<20>", + "<21>","<22>","<23>","<24>","<25>", + "<26>" + }; + char *atab[] = + { + "<221>","<222>","<223>","<224>","<225>", + "<226>","<227>","<228>","<229>","<230>", + "<231>","<232>","<233>","<234>","<235>", + "<236>","<237>","<238>","<239>","<240>", + "<241>","<242>","<243>","<244>","<245>", + "<246>" + }; + char* letr[26] = + { + "a","b","c","d","e","f","g","h","i","j", + "k","l","m","n","o","p","q","r","s","t", + "u","v","w","x","y","z" + }; + char* dot = { "." }; + int bspace[bsp_max]; + int* bsp_nxt = { bspace }; + int bdebug = 0; + int lflag; + int cflag; + int sflag; + + int* bundle(int, ...); + void conout(int*, char*); + int cpeek(int, int, int); + int getch(void); + int* geta(char*); + int* getf(char*); + void getout(void); + void output(int*); + void pp(char*); + void routput(int*); + void tp(char*); + void yyerror(char*, ...); + int yyparse(void); + + typedef void* pointer; +/* #pragma varargck type "lx" pointer */ + +%} +%union +{ + int* iptr; + char* cptr; + int cc; +} + +%type <iptr> pstat stat stat1 def slist dlets e ase nase +%type <iptr> slist re fprefix cargs eora cons constant lora +%type <cptr> crs + +%token <cptr> LETTER EQOP _AUTO DOT +%token <cc> DIGIT SQRT LENGTH _IF FFF EQ +%token <cc> _PRINT _WHILE _FOR NE LE GE INCR DECR +%token <cc> _RETURN _BREAK _DEFINE BASE OBASE SCALE +%token <cc> QSTR ERROR + +%right '=' EQOP +%left '+' '-' +%left '*' '/' '%' +%right '^' +%left UMINUS + +%% +start: + start stuff +| stuff + +stuff: + pstat tail + { + output($1); + } +| def dargs ')' '{' dlist slist '}' + { + ttp = bundle(6, pre, $6, post , "0", numb[lev], "Q"); + conout(ttp, (char*)$1); + rcrs = crs; + output((int*)""); /* this is horse puk!! */ + lev = bindx = 0; + } + +dlist: + tail +| dlist _AUTO dlets tail + +stat: + stat1 +| nase + { + if(sflag) + bundle(2, $1, "s."); + } + +pstat: + stat1 + { + if(sflag) + bundle(2, $1, "0"); + } +| nase + { + if(!sflag) + bundle(2, $1, "ps."); + } + +stat1: + { + bundle(1, ""); + } +| ase + { + bundle(2, $1, "s."); + } +| SCALE '=' e + { + bundle(2, $3, "k"); + } +| SCALE EQOP e + { + bundle(4, "K", $3, $2, "k"); + } +| BASE '=' e + { + bundle(2, $3, "i"); + } +| BASE EQOP e + { + bundle(4, "I", $3, $2, "i"); + } +| OBASE '=' e + { + bundle(2, $3, "o"); + } +| OBASE EQOP e + { + bundle(4, "O", $3, $2, "o"); + } +| QSTR + { + bundle(3, "[", $1, "]P"); + } +| _BREAK + { + bundle(2, numb[lev-bstack[bindx-1]], "Q"); + } +| _PRINT e + { + bundle(2, $2, "ps."); + } +| _RETURN e + { + bundle(4, $2, post, numb[lev], "Q"); + } +| _RETURN + { + bundle(4, "0", post, numb[lev], "Q"); + } +| '{' slist '}' + { + $$ = $2; + } +| FFF + { + bundle(1, "fY"); + } +| _IF crs BLEV '(' re ')' stat + { + conout($7, $2); + bundle(3, $5, $2, " "); + } +| _WHILE crs '(' re ')' stat BLEV + { + bundle(3, $6, $4, $2); + conout($$, $2); + bundle(3, $4, $2, " "); + } +| fprefix crs re ';' e ')' stat BLEV + { + bundle(5, $7, $5, "s.", $3, $2); + conout($$, $2); + bundle(5, $1, "s.", $3, $2, " "); + } +| '~' LETTER '=' e + { + bundle(3, $4, "S", $2); + } + +fprefix: + _FOR '(' e ';' + { + $$ = $3; + } + +BLEV: + = + { + --bindx; + } + +slist: + stat +| slist tail stat + { + bundle(2, $1, $3); + } + +tail: + '\n' + { + ln++; + } +| ';' + +re: + e EQ e + { + $$ = bundle(3, $1, $3, "="); + } +| e '<' e + { + bundle(3, $1, $3, ">"); + } +| e '>' e + { + bundle(3, $1, $3, "<"); + } +| e NE e + { + bundle(3, $1, $3, "!="); + } +| e GE e + { + bundle(3, $1, $3, "!>"); + } +| e LE e + { + bundle(3, $1, $3, "!<"); + } +| e + { + bundle(2, $1, " 0!="); + } + +nase: + '(' e ')' + { + $$ = $2; + } +| cons + { + bundle(3, " ", $1, " "); + } +| DOT cons + { + bundle(3, " .", $2, " "); + } +| cons DOT cons + { + bundle(5, " ", $1, ".", $3, " "); + } +| cons DOT + { + bundle(4, " ", $1, ".", " "); + } +| DOT + { + $<cptr>$ = "l."; + } +| LETTER '[' e ']' + { + bundle(3, $3, ";", geta($1)); + } +| LETTER INCR + { + bundle(4, "l", $1, "d1+s", $1); + } +| INCR LETTER + { + bundle(4, "l", $2, "1+ds", $2); + } +| DECR LETTER + { + bundle(4, "l", $2, "1-ds", $2); + } +| LETTER DECR + { + bundle(4, "l", $1, "d1-s", $1); + } +| LETTER '[' e ']' INCR + { + bundle(7, $3, ";", geta($1), "d1+" ,$3, ":" ,geta($1)); + } +| INCR LETTER '[' e ']' + { + bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2)); + } +| LETTER '[' e ']' DECR + { + bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1)); + } +| DECR LETTER '[' e ']' + { + bundle(7, $4, ";", geta($2), "1-d", $4, ":" ,geta($2)); + } +| SCALE INCR + { + bundle(1, "Kd1+k"); + } +| INCR SCALE + { + bundle(1, "K1+dk"); + } +| SCALE DECR + { + bundle(1, "Kd1-k"); + } +| DECR SCALE + { + bundle(1, "K1-dk"); + } +| BASE INCR + { + bundle(1, "Id1+i"); + } +| INCR BASE + { + bundle(1, "I1+di"); + } +| BASE DECR + { + bundle(1, "Id1-i"); + } +| DECR BASE + { + bundle(1, "I1-di"); + } +| OBASE INCR + { + bundle(1, "Od1+o"); + } +| INCR OBASE + { + bundle(1, "O1+do"); + } +| OBASE DECR + { + bundle(1, "Od1-o"); + } +| DECR OBASE + { + bundle(1, "O1-do"); + } +| LETTER '(' cargs ')' + { + bundle(4, $3, "l", getf($1), "x"); + } +| LETTER '(' ')' + { + bundle(3, "l", getf($1), "x"); + } +| LETTER = { + bundle(2, "l", $1); + } +| LENGTH '(' e ')' + { + bundle(2, $3, "Z"); + } +| SCALE '(' e ')' + { + bundle(2, $3, "X"); + } +| '?' + { + bundle(1, "?"); + } +| SQRT '(' e ')' + { + bundle(2, $3, "v"); + } +| '~' LETTER + { + bundle(2, "L", $2); + } +| SCALE + { + bundle(1, "K"); + } +| BASE + { + bundle(1, "I"); + } +| OBASE + { + bundle(1, "O"); + } +| '-' e + { + bundle(3, " 0", $2, "-"); + } +| e '+' e + { + bundle(3, $1, $3, "+"); + } +| e '-' e + { + bundle(3, $1, $3, "-"); + } +| e '*' e + { + bundle(3, $1, $3, "*"); + } +| e '/' e + { + bundle(3, $1, $3, "/"); + } +| e '%' e + { + bundle(3, $1, $3, "%%"); + } +| e '^' e + { + bundle(3, $1, $3, "^"); + } + +ase: + LETTER '=' e + { + bundle(3, $3, "ds", $1); + } +| LETTER '[' e ']' '=' e + { + bundle(5, $6, "d", $3, ":", geta($1)); + } +| LETTER EQOP e + { + bundle(6, "l", $1, $3, $2, "ds", $1); + } +| LETTER '[' e ']' EQOP e + { + bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":", geta($1)); + } + +e: + ase +| nase + +cargs: + eora +| cargs ',' eora + { + bundle(2, $1, $3); + } + +eora: + e +| LETTER '[' ']' + { + bundle(2, "l", geta($1)); + } + +cons: + constant + { + *cp++ = 0; + } + +constant: + '_' + { + $<cptr>$ = cp; + *cp++ = '_'; + } +| DIGIT + { + $<cptr>$ = cp; + *cp++ = $1; + } +| constant DIGIT + { + *cp++ = $2; + } + +crs: + = + { + $$ = cp; + *cp++ = '<'; + *cp++ = crs/100+'0'; + *cp++ = (crs%100)/10+'0'; + *cp++ = crs%10+'0'; + *cp++ = '>'; + *cp++ = '\0'; + if(crs++ >= 220) { + yyerror("program too big"); + getout(); + } + bstack[bindx++] = lev++; + } + +def: + _DEFINE LETTER '(' + { + $$ = getf($2); + pre = (int*)""; + post = (int*)""; + lev = 1; + bindx = 0; + bstack[bindx] = 0; + } + +dargs: +| lora + { + pp((char*)$1); + } +| dargs ',' lora + { + pp((char*)$3); + } + +dlets: + lora + { + tp((char*)$1); + } +| dlets ',' lora + { + tp((char*)$3); + } + +lora: + LETTER + { + $<cptr>$=$1; + } +| LETTER '[' ']' + { + $$ = geta($1); + } + +%% + +int +yylex(void) +{ + int c, ch; + +restart: + c = getch(); + peekc = -1; + while(c == ' ' || c == '\t') + c = getch(); + if(c == '\\') { + getch(); + goto restart; + } + if(c >= 'a' && c <= 'z') { + /* look ahead to look for reserved words */ + peekc = getch(); + if(peekc >= 'a' && peekc <= 'z') { /* must be reserved word */ + if(c=='p' && peekc=='r') { + c = _PRINT; + goto skip; + } + if(c=='i' && peekc=='f') { + c = _IF; + goto skip; + } + if(c=='w' && peekc=='h') { + c = _WHILE; + goto skip; + } + if(c=='f' && peekc=='o') { + c = _FOR; + goto skip; + } + if(c=='s' && peekc=='q') { + c = SQRT; + goto skip; + } + if(c=='r' && peekc=='e') { + c = _RETURN; + goto skip; + } + if(c=='b' && peekc=='r') { + c = _BREAK; + goto skip; + } + if(c=='d' && peekc=='e') { + c = _DEFINE; + goto skip; + } + if(c=='s' && peekc=='c') { + c = SCALE; + goto skip; + } + if(c=='b' && peekc=='a') { + c = BASE; + goto skip; + } + if(c=='i' && peekc=='b') { + c = BASE; + goto skip; + } + if(c=='o' && peekc=='b') { + c = OBASE; + goto skip; + } + if(c=='d' && peekc=='i') { + c = FFF; + goto skip; + } + if(c=='a' && peekc=='u') { + c = _AUTO; + goto skip; + } + if(c=='l' && peekc=='e') { + c = LENGTH; + goto skip; + } + if(c=='q' && peekc=='u') + getout(); + /* could not be found */ + return ERROR; + + skip: /* skip over rest of word */ + peekc = -1; + for(;;) { + ch = getch(); + if(ch < 'a' || ch > 'z') + break; + } + peekc = ch; + return c; + } + + /* usual case; just one single letter */ + yylval.cptr = letr[c-'a']; + return LETTER; + } + if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { + yylval.cc = c; + return DIGIT; + } + switch(c) { + case '.': + return DOT; + case '*': + yylval.cptr = "*"; + return cpeek('=', EQOP, c); + case '%': + yylval.cptr = "%%"; + return cpeek('=', EQOP, c); + case '^': + yylval.cptr = "^"; + return cpeek('=', EQOP, c); + case '+': + ch = cpeek('=', EQOP, c); + if(ch == EQOP) { + yylval.cptr = "+"; + return ch; + } + return cpeek('+', INCR, c); + case '-': + ch = cpeek('=', EQOP, c); + if(ch == EQOP) { + yylval.cptr = "-"; + return ch; + } + return cpeek('-', DECR, c); + case '=': + return cpeek('=', EQ, '='); + case '<': + return cpeek('=', LE, '<'); + case '>': + return cpeek('=', GE, '>'); + case '!': + return cpeek('=', NE, '!'); + case '/': + ch = cpeek('=', EQOP, c); + if(ch == EQOP) { + yylval.cptr = "/"; + return ch; + } + if(peekc == '*') { + peekc = -1; + for(;;) { + ch = getch(); + if(ch == '*') { + peekc = getch(); + if(peekc == '/') { + peekc = -1; + goto restart; + } + } + } + } + return c; + case '"': + yylval.cptr = str; + while((c=getch()) != '"'){ + *str++ = c; + if(str >= &string[999]){ + yyerror("string space exceeded"); + getout(); + } + } + *str++ = 0; + return QSTR; + default: + return c; + } +} + +int +cpeek(int c, int yes, int no) +{ + + peekc = getch(); + if(peekc == c) { + peekc = -1; + return yes; + } + return no; +} + +int +getch(void) +{ + long ch; + +loop: + ch = peekc; + if(ch < 0){ + if(in == 0) + ch = -1; + else + ch = Bgetc(in); + } + peekc = -1; + if(ch >= 0) + return ch; + ifile++; + if(ifile > sargc) { + if(ifile >= sargc+2) + getout(); + in = &stdin; + Binit(in, 0, OREAD); + ln = 0; + goto loop; + } + Bterm(in); + if((in = Bopen(sargv[ifile], OREAD)) != 0){ + ln = 0; + ss = sargv[ifile]; + goto loop; + } + yyerror("cannot open input file"); + return 0; /* shut up ken */ +} + +int* +bundle(int a, ...) +{ + int i, *p, *q; + + p = &a; + i = *p++; + q = bsp_nxt; + if(bdebug) + fprint(2, "bundle %d elements at %lx\n", i, q); + while(i-- > 0) { + if(bsp_nxt >= &bspace[bsp_max]) + yyerror("bundling space exceeded"); + *bsp_nxt++ = *p++; + } + *bsp_nxt++ = 0; + yyval.iptr = q; + return q; +} + +void +routput(int *p) +{ + if(bdebug) + fprint(2, "routput(%lx)\n", p); + if(p >= &bspace[0] && p < &bspace[bsp_max]) { + /* part of a bundle */ + while(*p != 0) + routput((int*)(*p++)); + } else + Bprint(&stdout, (char*)p); /* character string */ +} + +void +output(int *p) +{ + routput(p); + bsp_nxt = &bspace[0]; + Bprint(&stdout, "\n"); + Bflush(&stdout); + cp = cary; + crs = rcrs; +} + +void +conout(int *p, char *s) +{ + Bprint(&stdout, "["); + routput(p); + Bprint(&stdout, "]s%s\n", s); + Bflush(&stdout); + lev--; +} + +void +yyerror(char *s, ...) +{ + if(ifile > sargc) + ss = "teletype"; + Bprint(&stdout, "c[%s on line %d, %s]pc\n", s, ln+1, ss); + Bflush(&stdout); + cp = cary; + crs = rcrs; + bindx = 0; + lev = 0; + bsp_nxt = &bspace[0]; +} + +void +pp(char *s) +{ + /* puts the relevant stuff on pre and post for the letter s */ + bundle(3, "S", s, pre); + pre = yyval.iptr; + bundle(4, post, "L", s, "s."); + post = yyval.iptr; +} + +void +tp(char *s) +{ + /* same as pp, but for temps */ + bundle(3, "0S", s, pre); + pre = yyval.iptr; + bundle(4, post, "L", s, "s."); + post = yyval.iptr; +} + +void +yyinit(int argc, char **argv) +{ + Binit(&stdout, 1, OWRITE); + sargv = argv; + sargc = argc - 1; + if(sargc == 0) { + in = &stdin; + Binit(in, 0, OREAD); + } else if((in = Bopen(sargv[1], OREAD)) == 0) + yyerror("cannot open input file"); + ifile = 1; + ln = 0; + ss = sargv[1]; +} + +void +getout(void) +{ + Bprint(&stdout, "q"); + Bflush(&stdout); + exits(0); +} + +int* +getf(char *p) +{ + return (int*)funtab[*p - 'a']; +} + +int* +geta(char *p) +{ + return (int*)atab[*p - 'a']; +} + +void +main(int argc, char **argv) +{ + int p[2]; + + while(argc > 1 && *argv[1] == '-') { + switch(argv[1][1]) { + case 'd': + bdebug++; + break; + case 'c': + cflag++; + break; + case 'l': + lflag++; + break; + case 's': + sflag++; + break; + default: + fprint(2, "Usage: bc [-l] [-c] [file ...]\n"); + exits("usage"); + } + argc--; + argv++; + } + if(lflag) { + argv--; + argc++; + argv[1] = "/sys/lib/bclib"; + } + if(cflag) { + yyinit(argc, argv); + for(;;) + yyparse(); + exits(0); + } + pipe(p); + if(fork() == 0) { + dup(p[1], 1); + close(p[0]); + close(p[1]); + yyinit(argc, argv); + for(;;) + yyparse(); + } + dup(p[0], 0); + close(p[0]); + close(p[1]); + execl("/bin/dc", "dc", 0); +} diff --git a/src/cmd/jpg/mkfile b/src/cmd/jpg/mkfile index 198f8e2f..cdefe413 100644 --- a/src/cmd/jpg/mkfile +++ b/src/cmd/jpg/mkfile @@ -38,12 +38,12 @@ torgbv.$O: ycbcr.h rgbv.h ycbcr.h: rgbycc.c 9c rgbycc.c - 9l -o o.rgbycc rgbycc.c + 9l -o o.rgbycc rgbycc.o -ldraw -l9 ./o.rgbycc >ycbcr.h rgbv.h: rgbrgbv.c 9c rgbrgbv.c - 9l -o o.rgbrgbv rgbrgbv.c + 9l -o o.rgbrgbv rgbrgbv.o -ldraw -l9 ./o.rgbrgbv >rgbv.h nuke:V: nuke-headers diff --git a/src/cmd/mkfile b/src/cmd/mkfile index 1b064ebc..ab348260 100644 --- a/src/cmd/mkfile +++ b/src/cmd/mkfile @@ -1,8 +1,7 @@ <$PLAN9/src/mkhdr -TARG=`ls *.c | sed 's/\.c//'` -LDFLAGS=$LDFLAGS -L$X11/lib -lX11 -SHORTLIB=sec fs mux regexp9 draw thread bio 9 +TARG=`ls *.[cy] | sed 's/\.c//'` +SHORTLIB=sec fs mux regexp9 thread bio 9 <$PLAN9/src/mkmany @@ -11,4 +10,21 @@ DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"` <$PLAN9/src/mkdirs -dir-install: $PLAN9/bin/yacc +dir-all dir-install: $PLAN9/bin/9yacc + +XLIB=draw bio 9 +$O.clock: clock.$O ${XLIB:%=$PLAN9/lib/lib%.a} + $LD -o $target $prereq -L$X11/lib -lX11 + +$O.tweak: tweak.$O ${XLIB:%=$PLAN9/lib/lib%.a} + $LD -o $target $prereq -L$X11/lib -lX11 + +%.tab.h %.tab.c: %.y + $YACC $YFLAGS -s $stem $prereq + +%.o: %.tab.c + 9c -o $target $stem.tab.c + +CLEANFILES=$CLEANFILES bc.tab.[ch] units.tab.[ch] + + diff --git a/src/cmd/mtime.c b/src/cmd/mtime.c new file mode 100644 index 00000000..db5ea490 --- /dev/null +++ b/src/cmd/mtime.c @@ -0,0 +1,33 @@ +#include <u.h> +#include <libc.h> + +void +usage(void) +{ + fprint(2, "usage: mtime file...\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int errors, i; + Dir *d; + + ARGBEGIN{ + default: + usage(); + }ARGEND + + errors = 0; + for(i=0; i<argc; i++){ + if((d = dirstat(argv[i])) == nil){ + fprint(2, "stat %s: %r\n", argv[i]); + errors = 1; + }else{ + print("%11lud %s\n", d->mtime, argv[i]); + free(d); + } + } + exits(errors ? "errors" : nil); +} diff --git a/src/cmd/news.c b/src/cmd/news.c new file mode 100644 index 00000000..c6a99a30 --- /dev/null +++ b/src/cmd/news.c @@ -0,0 +1,231 @@ +/* + * news foo prints /lib/news/foo + * news -a prints all news items, latest first + * news -n lists names of new items + * news prints items changed since last news + */ + +#include <u.h> +#include <libc.h> +#include <bio.h> + +#define NINC 50 /* Multiples of directory allocation */ +char *NEWS = "#9/news"; +char TFILE[] = "%s/lib/newstime"; + +/* + * The following items should not be printed. + */ +char* ignore[] = +{ + "core", + "dead.letter", + 0 +}; + +typedef +struct +{ + long time; + char *name; + vlong length; +} File; +File* n_list; +int n_count; +int n_items; +Biobuf bout; + +int fcmp(const void *a, const void *b); +void read_dir(int update); +void print_item(char *f); +void eachitem(void (*emit)(char*), int all, int update); +void note(char *s); + +void +main(int argc, char *argv[]) +{ + int i; + + NEWS = unsharp(NEWS); + + Binit(&bout, 1, OWRITE); + if(argc == 1) { + eachitem(print_item, 0, 1); + exits(0); + } + ARGBEGIN{ + case 'a': /* print all */ + eachitem(print_item, 1, 0); + break; + + case 'n': /* names only */ + eachitem(note, 0, 0); + if(n_items) + Bputc(&bout, '\n'); + break; + + default: + fprint(2, "news: bad option %c\n", ARGC()); + exits("usage"); + }ARGEND + for(i=0; i<argc; i++) + print_item(argv[i]); + exits(0); +} + +int +fcmp(const void *a, const void *b) +{ + long x; + + x = ((File*)b)->time - ((File*)a)->time; + if(x < 0) + return -1; + if(x > 0) + return 1; + return 0; +} + +/* + * read_dir: get the file names and modification dates for the + * files in /usr/news into n_list; sort them in reverse by + * modification date. + */ +void +read_dir(int update) +{ + Dir *d; + char newstime[100], *home; + int i, j, n, na, fd; + + n_count = 0; + n_list = malloc(NINC*sizeof(File)); + na = NINC; + home = getenv("home"); + if(home) { + sprint(newstime, TFILE, home); + d = dirstat(newstime); + if(d != nil) { + n_list[n_count].name = strdup(""); + n_list[n_count].time =d->mtime-1; + n_list[n_count].length = 0; + n_count++; + free(d); + } + if(update) { + fd = create(newstime, OWRITE, 0644); + if(fd >= 0) + close(fd); + } + } + fd = open(NEWS, OREAD); + if(fd < 0) { + fprint(2, "news: "); + perror(NEWS); + exits(NEWS); + } + + n = dirreadall(fd, &d); + for(i=0; i<n; i++) { + for(j=0; ignore[j]; j++) + if(strcmp(ignore[j], d[i].name) == 0) + goto ign; + if(na <= n_count) { + na += NINC; + n_list = realloc(n_list, na*sizeof(File)); + } + n_list[n_count].name = strdup(d[i].name); + n_list[n_count].time = d[i].mtime; + n_list[n_count].length = d[i].length; + n_count++; + ign:; + } + free(d); + + close(fd); + qsort(n_list, n_count, sizeof(File), fcmp); +} + +void +print_item(char *file) +{ + char name[4096], *p, *ep; + Dir *dbuf; + int f, c; + int bol, bop; + + sprint(name, "%s/%s", NEWS, file); + f = open(name, OREAD); + if(f < 0) { + fprint(2, "news: "); + perror(name); + return; + } + strcpy(name, "..."); + dbuf = dirfstat(f); + if(dbuf == nil) + return; + Bprint(&bout, "\n%s (%s) %s\n", file, + dbuf->muid[0]? dbuf->muid : dbuf->uid, + asctime(localtime(dbuf->mtime))); + free(dbuf); + + bol = 1; /* beginning of line ...\n */ + bop = 1; /* beginning of page ...\n\n */ + for(;;) { + c = read(f, name, sizeof(name)); + if(c <= 0) + break; + p = name; + ep = p+c; + while(p < ep) { + c = *p++; + if(c == '\n') { + if(!bop) { + Bputc(&bout, c); + if(bol) + bop = 1; + bol = 1; + } + continue; + } + if(bol) { + Bputc(&bout, '\t'); + bol = 0; + bop = 0; + } + Bputc(&bout, c); + } + } + if(!bol) + Bputc(&bout, '\n'); + close(f); +} + +void +eachitem(void (*emit)(char*), int all, int update) +{ + int i; + + read_dir(update); + for(i=0; i<n_count; i++) { + if(n_list[i].name[0] == 0) { /* newstime */ + if(all) + continue; + break; + } + if(n_list[i].length == 0) /* in progress */ + continue; + (*emit)(n_list[i].name); + } +} + +void +note(char *file) +{ + + if(!n_items) + Bprint(&bout, "news:"); + Bprint(&bout, " %s", file); + n_items++; +} diff --git a/src/cmd/primes.c b/src/cmd/primes.c new file mode 100644 index 00000000..0e926545 --- /dev/null +++ b/src/cmd/primes.c @@ -0,0 +1,131 @@ +#include <u.h> +#include <libc.h> + +#define ptsiz (sizeof(pt)/sizeof(pt[0])) +#define whsiz (sizeof(wheel)/sizeof(wheel[0])) +#define tabsiz (sizeof(table)/sizeof(table[0])) +#define tsiz8 (tabsiz*8) + +double big = 9.007199254740992e15; + +int pt[] = +{ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97,101,103,107,109,113, + 127,131,137,139,149,151,157,163,167,173, + 179,181,191,193,197,199,211,223,227,229, +}; +double wheel[] = +{ + 10, 2, 4, 2, 4, 6, 2, 6, 4, 2, + 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, + 8, 4, 2, 4, 2, 4, 8, 6, 4, 6, + 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, + 2, 6, 4, 2, 4, 2,10, 2, +}; +uchar table[1000]; +uchar bittab[] = +{ + 1, 2, 4, 8, 16, 32, 64, 128, +}; + +void mark(double nn, long k); +void ouch(void); + +void +main(int argc, char *argp[]) +{ + int i; + double k, temp, v, limit, nn; + + if(argc <= 1) { + fprint(2, "usage: primes starting [ending]\n"); + exits("usage"); + } + nn = atof(argp[1]); + limit = big; + if(argc > 2) { + limit = atof(argp[2]); + if(limit < nn) + exits(0); + if(limit > big) + ouch(); + } + if(nn < 0 || nn > big) + ouch(); + if(nn == 0) + nn = 1; + + if(nn < 230) { + for(i=0; i<ptsiz; i++) { + if(pt[i] < nn) + continue; + if(pt[i] > limit) + exits(0); + print("%d\n", pt[i]); + if(limit >= big) + exits(0); + } + nn = 230; + } + + modf(nn/2, &temp); + nn = 2.*temp + 1; +/* + * clear the sieve table. + */ + for(;;) { + for(i=0; i<tabsiz; i++) + table[i] = 0; +/* + * run the sieve. + */ + v = sqrt(nn+tsiz8); + mark(nn, 3); + mark(nn, 5); + mark(nn, 7); + for(i=0,k=11; k<=v; k+=wheel[i]) { + mark(nn, k); + i++; + if(i >= whsiz) + i = 0; + } +/* + * now get the primes from the table + * and print them. + */ + for(i=0; i<tsiz8; i+=2) { + if(table[i>>3] & bittab[i&07]) + continue; + temp = nn + i; + if(temp > limit) + exits(0); + print("%.0f\n", temp); + if(limit >= big) + exits(0); + } + nn += tsiz8; + } +} + +void +mark(double nn, long k) +{ + double t1; + long j; + + modf(nn/k, &t1); + j = k*t1 - nn; + if(j < 0) + j += k; + for(; j<tsiz8; j+=k) + table[j>>3] |= bittab[j&07]; +} + +void +ouch(void) +{ + fprint(2, "limits exceeded\n"); + exits("limits"); +} diff --git a/src/cmd/units.y b/src/cmd/units.y new file mode 100644 index 00000000..372295fd --- /dev/null +++ b/src/cmd/units.y @@ -0,0 +1,795 @@ +%{ +#include <u.h> +#include <libc.h> +#include <bio.h> + +enum +{ + Ndim = 15, /* number of dimensions */ + Nsym = 40, /* size of a name */ + Nvar = 203, /* hash table size */ + Maxe = 695, /* log of largest number */ +}; + +typedef struct Var Var; +typedef struct Node Node; +typedef struct Prefix Prefix; + +struct Node +{ + double val; + schar dim[Ndim]; +}; +struct Var +{ + Rune name[Nsym]; + Node node; + Var* link; +}; +struct Prefix +{ + double val; + char* name; + Rune* pname; +}; + +char buf[100]; +int digval; +Biobuf* fi; +Biobuf linebuf; +Var* fund[Ndim]; +Rune line[1000]; +ulong lineno; +int linep; +int nerrors; +Node one; +int peekrune; +Node retnode1; +Node retnode2; +Node retnode; +Rune sym[Nsym]; +Var* vars[Nvar]; +int vflag; + +#define div unitsdiv + +extern void add(Node*, Node*, Node*); +extern void div(Node*, Node*, Node*); +extern int specialcase(Node*, Node*, Node*); +extern double fadd(double, double); +extern double fdiv(double, double); +extern double fmul(double, double); +extern int gdigit(void*); +extern Var* lookup(int); +extern void main(int, char*[]); +extern void mul(Node*, Node*, Node*); +extern void ofile(void); +extern double pname(void); +extern void printdim(char*, int, int); +extern int ralpha(int); +extern int readline(void); +extern void sub(Node*, Node*, Node*); +extern int Ufmt(Fmt*); +extern void xpn(Node*, Node*, int); +extern void yyerror(char*, ...); +extern int yylex(void); +extern int yyparse(void); + +typedef Node* indnode; +/* #pragma varargck type "U" indnode */ + +%} +%union +{ + Node node; + Var* var; + int numb; + double val; +} + +%type <node> prog expr expr0 expr1 expr2 expr3 expr4 + +%token <val> VAL +%token <var> VAR +%token <numb> SUP +%% +prog: + ':' VAR expr + { + int f; + + f = $2->node.dim[0]; + $2->node = $3; + $2->node.dim[0] = 1; + if(f) + yyerror("redefinition of %S", $2->name); + else + if(vflag) + print("%S\t%U\n", $2->name, &$2->node); + } +| ':' VAR '#' + { + int f, i; + + for(i=1; i<Ndim; i++) + if(fund[i] == 0) + break; + if(i >= Ndim) { + yyerror("too many dimensions"); + i = Ndim-1; + } + fund[i] = $2; + + f = $2->node.dim[0]; + $2->node = one; + $2->node.dim[0] = 1; + $2->node.dim[i] = 1; + if(f) + yyerror("redefinition of %S", $2->name); + else + if(vflag) + print("%S\t#\n", $2->name); + } +| '?' expr + { + retnode1 = $2; + } +| '?' + { + retnode1 = one; + } + +expr: + expr4 +| expr '+' expr4 + { + add(&$$, &$1, &$3); + } +| expr '-' expr4 + { + sub(&$$, &$1, &$3); + } + +expr4: + expr3 +| expr4 '*' expr3 + { + mul(&$$, &$1, &$3); + } +| expr4 '/' expr3 + { + div(&$$, &$1, &$3); + } + +expr3: + expr2 +| expr3 expr2 + { + mul(&$$, &$1, &$2); + } + +expr2: + expr1 +| expr2 SUP + { + xpn(&$$, &$1, $2); + } +| expr2 '^' expr1 + { + int i; + + for(i=1; i<Ndim; i++) + if($3.dim[i]) { + yyerror("exponent has units"); + $$ = $1; + break; + } + if(i >= Ndim) { + i = $3.val; + if(i != $3.val) + yyerror("exponent not integral"); + xpn(&$$, &$1, i); + } + } + +expr1: + expr0 +| expr1 '|' expr0 + { + div(&$$, &$1, &$3); + } + +expr0: + VAR + { + if($1->node.dim[0] == 0) { + yyerror("undefined %S", $1->name); + $$ = one; + } else + $$ = $1->node; + } +| VAL + { + $$ = one; + $$.val = $1; + } +| '(' expr ')' + { + $$ = $2; + } +%% + +int +yylex(void) +{ + int c, i; + + c = peekrune; + peekrune = ' '; + +loop: + if((c >= '0' && c <= '9') || c == '.') + goto numb; + if(ralpha(c)) + goto alpha; + switch(c) { + case ' ': + case '\t': + c = line[linep++]; + goto loop; + case 0xd7: + return 0x2a; + case 0xf7: + return 0x2f; + case 0xb9: + case 0x2071: + yylval.numb = 1; + return SUP; + case 0xb2: + case 0x2072: + yylval.numb = 2; + return SUP; + case 0xb3: + case 0x2073: + yylval.numb = 3; + return SUP; + } + return c; + +alpha: + memset(sym, 0, sizeof(sym)); + for(i=0;; i++) { + if(i < nelem(sym)) + sym[i] = c; + c = line[linep++]; + if(!ralpha(c)) + break; + } + sym[nelem(sym)-1] = 0; + peekrune = c; + yylval.var = lookup(0); + return VAR; + +numb: + digval = c; + yylval.val = fmtcharstod(gdigit, 0); + return VAL; +} + +void +main(int argc, char *argv[]) +{ + char *file; + + ARGBEGIN { + default: + print("usage: units [-v] [file]\n"); + exits("usage"); + case 'v': + vflag = 1; + break; + } ARGEND + + file = unsharp("#9/lib/units"); + if(argc > 0) + file = argv[0]; + fi = Bopen(file, OREAD); + if(fi == 0) { + print("cant open: %s\n", file); + exits("open"); + } + fmtinstall('U', Ufmt); + one.val = 1; + + /* + * read the 'units' file to + * develope a database + */ + lineno = 0; + for(;;) { + lineno++; + if(readline()) + break; + if(line[0] == 0 || line[0] == '/') + continue; + peekrune = ':'; + yyparse(); + } + + /* + * read the console to + * print ratio of pairs + */ + Bterm(fi); + fi = &linebuf; + Binit(fi, 0, OREAD); + lineno = 0; + for(;;) { + if(lineno & 1) + print("you want: "); + else + print("you have: "); + if(readline()) + break; + peekrune = '?'; + nerrors = 0; + yyparse(); + if(nerrors) + continue; + if(lineno & 1) { + if(specialcase(&retnode, &retnode2, &retnode1)) + print("\tis %U\n", &retnode); + else { + div(&retnode, &retnode2, &retnode1); + print("\t* %U\n", &retnode); + div(&retnode, &retnode1, &retnode2); + print("\t/ %U\n", &retnode); + } + } else + retnode2 = retnode1; + lineno++; + } + print("\n"); + exits(0); +} + +/* + * all characters that have some + * meaning. rest are usable as names + */ +int +ralpha(int c) +{ + switch(c) { + case 0: + case '+': + case '-': + case '*': + case '/': + case '[': + case ']': + case '(': + case ')': + case '^': + case ':': + case '?': + case ' ': + case '\t': + case '.': + case '|': + case '#': + case 0xb9: + case 0x2071: + case 0xb2: + case 0x2072: + case 0xb3: + case 0x2073: + case 0xd7: + case 0xf7: + return 0; + } + return 1; +} + +int +gdigit(void *v) +{ + int c; + + USED(v); + c = digval; + if(c) { + digval = 0; + return c; + } + c = line[linep++]; + peekrune = c; + return c; +} + +void +yyerror(char *fmt, ...) +{ + va_list arg; + + /* + * hack to intercept message from yaccpar + */ + if(strcmp(fmt, "syntax error") == 0) { + yyerror("syntax error, last name: %S", sym); + return; + } + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + print("%ld: %S\n\t%s\n", lineno, line, buf); + nerrors++; + if(nerrors > 5) { + print("too many errors\n"); + exits("errors"); + } +} + +void +add(Node *c, Node *a, Node *b) +{ + int i, d; + + for(i=0; i<Ndim; i++) { + d = a->dim[i]; + c->dim[i] = d; + if(d != b->dim[i]) + yyerror("add must be like units"); + } + c->val = fadd(a->val, b->val); +} + +void +sub(Node *c, Node *a, Node *b) +{ + int i, d; + + for(i=0; i<Ndim; i++) { + d = a->dim[i]; + c->dim[i] = d; + if(d != b->dim[i]) + yyerror("sub must be like units"); + } + c->val = fadd(a->val, -b->val); +} + +void +mul(Node *c, Node *a, Node *b) +{ + int i; + + for(i=0; i<Ndim; i++) + c->dim[i] = a->dim[i] + b->dim[i]; + c->val = fmul(a->val, b->val); +} + +void +div(Node *c, Node *a, Node *b) +{ + int i; + + for(i=0; i<Ndim; i++) + c->dim[i] = a->dim[i] - b->dim[i]; + c->val = fdiv(a->val, b->val); +} + +void +xpn(Node *c, Node *a, int b) +{ + int i; + + *c = one; + if(b < 0) { + b = -b; + for(i=0; i<b; i++) + div(c, c, a); + } else + for(i=0; i<b; i++) + mul(c, c, a); +} + +int +specialcase(Node *c, Node *a, Node *b) +{ + int i, d, d1, d2; + + d1 = 0; + d2 = 0; + for(i=1; i<Ndim; i++) { + d = a->dim[i]; + if(d) { + if(d != 1 || d1) + return 0; + d1 = i; + } + d = b->dim[i]; + if(d) { + if(d != 1 || d2) + return 0; + d2 = i; + } + } + if(d1 == 0 || d2 == 0) + return 0; + + if(memcmp(fund[d1]->name, L"°C", 3*sizeof(Rune)) == 0 && + memcmp(fund[d2]->name, L"°F", 3*sizeof(Rune)) == 0 && + b->val == 1) { + memcpy(c->dim, b->dim, sizeof(c->dim)); + c->val = a->val * 9. / 5. + 32.; + return 1; + } + + if(memcmp(fund[d1]->name, L"°F", 3*sizeof(Rune)) == 0 && + memcmp(fund[d2]->name, L"°C", 3*sizeof(Rune)) == 0 && + b->val == 1) { + memcpy(c->dim, b->dim, sizeof(c->dim)); + c->val = (a->val - 32.) * 5. / 9.; + return 1; + } + return 0; +} + +void +printdim(char *str, int d, int n) +{ + Var *v; + + if(n) { + v = fund[d]; + if(v) + sprint(strchr(str, 0), " %S", v->name); + else + sprint(strchr(str, 0), " [%d]", d); + switch(n) { + case 1: + break; + case 2: + strcat(str, "²"); + break; + case 3: + strcat(str, "³"); + break; + default: + sprint(strchr(str, 0), "^%d", n); + } + } +} + +int +Ufmt(Fmt *fp) +{ + char str[200]; + Node *n; + int f, i, d; + + n = va_arg(fp->args, Node*); + sprint(str, "%g", n->val); + + f = 0; + for(i=1; i<Ndim; i++) { + d = n->dim[i]; + if(d > 0) + printdim(str, i, d); + else + if(d < 0) + f = 1; + } + + if(f) { + strcat(str, " /"); + for(i=1; i<Ndim; i++) { + d = n->dim[i]; + if(d < 0) + printdim(str, i, -d); + } + } + + return fmtstrcpy(fp, str); +} + +int +readline(void) +{ + int i, c; + + linep = 0; + for(i=0;; i++) { + c = Bgetrune(fi); + if(c < 0) + return 1; + if(c == '\n') + break; + if(i < nelem(line)) + line[i] = c; + } + if(i >= nelem(line)) + i = nelem(line)-1; + line[i] = 0; + return 0; +} + +Var* +lookup(int f) +{ + int i; + Var *v, *w; + double p; + ulong h; + + h = 0; + for(i=0; sym[i]; i++) + h = h*13 + sym[i]; + h %= nelem(vars); + + for(v=vars[h]; v; v=v->link) + if(memcmp(sym, v->name, sizeof(sym)) == 0) + return v; + if(f) + return 0; + v = malloc(sizeof(*v)); + if(v == nil) { + fprint(2, "out of memory\n"); + exits("mem"); + } + memset(v, 0, sizeof(*v)); + memcpy(v->name, sym, sizeof(sym)); + v->link = vars[h]; + vars[h] = v; + + p = 1; + for(;;) { + p = fmul(p, pname()); + if(p == 0) + break; + w = lookup(1); + if(w) { + v->node = w->node; + v->node.val = fmul(v->node.val, p); + break; + } + } + return v; +} + +Prefix prefix[] = +{ + 1e-24, "yocto", 0, + 1e-21, "zepto", 0, + 1e-18, "atto", 0, + 1e-15, "femto", 0, + 1e-12, "pico", 0, + 1e-9, "nano", 0, + 1e-6, "micro", 0, + 1e-6, "μ", 0, + 1e-3, "milli", 0, + 1e-2, "centi", 0, + 1e-1, "deci", 0, + 1e1, "deka", 0, + 1e2, "hecta", 0, + 1e2, "hecto", 0, + 1e3, "kilo", 0, + 1e6, "mega", 0, + 1e6, "meg", 0, + 1e9, "giga", 0, + 1e12, "tera", 0, + 1e15, "peta", 0, + 1e18, "exa", 0, + 1e21, "zetta", 0, + 1e24, "yotta", 0, + 0, 0, 0, +}; + +double +pname(void) +{ + Rune *p; + int i, j, c; + + /* + * rip off normal prefixs + */ + if(prefix[0].pname == nil){ + for(i=0; prefix[i].name; i++) + prefix[i].pname = runesmprint("%s", prefix[i].name); + } + + for(i=0; p=prefix[i].pname; i++) { + for(j=0; c=p[j]; j++) + if(c != sym[j]) + goto no; + memmove(sym, sym+j, (Nsym-j)*sizeof(*sym)); + memset(sym+(Nsym-j), 0, j*sizeof(*sym)); + return prefix[i].val; + no:; + } + + /* + * rip off 's' suffixes + */ + for(j=0; sym[j]; j++) + ; + j--; + /* j>1 is special hack to disallow ms finding m */ + if(j > 1 && sym[j] == 's') { + sym[j] = 0; + return 1; + } + return 0; +} + +/* + * careful floating point + */ +double +fmul(double a, double b) +{ + double l; + + if(a <= 0) { + if(a == 0) + return 0; + l = log(-a); + } else + l = log(a); + + if(b <= 0) { + if(b == 0) + return 0; + l += log(-b); + } else + l += log(b); + + if(l > Maxe) { + yyerror("overflow in multiply"); + return 1; + } + if(l < -Maxe) { + yyerror("underflow in multiply"); + return 0; + } + return a*b; +} + +double +fdiv(double a, double b) +{ + double l; + + if(a <= 0) { + if(a == 0) + return 0; + l = log(-a); + } else + l = log(a); + + if(b <= 0) { + if(b == 0) { + yyerror("division by zero"); + return 1; + } + l -= log(-b); + } else + l -= log(b); + + if(l > Maxe) { + yyerror("overflow in divide"); + return 1; + } + if(l < -Maxe) { + yyerror("underflow in divide"); + return 0; + } + return a/b; +} + +double +fadd(double a, double b) +{ + return a + b; +} |