1070 lines · 18.6 KB · Text
RawDownload
%{#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#include <mp.h>#include <thread.h>#undef long#include <unistd.h> int inbase = 10, outbase, divmode, sep, heads, fail, prompt, eof;enum { MAXARGS = 16 }; typedef struct Num Num;struct Num {	mpint i;	int b;	Ref r;};enum { STRONG = 0x100 }; void *emalloc(int n){	void *v;		v = malloc(n);	if(v == nil)		sysfatal("malloc: %r");	memset(v, 0, n);	setmalloctag(v, getcallerpc(&n));	return v;} void *error(char *fmt, ...){	va_list va;	Fmt f;	char buf[256];		fmtfdinit(&f, 2, buf, sizeof(buf));	va_start(va, fmt);	fmtvprint(&f, fmt, va);	fmtrune(&f, '\n');	fmtfdflush(&f);	va_end(va);	fail++;	return nil;} Num *numalloc(void){	Num *r;		r = emalloc(sizeof(Num));	r->r.ref = 1;	r->i.p = emalloc(sizeof(mpdigit));	mpassign(mpzero, r);	return r;} Num *numincref(Num *n){	incref(&n->r);	return n;} Num *numdecref(Num *n){	if(n == nil) return nil;	if(decref(&n->r) == 0){		free(n->i.p);		free(n);		return nil;	}	return n;} Num *nummod(Num *n){	Num *m; 	if(n == nil) return nil;	if(n->r.ref == 1) return n;	m = numalloc();	mpassign(n, m);	m->b = n->b;	numdecref(n);	return m;} intbasemax(int a, int b){	if(a == STRONG+10 && b >= STRONG) return b;	if(b == STRONG+10 && a >= STRONG) return a;	if(a == 10) return b;	if(b == 10) return a;	if(a < b) return b;	return a;} typedef struct Symbol Symbol;struct Symbol {	enum {		SYMNONE,		SYMVAR,		SYMFUNC,	} t;	Num *val;	int nargs;	Num *(*func)(int unused, Num **); 	char *name;	Symbol *next;};Symbol *symtab[64]; Symbol *getsym(char *n, int mk){	Symbol **p;	for(p = &symtab[*n&63]; *p != nil; p = &(*p)->next)		if(strcmp((*p)->name, n) == 0)			return *p;	if(!mk) return nil;	*p = emalloc(sizeof(Symbol));	(*p)->name = strdup(n);	return *p;} static voidprinthead(int n, int s, int sp, char *t){	char *q;	int i, j, k;		for(i = 1; i < n; i *= 10)		;	while(i /= 10, i != 0){		q = t;		*--q = 0;		for(j = 0, k = 0; j < n; j += s, k++){			if(k == sep && sep != 0){				*--q = ' ';				k = 0;			}			if(j >= i || j == 0 && i == 1)				*--q = '0' + j / i % 10;			else				*--q = ' ';		}		for(j = 0; j < sp; j++)			*--q = ' ';		print("%s\n", q);	}} voidnumprint(Num *n){	int b;	int l, i, st, sp;	char *s, *t, *p, *q; 	if(n == nil) return;	if(n->b >= STRONG || n->b != 0 && outbase == 0)		b = n->b & ~STRONG;	else if(outbase == 0)		b = 10;	else		b = outbase;	s = mptoa(n, b, nil, 0);	l = strlen(s);	t = emalloc(l * 2 + 4);	q = t + l * 2 + 4;	if(heads){		switch(b){		case 16: st = 4; sp = 2; break;		case 8: st = 3; sp = 1; break;		case 2: st = 1; sp = 2; break;		default: st = 0; sp = 0;		}		if(n->i.sign < 0)			sp++;		if(st != 0)			printhead(mpsignif(n), st, sp, q);	}	*--q = 0;	for(p = s + l - 1, i = 0; p >= s && *p != '-'; p--, i++){		if(sep != 0 && i == sep){			*--q = '_';			i = 0;		}		if(*p >= 'A')			*--q = *p + ('a' - 'A');		else			*--q = *p;	}	if(mpcmp(n, mpzero) != 0)		switch(b){		case 16: *--q = 'x'; *--q = '0'; break;		case 10: if(outbase != 0 && outbase != 10 || inbase != 10) {*--q = 'd'; *--q = '0';} break;		case 8: *--q = '0'; break;		case 2: *--q = 'b'; *--q = '0'; break;		}	if(p >= s)		*--q = '-';	print("%s\n", q);	free(s);	free(t);} voidnumdecrefs(int n, Num **x){	int i;		for(i = 0; i < n; i++)		numdecref(x[i]);} Num *fncall(Symbol *s, int n, Num **x){	int i; 	if(s->t != SYMFUNC){		numdecrefs(n, x);		return error("%s: not a function", s->name);	}	else if(s->nargs >= 0 && s->nargs != n){		numdecrefs(n, x);		return error("%s: wrong number of arguments", s->name);	}	for(i = 0; i < n; i++)		if(x[i] == nil)			return nil;	return s->func(n, x);} Num *hexfix(Symbol *s){	char *b, *p, *q; 	if(inbase != 16) return nil;	if(s->val != nil) return numincref(s->val);	if(strspn(s->name, "0123456789ABCDEFabcdef_") != strlen(s->name)) return nil;	b = strdup(s->name);	for(p = b, q = b; *p != 0; p++)		if(*p != '_')			*q++ = *p;	*q = 0;	s->val = numalloc();	strtomp(b, nil, 16, s->val);	s->val->b = 16;	free(b);	return numincref(s->val);} %} %token LOEXP LOLSH LORSH LOEQ LONE LOLE LOGE LOLAND LOLOR %union {	Num *n;	Symbol *sym;	struct {		Num *x[MAXARGS];		int n;	} args;} %token <n> LNUM%token <sym> LSYMB %type <n> expr%type <args> elist elist1 %right '='%right '?'%left LOLOR%left LOLAND%left '|'%left '^'%left '&'%left LOEQ LONE%left '<' '>' LOLE LOGE%left LOLSH LORSH%left '+' '-'%left unary%left '*' '/' '%'%right LOEXP%right '$' %{	int save;	Num *last;	Num *lastp; 	extern Num *numbin(int op, Num *a, Num *b);	extern void yyerror(char *msg);	extern int yylex(void);%} %% input: | input line '\n' {		if(!fail && last != nil) {			numprint(last);			numdecref(lastp);			lastp = last;		}		fail = 0;		last = nil;	} line: stat	| line ';' stat stat: { last = nil; }	| expr { last = $1; }	| '_' { save = inbase; inbase = 10; } expr {		inbase = save;		if(mpcmp($3, mpzero) < 0)			error("no.");		if(!fail) 			sep = mptoi($3);		numdecref($3);		numdecref(last);		last = nil;	}	| '<' { save = inbase; inbase = 10; } expr {		inbase = save;		if(!fail) 			inbase = mptoi($3);		if(inbase != 2 && inbase != 8 && inbase != 10 && inbase != 16){			error("no.");			inbase = save;		}		numdecref($3);		numdecref(last);		last = nil;	}	| '>' { save = inbase; inbase = 10; } expr {		inbase = save;		save = outbase;		if(!fail) 			outbase = mptoi($3);		if(outbase != 0 && outbase != 2 && outbase != 8 && outbase != 10 && outbase != 16){			error("no.");			outbase = save;		}		numdecref($3);		numdecref(last);		last = nil;	}	| '/' { save = inbase; inbase = 10; } expr {		inbase = save;		save = divmode;		if(!fail) 			divmode = mptoi($3);		if(divmode != 0 && divmode != 1){			error("no.");			divmode = save;		}		numdecref($3);		numdecref(last);		last = nil;	}	| '\'' { save = inbase; inbase = 10; } expr {		inbase = save;		save = heads;		if(!fail) 			heads = mptoi($3);		if(heads != 0 && heads != 1){			error("no.");			heads = save;		}		numdecref($3);		numdecref(last);		last = nil;	}	| error expr: LNUM	| '(' expr ')' { $$ = $2; }	| expr '+' expr { $$ = numbin('+', $1, $3); }	| expr '-' expr { $$ = numbin('-', $1, $3); }	| expr '*' expr { $$ = numbin('*', $1, $3); }	| expr '/' expr { $$ = numbin('/', $1, $3); }	| expr '%' expr { $$ = numbin('%', $1, $3); }	| expr '&' expr { $$ = numbin('&', $1, $3); }	| expr '|' expr { $$ = numbin('|', $1, $3); }	| expr '^' expr { $$ = numbin('^', $1, $3); }		| expr LOEXP expr { $$ = numbin(LOEXP, $1, $3); }	| expr LOLSH expr { $$ = numbin(LOLSH, $1, $3); }	| expr LORSH expr { $$ = numbin(LORSH, $1, $3); }	| expr LOEQ expr { $$ = numbin(LOEQ, $1, $3); }	| expr LONE expr { $$ = numbin(LONE, $1, $3); }	| expr '<' expr { $$ = numbin('<', $1, $3); }	| expr '>' expr { $$ = numbin('>', $1, $3); }	| expr LOLE expr { $$ = numbin(LOLE, $1, $3); }	| expr LOGE expr { $$ = numbin(LOGE, $1, $3); }	| expr LOLAND expr { $$ = numbin(LOLAND, $1, $3); }	| expr LOLOR expr { $$ = numbin(LOLOR, $1, $3); }	| '+' expr %prec unary { $$ = $2; }	| '-' expr %prec unary { $$ = nummod($2); if($$ != nil) mpsub(mpzero, $$, $$); }	| '~' expr %prec unary { $$ = nummod($2); if($$ != nil) mpnot($$, $$); }	| '!' expr %prec unary { $$ = nummod($2); if($$ != nil) {itomp(mpcmp($$, mpzero) == 0, $$); $$->b = 0; } }	| '$' expr { $$ = nummod($2); if($$ != nil) {if($2->i.sign > 0) mpxtend($2, mpsignif($2), $$); else mpassign($2, $$); } }	| expr '?' expr ':' expr %prec '?' {		if($1 == nil || mpcmp($1, mpzero) != 0){			$$ = $3;			numdecref($5);		}else{			$$ = $5;			numdecref($3);		}		numdecref($1);	}	| LSYMB '(' elist ')' { $$ = fncall($1, $3.n, $3.x); }	| LSYMB {		Num *n;		$$ = nil;		switch($1->t){		case SYMVAR: $$ = numincref($1->val); break;		case SYMNONE:			n = hexfix($1);			if(n != nil) $$ = n;			else error("%s undefined", $1->name);			break;		case SYMFUNC: error("%s is a function", $1->name); break;		default: error("%s invalid here", $1->name);		}	}	| LSYMB '=' expr {		if($1->t != SYMNONE && $1->t != SYMVAR)			error("%s redefined", $1->name);		else if(!fail){			$1->t = SYMVAR;			numdecref($1->val);			$1->val = numincref($3);		}		$$ = $3;	}	| '@' {		$$ = lastp;		if($$ == nil) error("no last result");		else numincref($$);	}	| expr '$' expr { $$ = numbin('$', $1, $3); } elist: { $$.n = 0; } | elist1elist1: expr { $$.x[0] = $1; $$.n = 1; }	| elist1 ',' expr {		$$ = $1;		if($$.n >= MAXARGS)			error("too many arguments");		else			$$.x[$$.n++] = $3;	} %% typedef struct Keyword Keyword;struct Keyword {	char *name;	int tok;}; Keyword ops[] = {	"**", LOEXP,	"<<", LOLSH,	"<=", LOLE,	">>", LORSH,	">=", LOGE,	"==", LOEQ,	"&&", LOLAND,	"||", LOLOR,	"", 0,}; Keyword *optab[128];  Biobuf *in;int prompted; Num *numbin(int op, Num *a, Num *b){	mpint *r;		if(fail || a == nil || b == nil) return nil;

Lines 1–500 of 1070.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t