t4.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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. /* t4.c: read table specification */
  10. # include "t.h"
  11. int oncol;
  12. void
  13. getspec(void)
  14. {
  15. int icol, i;
  16. qcol = findcol() + 1;/* must allow one extra for line at right */
  17. garray(qcol);
  18. sep[-1] = -1;
  19. for (icol = 0; icol < qcol; icol++) {
  20. sep[icol] = -1;
  21. evenup[icol] = 0;
  22. cll[icol][0] = 0;
  23. for (i = 0; i < MAXHEAD; i++) {
  24. csize[icol][i][0] = 0;
  25. vsize[icol][i][0] = 0;
  26. font[icol][i][0] = lefline[icol][i] = 0;
  27. flags[icol][i] = 0;
  28. style[icol][i] = 'l';
  29. }
  30. }
  31. for (i = 0; i < MAXHEAD; i++)
  32. lefline[qcol][i] = 0; /* fixes sample55 looping */
  33. nclin = ncol = 0;
  34. oncol = 0;
  35. left1flg = rightl = 0;
  36. readspec();
  37. Bprint(&tabout, ".rm");
  38. for (i = 0; i < ncol; i++)
  39. Bprint(&tabout, " %2s", reg(i, CRIGHT));
  40. Bprint(&tabout, "\n");
  41. }
  42. void
  43. readspec(void)
  44. {
  45. int icol, c, sawchar, stopc, i;
  46. char sn[10], *snp, *temp;
  47. sawchar = icol = 0;
  48. while (c = get1char()) {
  49. switch (c) {
  50. default:
  51. if (c != tab) {
  52. char buf[64];
  53. sprint(buf, "bad table specification character %c", c);
  54. error(buf);
  55. }
  56. case ' ': /* note this is also case tab */
  57. continue;
  58. case '\n':
  59. if (sawchar == 0)
  60. continue;
  61. case ',':
  62. case '.': /* end of table specification */
  63. ncol = max(ncol, icol);
  64. if (lefline[ncol][nclin] > 0) {
  65. ncol++;
  66. rightl++;
  67. };
  68. if (sawchar)
  69. nclin++;
  70. if (nclin >= MAXHEAD)
  71. error("too many lines in specification");
  72. icol = 0;
  73. if (ncol == 0 || nclin == 0)
  74. error("no specification");
  75. if (c == '.') {
  76. while ((c = get1char()) && c != '\n')
  77. if (c != ' ' && c != '\t')
  78. error("dot not last character on format line");
  79. /* fix up sep - default is 3 except at edge */
  80. for (icol = 0; icol < ncol; icol++)
  81. if (sep[icol] < 0)
  82. sep[icol] = icol + 1 < ncol ? 3 : 2;
  83. if (oncol == 0)
  84. oncol = ncol;
  85. else if (oncol + 2 < ncol)
  86. error("tried to widen table in T&, not allowed");
  87. return;
  88. }
  89. sawchar = 0;
  90. continue;
  91. case 'C':
  92. case 'S':
  93. case 'R':
  94. case 'N':
  95. case 'L':
  96. case 'A':
  97. c += ('a' - 'A');
  98. case '_':
  99. if (c == '_')
  100. c = '-';
  101. case '=':
  102. case '-':
  103. case '^':
  104. case 'c':
  105. case 's':
  106. case 'n':
  107. case 'r':
  108. case 'l':
  109. case 'a':
  110. style[icol][nclin] = c;
  111. if (c == 's' && icol <= 0)
  112. error("first column can not be S-type");
  113. if (c == 's' && style[icol-1][nclin] == 'a') {
  114. Bprint(&tabout, ".tm warning: can't span a-type cols, changed to l\n");
  115. style[icol-1][nclin] = 'l';
  116. }
  117. if (c == 's' && style[icol-1][nclin] == 'n') {
  118. Bprint(&tabout, ".tm warning: can't span n-type cols, changed to c\n");
  119. style[icol-1][nclin] = 'c';
  120. }
  121. icol++;
  122. if (c == '^' && nclin <= 0)
  123. error("first row can not contain vertical span");
  124. if (icol > qcol)
  125. error("too many columns in table");
  126. sawchar = 1;
  127. continue;
  128. case 'b':
  129. case 'i':
  130. c += 'A' - 'a';
  131. case 'B':
  132. case 'I':
  133. if (icol == 0)
  134. continue;
  135. snp = font[icol-1][nclin];
  136. snp[0] = (c == 'I' ? '2' : '3');
  137. snp[1] = 0;
  138. continue;
  139. case 't':
  140. case 'T':
  141. if (icol > 0)
  142. flags[icol-1][nclin] |= CTOP;
  143. continue;
  144. case 'd':
  145. case 'D':
  146. if (icol > 0)
  147. flags[icol-1][nclin] |= CDOWN;
  148. continue;
  149. case 'f':
  150. case 'F':
  151. if (icol == 0)
  152. continue;
  153. snp = font[icol-1][nclin];
  154. snp[0] = snp[1] = stopc = 0;
  155. for (i = 0; i < 2; i++) {
  156. c = get1char();
  157. if (i == 0 && c == '(') {
  158. stopc = ')';
  159. c = get1char();
  160. }
  161. if (c == 0)
  162. break;
  163. if (c == stopc) {
  164. stopc = 0;
  165. break;
  166. }
  167. if (stopc == 0)
  168. if (c == ' ' || c == tab )
  169. break;
  170. if (c == '\n' || c == '|') {
  171. un1getc(c);
  172. break;
  173. }
  174. snp[i] = c;
  175. if (c >= '0' && c <= '9')
  176. break;
  177. }
  178. if (stopc)
  179. if (get1char() != stopc)
  180. error("Nonterminated font name");
  181. continue;
  182. case 'P':
  183. case 'p':
  184. if (icol <= 0)
  185. continue;
  186. temp = snp = csize[icol-1][nclin];
  187. while (c = get1char()) {
  188. if (c == ' ' || c == tab || c == '\n')
  189. break;
  190. if (c == '-' || c == '+')
  191. if (snp > temp)
  192. break;
  193. else
  194. *snp++ = c;
  195. else if (digit(c))
  196. *snp++ = c;
  197. else
  198. break;
  199. if (snp - temp > 4)
  200. error("point size too large");
  201. }
  202. *snp = 0;
  203. if (atoi(temp) > 36)
  204. error("point size unreasonable");
  205. un1getc (c);
  206. continue;
  207. case 'V':
  208. case 'v':
  209. if (icol <= 0)
  210. continue;
  211. temp = snp = vsize[icol-1][nclin];
  212. while (c = get1char()) {
  213. if (c == ' ' || c == tab || c == '\n')
  214. break;
  215. if (c == '-' || c == '+')
  216. if (snp > temp)
  217. break;
  218. else
  219. *snp++ = c;
  220. else if (digit(c))
  221. *snp++ = c;
  222. else
  223. break;
  224. if (snp - temp > 4)
  225. error("vertical spacing value too large");
  226. }
  227. *snp = 0;
  228. un1getc(c);
  229. continue;
  230. case 'w':
  231. case 'W':
  232. snp = cll [icol-1];
  233. /* Dale Smith didn't like this check - possible to have two text blocks
  234. of different widths now ....
  235. if (*snp)
  236. {
  237. Bprint(&tabout, "Ignored second width specification");
  238. continue;
  239. }
  240. /* end commented out code ... */
  241. stopc = 0;
  242. while (c = get1char()) {
  243. if (snp == cll[icol-1] && c == '(') {
  244. stopc = ')';
  245. continue;
  246. }
  247. if ( !stopc && (c > '9' || c < '0'))
  248. break;
  249. if (stopc && c == stopc)
  250. break;
  251. *snp++ = c;
  252. }
  253. *snp = 0;
  254. if (snp - cll[icol-1] > CLLEN)
  255. error ("column width too long");
  256. if (!stopc)
  257. un1getc(c);
  258. continue;
  259. case 'e':
  260. case 'E':
  261. if (icol < 1)
  262. continue;
  263. evenup[icol-1] = 1;
  264. evenflg = 1;
  265. continue;
  266. case 'z':
  267. case 'Z': /* zero width-ignre width this item */
  268. if (icol < 1)
  269. continue;
  270. flags[icol-1][nclin] |= ZEROW;
  271. continue;
  272. case 'u':
  273. case 'U': /* half line up */
  274. if (icol < 1)
  275. continue;
  276. flags[icol-1][nclin] |= HALFUP;
  277. continue;
  278. case '0':
  279. case '1':
  280. case '2':
  281. case '3':
  282. case '4':
  283. case '5':
  284. case '6':
  285. case '7':
  286. case '8':
  287. case '9':
  288. sn[0] = c;
  289. snp = sn + 1;
  290. while (digit(*snp++ = c = get1char()))
  291. ;
  292. un1getc(c);
  293. sep[icol-1] = max(sep[icol-1], numb(sn));
  294. continue;
  295. case '|':
  296. lefline[icol][nclin]++;
  297. if (icol == 0)
  298. left1flg = 1;
  299. continue;
  300. }
  301. }
  302. error("EOF reading table specification");
  303. }
  304. int
  305. findcol(void)
  306. {
  307. # define FLNLIM 200
  308. /* this counts the number of columns and then puts the line back*/
  309. char *s, line[FLNLIM+2], *p;
  310. int c, n = 0, inpar = 0;
  311. while ((c = get1char()) != 0 && c == ' ')
  312. ;
  313. if (c != '\n')
  314. un1getc(c);
  315. for (s = line; *s = c = get1char(); s++) {
  316. if (c == ')')
  317. inpar = 0;
  318. if (inpar)
  319. continue;
  320. if (c == '\n' || c == 0 || c == '.' || c == ',')
  321. break;
  322. else if (c == '(')
  323. inpar = 1;
  324. else if (s >= line + FLNLIM)
  325. error("too long spec line");
  326. }
  327. for (p = line; p < s; p++)
  328. switch (*p) {
  329. case 'l':
  330. case 'r':
  331. case 'c':
  332. case 'n':
  333. case 'a':
  334. case 's':
  335. case 'L':
  336. case 'R':
  337. case 'C':
  338. case 'N':
  339. case 'A':
  340. case 'S':
  341. case '-':
  342. case '=':
  343. case '_':
  344. n++;
  345. }
  346. while (p >= line)
  347. un1getc(*p--);
  348. return(n);
  349. }
  350. void
  351. garray(int qcol)
  352. {
  353. style = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int));
  354. evenup = (int *) getcore(qcol, sizeof(int));
  355. lefline = (int (*)[]) getcore(MAXHEAD * (qcol + 1), sizeof (int)); /*+1 for sample55 loop - others may need it too*/
  356. font = (char (*)[][2]) getcore(MAXHEAD * qcol, 2);
  357. csize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4);
  358. vsize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4);
  359. flags = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int));
  360. cll = (char (*)[])getcore(qcol, CLLEN);
  361. sep = (int *) getcore(qcol + 1, sizeof(int));
  362. sep++; /* sep[-1] must be legal */
  363. used = (int *) getcore(qcol + 1, sizeof(int));
  364. lused = (int *) getcore(qcol + 1, sizeof(int));
  365. rused = (int *) getcore(qcol + 1, sizeof(int));
  366. doubled = (int *) getcore(qcol + 1, sizeof(int));
  367. acase = (int *) getcore(qcol + 1, sizeof(int));
  368. topat = (int *) getcore(qcol + 1, sizeof(int));
  369. }
  370. char *
  371. getcore(int a, int b)
  372. {
  373. char *x;
  374. x = calloc(a, b);
  375. if (x == 0)
  376. error("Couldn't get memory");
  377. return(x);
  378. }
  379. void
  380. freearr(void)
  381. {
  382. free(style);
  383. free(evenup);
  384. free(lefline);
  385. free(flags);
  386. free(font);
  387. free(csize);
  388. free(vsize);
  389. free(cll);
  390. free(--sep); /* netnews says this should be --sep because incremented earlier! */
  391. free(used);
  392. free(lused);
  393. free(rused);
  394. free(doubled);
  395. free(acase);
  396. free(topat);
  397. }