t4.c 8.2 KB

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