add new guys

This commit is contained in:
rsc 2004-04-21 23:22:06 +00:00
parent 3e63e5c271
commit 17e5fb8973
7 changed files with 2195 additions and 6 deletions

983
src/cmd/bc.y Normal file
View file

@ -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);
}

View file

@ -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

View file

@ -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]

33
src/cmd/mtime.c Normal file
View file

@ -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);
}

231
src/cmd/news.c Normal file
View file

@ -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++;
}

131
src/cmd/primes.c Normal file
View file

@ -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");
}

795
src/cmd/units.y Normal file
View file

@ -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;
}