URI:
       tt8.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tt8.c (6231B)
       ---
            1 #include "a.h"
            2 /*
            3  * 8. Number Registers
            4  * (Reg register implementation is also here.)
            5  */
            6 
            7 /*
            8  *        \nx                N
            9  *        \n(xx        N
           10  *        \n+x                N+=M
           11  *        \n-x                N-=M
           12  *
           13  *        .nr R ±N M
           14  *        .af R c
           15  *
           16  *        formats
           17  *                1        0, 1, 2, 3, ...
           18  *                001        001, 002, 003, ...
           19  *                i        0, i, ii, iii, iv, v, ...
           20  *                I        0, I, II, III, IV, V, ...
           21  *                a        0, a, b, ..., aa, ab, ..., zz, aaa, ...
           22  *                A        0, A, B, ..., AA, AB, ..., ZZ, AAA, ...
           23  *
           24  *        \gx \g(xx return format of number register
           25  *
           26  *        .rr R
           27  */
           28 
           29 typedef struct Reg Reg;
           30 struct Reg
           31 {
           32         Reg *next;
           33         Rune *name;
           34         Rune *val;
           35         Rune *fmt;
           36         int inc;
           37 };
           38 
           39 Reg *dslist;
           40 Reg *nrlist;
           41 
           42 /*
           43  * Define strings and numbers.
           44  */
           45 void
           46 dsnr(Rune *name, Rune *val, Reg **l)
           47 {
           48         Reg *s;
           49 
           50         for(s = *l; s != nil; s = *l){
           51                 if(runestrcmp(s->name, name) == 0)
           52                         break;
           53                 l = &s->next;
           54         }
           55         if(val == nil){
           56                 if(s){
           57                         *l = s->next;
           58                         free(s->val);
           59                         free(s->fmt);
           60                         free(s);
           61                 }
           62                 return;
           63         }
           64         if(s == nil){
           65                 s = emalloc(sizeof(Reg));
           66                 *l = s;
           67                 s->name = erunestrdup(name);
           68         }else
           69                 free(s->val);
           70         s->val = erunestrdup(val);
           71 }
           72 
           73 Rune*
           74 getdsnr(Rune *name, Reg *list)
           75 {
           76         Reg *s;
           77 
           78         for(s=list; s; s=s->next)
           79                 if(runestrcmp(name, s->name) == 0)
           80                         return s->val;
           81         return nil;
           82 }
           83 
           84 void
           85 ds(Rune *name, Rune *val)
           86 {
           87         dsnr(name, val, &dslist);
           88 }
           89 
           90 void
           91 as(Rune *name, Rune *val)
           92 {
           93         Rune *p, *q;
           94 
           95         p = getds(name);
           96         if(p == nil)
           97                 p = L("");
           98         q = runemalloc(runestrlen(p)+runestrlen(val)+1);
           99         runestrcpy(q, p);
          100         runestrcat(q, val);
          101         ds(name, q);
          102         free(q);
          103 }
          104 
          105 Rune*
          106 getds(Rune *name)
          107 {
          108         return getdsnr(name, dslist);
          109 }
          110 
          111 void
          112 printds(int t)
          113 {
          114         int n, total;
          115         Reg *s;
          116 
          117         total = 0;
          118         for(s=dslist; s; s=s->next){
          119                 if(s->val)
          120                         n = runestrlen(s->val);
          121                 else
          122                         n = 0;
          123                 total += n;
          124                 if(!t)
          125                         fprint(2, "%S\t%d\n", s->name, n);
          126         }
          127         fprint(2, "total\t%d\n", total);
          128 }
          129 
          130 void
          131 nr(Rune *name, int val)
          132 {
          133         Rune buf[20];
          134 
          135         runesnprint(buf, nelem(buf), "%d", val);
          136         _nr(name, buf);
          137 }
          138 
          139 void
          140 af(Rune *name, Rune *fmt)
          141 {
          142         Reg *s;
          143 
          144         if(_getnr(name) == nil)
          145                 _nr(name, L("0"));
          146         for(s=nrlist; s; s=s->next)
          147                 if(runestrcmp(s->name, name) == 0)
          148                         s->fmt = erunestrdup(fmt);
          149 }
          150 
          151 Rune*
          152 getaf(Rune *name)
          153 {
          154         Reg *s;
          155 
          156         for(s=nrlist; s; s=s->next)
          157                 if(runestrcmp(s->name, name) == 0)
          158                         return s->fmt;
          159         return nil;
          160 }
          161 
          162 void
          163 printnr(void)
          164 {
          165         Reg *r;
          166 
          167         for(r=nrlist; r; r=r->next)
          168                 fprint(2, "%S %S %d\n", r->name, r->val, r->inc);
          169 }
          170 
          171 /*
          172  * Some internal number registers are actually strings,
          173  * so provide _ versions to get at them.
          174  */
          175 void
          176 _nr(Rune *name, Rune *val)
          177 {
          178         dsnr(name, val, &nrlist);
          179 }
          180 
          181 Rune*
          182 _getnr(Rune *name)
          183 {
          184         return getdsnr(name, nrlist);
          185 }
          186 
          187 int
          188 getnr(Rune *name)
          189 {
          190         Rune *p;
          191 
          192         p = _getnr(name);
          193         if(p == nil)
          194                 return 0;
          195         return eval(p);
          196 }
          197 
          198 /* new register */
          199 void
          200 r_nr(int argc, Rune **argv)
          201 {
          202         Reg *s;
          203 
          204         if(argc < 2)
          205                 return;
          206         if(argc < 3)
          207                 nr(argv[1], 0);
          208         else{
          209                 if(argv[2][0] == '+')
          210                         nr(argv[1], getnr(argv[1])+eval(argv[2]+1));
          211                 else if(argv[2][0] == '-')
          212                         nr(argv[1], getnr(argv[1])-eval(argv[2]+1));
          213                 else
          214                         nr(argv[1], eval(argv[2]));
          215         }
          216         if(argc > 3){
          217                 for(s=nrlist; s; s=s->next)
          218                         if(runestrcmp(s->name, argv[1]) == 0)
          219                                 s->inc = eval(argv[3]);
          220         }
          221 }
          222 
          223 /* assign format */
          224 void
          225 r_af(int argc, Rune **argv)
          226 {
          227         USED(argc);
          228 
          229         af(argv[1], argv[2]);
          230 }
          231 
          232 /* remove register */
          233 void
          234 r_rr(int argc, Rune **argv)
          235 {
          236         int i;
          237 
          238         for(i=1; i<argc; i++)
          239                 _nr(argv[i], nil);
          240 }
          241 
          242 /* fmt integer in base 26 */
          243 void
          244 alpha(Rune *buf, int n, int a)
          245 {
          246         int i, v;
          247 
          248         i = 1;
          249         for(v=n; v>0; v/=26)
          250                 i++;
          251         if(i == 0)
          252                 i = 1;
          253         buf[i] = 0;
          254         while(i > 0){
          255                 buf[--i] = a+n%26;
          256                 n /= 26;
          257         }
          258 }
          259 
          260 struct romanv {
          261         char *s;
          262         int v;
          263 } romanv[] =
          264 {
          265         "m",        1000,
          266         "cm", 900,
          267         "d", 500,
          268         "cd", 400,
          269         "c", 100,
          270         "xc", 90,
          271         "l", 50,
          272         "xl", 40,
          273         "x", 10,
          274         "ix", 9,
          275         "v", 5,
          276         "iv", 4,
          277         "i", 1
          278 };
          279 
          280 /* fmt integer in roman numerals! */
          281 void
          282 roman(Rune *buf, int n, int upper)
          283 {
          284         Rune *p;
          285         char *q;
          286         struct romanv *r;
          287 
          288         if(upper)
          289                 upper = 'A' - 'a';
          290         if(n >= 5000 || n <= 0){
          291                 runestrcpy(buf, L("-"));
          292                 return;
          293         }
          294         p = buf;
          295         r = romanv;
          296         while(n > 0){
          297                 while(n >= r->v){
          298                         for(q=r->s; *q; q++)
          299                                 *p++ = *q + upper;
          300                         n -= r->v;
          301                 }
          302                 r++;
          303         }
          304         *p = 0;
          305 }
          306 
          307 Rune*
          308 getname(void)
          309 {
          310         int i, c, cc;
          311         static Rune buf[100];
          312 
          313         /* XXX add [name] syntax as in groff */
          314         c = getnext();
          315         if(c < 0)
          316                 return L("");
          317         if(c == '\n'){
          318                 warn("newline in name\n");
          319                 ungetnext(c);
          320                 return L("");
          321         }
          322         if(c == '['){
          323                 for(i=0; i<nelem(buf)-1; i++){
          324                         if((c = getrune()) < 0)
          325                                 return L("");
          326                         if(c == ']'){
          327                                 buf[i] = 0;
          328                                 return buf;
          329                         }
          330                         buf[i] = c;
          331                 }
          332                 return L("");
          333         }
          334         if(c != '('){
          335                 buf[0] = c;
          336                 buf[1] = 0;
          337                 return buf;
          338         }
          339         c = getnext();
          340         cc = getnext();
          341         if(c < 0 || cc < 0)
          342                 return L("");
          343         if(c == '\n' | cc == '\n'){
          344                 warn("newline in \\n");
          345                 ungetnext(cc);
          346                 if(c == '\n')
          347                         ungetnext(c);
          348         }
          349         buf[0] = c;
          350         buf[1] = cc;
          351         buf[2] = 0;
          352         return buf;
          353 }
          354 
          355 /* \n - return number register */
          356 int
          357 e_n(void)
          358 {
          359         int inc, v, l;
          360         Rune *name, *fmt, buf[100];
          361         Reg *s;
          362 
          363         inc = getnext();
          364         if(inc < 0)
          365                 return -1;
          366         if(inc != '+' && inc != '-'){
          367                 ungetnext(inc);
          368                 inc = 0;
          369         }
          370         name = getname();
          371         if(_getnr(name) == nil)
          372                 _nr(name, L("0"));
          373         for(s=nrlist; s; s=s->next){
          374                 if(runestrcmp(s->name, name) == 0){
          375                         if(s->fmt == nil && !inc && s->val[0]){
          376                                 /* might be a string! */
          377                                 pushinputstring(s->val);
          378                                 return 0;
          379                         }
          380                         v = eval(s->val);
          381                         if(inc){
          382                                 if(inc == '+')
          383                                         v += s->inc;
          384                                 else
          385                                         v -= s->inc;
          386                                 runesnprint(buf, nelem(buf), "%d", v);
          387                                 free(s->val);
          388                                 s->val = erunestrdup(buf);
          389                         }
          390                         fmt = s->fmt;
          391                         if(fmt == nil)
          392                                 fmt = L("1");
          393                         switch(fmt[0]){
          394                         case 'i':
          395                         case 'I':
          396                                 roman(buf, v, fmt[0]=='I');
          397                                 break;
          398                         case 'a':
          399                         case 'A':
          400                                 alpha(buf, v, fmt[0]);
          401                                 break;
          402                         default:
          403                                 l = runestrlen(fmt);
          404                                 if(l == 0)
          405                                         l = 1;
          406                                 runesnprint(buf, sizeof buf, "%0*d", l, v);
          407                                 break;
          408                         }
          409                         pushinputstring(buf);
          410                         return 0;
          411                 }
          412         }
          413         pushinputstring(L(""));
          414         return 0;
          415 }
          416 
          417 /* \g - number register format */
          418 int
          419 e_g(void)
          420 {
          421         Rune *p;
          422 
          423         p = getaf(getname());
          424         if(p == nil)
          425                 p = L("1");
          426         pushinputstring(p);
          427         return 0;
          428 }
          429 
          430 void
          431 r_pnr(int argc, Rune **argv)
          432 {
          433         USED(argc);
          434         USED(argv);
          435         printnr();
          436 }
          437 
          438 void
          439 t8init(void)
          440 {
          441         addreq(L("nr"), r_nr, -1);
          442         addreq(L("af"), r_af, 2);
          443         addreq(L("rr"), r_rr, -1);
          444         addreq(L("pnr"), r_pnr, 0);
          445 
          446         addesc('n', e_n, CopyMode|ArgMode|HtmlMode);
          447         addesc('g', e_g, 0);
          448 }