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