📄 t8.c
字号:
#include "a.h"/* * 8. Number Registers * (Reg register implementation is also here.) *//* * \nx N * \n(xx N * \n+x N+=M * \n-x N-=M * * .nr R ±N M * .af R c * * formats * 1 0, 1, 2, 3, ... * 001 001, 002, 003, ... * i 0, i, ii, iii, iv, v, ... * I 0, I, II, III, IV, V, ... * a 0, a, b, ..., aa, ab, ..., zz, aaa, ... * A 0, A, B, ..., AA, AB, ..., ZZ, AAA, ... * * \gx \g(xx return format of number register * * .rr R */typedef struct Reg Reg;struct Reg{ Reg *next; Rune *name; Rune *val; Rune *fmt; int inc;};Reg *dslist;Reg *nrlist;/* * Define strings and numbers. */voiddsnr(Rune *name, Rune *val, Reg **l){ Reg *s; for(s = *l; s != nil; s = *l){ if(runestrcmp(s->name, name) == 0) break; l = &s->next; } if(val == nil){ if(s){ *l = s->next; free(s->val); free(s->fmt); free(s); } return; } if(s == nil){ s = emalloc(sizeof(Reg)); *l = s; s->name = erunestrdup(name); }else free(s->val); s->val = erunestrdup(val);}Rune*getdsnr(Rune *name, Reg *list){ Reg *s; for(s=list; s; s=s->next) if(runestrcmp(name, s->name) == 0) return s->val; return nil;}voidds(Rune *name, Rune *val){ dsnr(name, val, &dslist);}voidas(Rune *name, Rune *val){ Rune *p, *q; p = getds(name); if(p == nil) p = L(""); q = runemalloc(runestrlen(p)+runestrlen(val)+1); runestrcpy(q, p); runestrcat(q, val); ds(name, q); free(q);}Rune*getds(Rune *name){ return getdsnr(name, dslist);}voidprintds(int t){ int n, total; Reg *s; total = 0; for(s=dslist; s; s=s->next){ if(s->val) n = runestrlen(s->val); else n = 0; total += n; if(!t) fprint(2, "%S\t%d\n", s->name, n); } fprint(2, "total\t%d\n", total);}voidnr(Rune *name, int val){ Rune buf[20]; runesnprint(buf, nelem(buf), "%d", val); _nr(name, buf);}voidaf(Rune *name, Rune *fmt){ Reg *s; if(_getnr(name) == nil) _nr(name, L("0")); for(s=nrlist; s; s=s->next) if(runestrcmp(s->name, name) == 0) s->fmt = erunestrdup(fmt);}Rune*getaf(Rune *name){ Reg *s; for(s=nrlist; s; s=s->next) if(runestrcmp(s->name, name) == 0) return s->fmt; return nil;}voidprintnr(void){ Reg *r; for(r=nrlist; r; r=r->next) fprint(2, "%S %S %d\n", r->name, r->val, r->inc);}/* * Some internal number registers are actually strings, * so provide _ versions to get at them. */void_nr(Rune *name, Rune *val){ dsnr(name, val, &nrlist);}Rune*_getnr(Rune *name){ return getdsnr(name, nrlist);}intgetnr(Rune *name){ Rune *p; p = _getnr(name); if(p == nil) return 0; return eval(p);}/* new register */voidr_nr(int argc, Rune **argv){ Reg *s; if(argc < 2) return; if(argc < 3) nr(argv[1], 0); else{ if(argv[2][0] == '+') nr(argv[1], getnr(argv[1])+eval(argv[2]+1)); else if(argv[2][0] == '-') nr(argv[1], getnr(argv[1])-eval(argv[2]+1)); else nr(argv[1], eval(argv[2])); } if(argc > 3){ for(s=nrlist; s; s=s->next) if(runestrcmp(s->name, argv[1]) == 0) s->inc = eval(argv[3]); }}/* assign format */voidr_af(int argc, Rune **argv){ USED(argc); af(argv[1], argv[2]);}/* remove register */voidr_rr(int argc, Rune **argv){ int i; for(i=1; i<argc; i++) _nr(argv[i], nil);}/* fmt integer in base 26 */voidalpha(Rune *buf, int n, int a){ int i, v; i = 1; for(v=n; v>0; v/=26) i++; if(i == 0) i = 1; buf[i] = 0; while(i > 0){ buf[--i] = a+n%26; n /= 26; }}struct romanv { char *s; int v;} romanv[] ={ "m", 1000, "cm", 900, "d", 500, "cd", 400, "c", 100, "xc", 90, "l", 50, "xl", 40, "x", 10, "ix", 9, "v", 5, "iv", 4, "i", 1};/* fmt integer in roman numerals! */voidroman(Rune *buf, int n, int upper){ Rune *p; char *q; struct romanv *r; if(upper) upper = 'A' - 'a'; if(n >= 5000 || n <= 0){ runestrcpy(buf, L("-")); return; } p = buf; r = romanv; while(n > 0){ while(n >= r->v){ for(q=r->s; *q; q++) *p++ = *q + upper; n -= r->v; } r++; } *p = 0;}Rune*getname(void){ int i, c, cc; static Rune buf[100]; /* XXX add [name] syntax as in groff */ c = getnext(); if(c < 0) return L(""); if(c == '\n'){ warn("newline in name\n"); ungetnext(c); return L(""); } if(c == '['){ for(i=0; i<nelem(buf)-1; i++){ if((c = getrune()) < 0) return L(""); if(c == ']'){ buf[i] = 0; return buf; } buf[i] = c; } return L(""); } if(c != '('){ buf[0] = c; buf[1] = 0; return buf; } c = getnext(); cc = getnext(); if(c < 0 || cc < 0) return L(""); if(c == '\n' | cc == '\n'){ warn("newline in \\n"); ungetnext(cc); if(c == '\n') ungetnext(c); } buf[0] = c; buf[1] = cc; buf[2] = 0; return buf;}/* \n - return number register */inte_n(void){ int inc, v, l; Rune *name, *fmt, buf[100]; Reg *s; inc = getnext(); if(inc < 0) return -1; if(inc != '+' && inc != '-'){ ungetnext(inc); inc = 0; } name = getname(); if(_getnr(name) == nil) _nr(name, L("0")); for(s=nrlist; s; s=s->next){ if(runestrcmp(s->name, name) == 0){ if(s->fmt == nil && !inc && s->val[0]){ /* might be a string! */ pushinputstring(s->val); return 0; } v = eval(s->val); if(inc){ if(inc == '+') v += s->inc; else v -= s->inc; runesnprint(buf, nelem(buf), "%d", v); free(s->val); s->val = erunestrdup(buf); } fmt = s->fmt; if(fmt == nil) fmt = L("1"); switch(fmt[0]){ case 'i': case 'I': roman(buf, v, fmt[0]=='I'); break; case 'a': case 'A': alpha(buf, v, fmt[0]); break; default: l = runestrlen(fmt); if(l == 0) l = 1; runesnprint(buf, sizeof buf, "%0*d", l, v); break; } pushinputstring(buf); return 0; } } pushinputstring(L("")); return 0;}/* \g - number register format */inte_g(void){ Rune *p; p = getaf(getname()); if(p == nil) p = L("1"); pushinputstring(p); return 0;}voidr_pnr(int argc, Rune **argv){ USED(argc); USED(argv); printnr();}voidt8init(void){ addreq(L("nr"), r_nr, -1); addreq(L("af"), r_af, 2); addreq(L("rr"), r_rr, -1); addreq(L("pnr"), r_pnr, 0); addesc('n', e_n, CopyMode|ArgMode|HtmlMode); addesc('g', e_g, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -