t8.c 6.5 KB

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