%{#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. Load more
%{ #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; } int basemax(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 void printhead(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); } } void numprint(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); } void numdecrefs(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; } | elist1 elist1: 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;