home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Product / Product.zip / sc621_3.zip / src / psc.c < prev    next >
C/C++ Source or Header  |  1993-11-21  |  8KB  |  368 lines

  1. /* Sc parse routine
  2.  *
  3.  * usage psc options
  4.  * options:
  5.  *   -L        Left justify strings.  Default is right justify.
  6.  *   -r        Assemble data into rows first, not columns.
  7.  *   -R    n    Increment by n between rows 
  8.  *   -C n    Increment by n between columns
  9.  *   -n n    Length of the row (column) should be n.
  10.  *   -s v    Top left location in the spreadsheet should be v; eg, k5
  11.  *   -d c       Use c as the delimiter between the fields.
  12.  *   -k         Keep all delimiters - Default is strip multiple delimiters to 1.
  13.  *   -f         suppress 'format' lines in output
  14.  *   -S        Use strings vs numbers for numbers
  15.  *   -P        Use numbers only when there is no [-+eE] (plain numbers only)
  16.  *
  17.  *  Author: Robert Bond
  18.  *  Adjustments: Jeff Buhrt and Eric Putz
  19.  */
  20. char *rev = "$Revision: 6.21 $";
  21.  
  22. #include <ctype.h>
  23. #include <stdio.h>
  24. #include "sc.h"
  25.  
  26. #define END    0
  27. #define NUM    1
  28. #define ALPHA    2
  29. #define SPACE    3
  30. #define EOL    4
  31.  
  32. extern char *optarg;
  33. extern int   optind, getopt(), atoi();
  34. char    *coltoa();
  35. char    *progname;
  36. int    getrow(), getcol(), scan();
  37.  
  38. int *fwidth;
  39. int *precision;
  40. int maxcols;
  41. int *realfmt;
  42.  
  43. /* option flags reset */
  44. int colfirst = FALSE;
  45. int leftadj = FALSE;
  46. int r0 = 0;
  47. int c0 = 0;
  48. int rinc = 1;
  49. int cinc = 1;
  50. int len = 20000;
  51. char delim1 = ' ';
  52. char delim2 = '\t';
  53. int strip_delim = TRUE;
  54. int drop_format = FALSE;
  55. int strnums    = FALSE;
  56. int plainnums    = FALSE;
  57.  
  58. char token[1000];
  59.  
  60. main(argc, argv)
  61. int argc;
  62. char **argv;
  63. {
  64.     int curlen;
  65.     int curcol, coff;
  66.     int currow, roff;
  67.     int first;
  68.     int c;
  69.     register effr, effc;
  70.     int i,j;
  71.     register char *p;
  72.  
  73.     progname = argv[0];
  74.     while ((c = getopt(argc, argv, "rfLks:R:C:n:d:SPv")) != EOF) {
  75.     switch(c) {
  76.     case 'r':
  77.         colfirst = TRUE;
  78.         break;
  79.     case 'L':
  80.         leftadj = TRUE;
  81.         break;
  82.     case 's':
  83.         c0 = getcol(optarg);
  84.         r0 = getrow(optarg);
  85.         break;
  86.     case 'R':
  87.         rinc = atoi(optarg);
  88.         break;
  89.     case 'C':
  90.         cinc = atoi(optarg);
  91.         break;
  92.     case 'n':
  93.         len = atoi(optarg);
  94.         break;
  95.     case 'd':
  96.         delim1 = optarg[0];
  97.         delim2 = '\0';
  98.         break;
  99.     case 'k':
  100.         strip_delim = FALSE;
  101.         break;
  102.     case 'f':
  103.         drop_format = TRUE;
  104.         break;
  105.     case 'S':
  106.         strnums = TRUE;
  107.         break;
  108.     case 'P':
  109.         plainnums = TRUE;
  110.         break;
  111.     case 'v':
  112.         (void) fprintf(stderr,"%s: %s\n", progname, rev);
  113.     default:
  114.         (void) fprintf(stderr,"Usage: %s [-rkfLSPv] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  115.         exit(1);
  116.         }
  117.     }
  118.  
  119.     if (optind < argc) {
  120.         (void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  121.         exit(1);
  122.     }
  123.  
  124.     /* setup the spreadsheet arrays */
  125.     if (!growtbl(GROWNEW, 0, 0))
  126.     exit(1);
  127.  
  128.     curlen = 0;
  129.     curcol = c0; coff = 0;
  130.     currow = r0; roff = 0;
  131.     first = TRUE;
  132.  
  133.     while(1) {
  134.  
  135.     effr = currow+roff;
  136.     effc = curcol+coff;
  137.  
  138.     switch(scan()) {
  139.     case END:
  140.         if(drop_format) exit(0);
  141.         for (i = 0; i<maxcols; i++) {
  142.         if (fwidth[i])
  143.             (void) printf("format %s %d %d\n", coltoa(i), 
  144.             fwidth[i]+1, precision[i]);
  145.         }
  146.         exit(0);
  147.     case NUM:
  148.         first = FALSE;
  149.         (void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
  150.         if (effc >= maxcols - 1)
  151.         {    if (!growtbl(GROWCOL, 0, effc))
  152.         {    (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  153.             continue;
  154.         }
  155.         }
  156.         i = 0;
  157.         j = 0;
  158.         p = token;
  159.         while (*p && *p != '.') {
  160.         p++; i++;
  161.         }
  162.         if (*p) {
  163.         p++; i++;
  164.         }
  165.         while (*p) {
  166.         p++; i++; j++;
  167.         }
  168.         {   int    ow, nw;
  169.  
  170.         ow = fwidth[effc] - precision[effc];
  171.         if (precision[effc] < j)
  172.             precision[effc] = j;
  173.     
  174.         if (fwidth[effc] < i)
  175.             fwidth[effc] = i;
  176.  
  177.         /* now make sure:
  178.          *    1234.567890 (format 11 6)
  179.          *    1234567.890 (format 11 3)
  180.          *    both show (format 14 6)
  181.          *        (really it uses 15 6 to separate columns)
  182.          */
  183.         if ((nw = i - j) > ow)
  184.             fwidth[effc] += nw - (fwidth[effc] - precision[effc]);
  185.         }
  186.         break;
  187.     case ALPHA:
  188.         first = FALSE;
  189.         if (leftadj)
  190.         (void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token); 
  191.         else
  192.         (void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token); 
  193.         if (effc >= maxcols - 1)
  194.         {    if (!growtbl(GROWCOL, 0, effc))
  195.         {    (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  196.             continue;
  197.         }
  198.         }
  199.         i = strlen(token);
  200.         if (i > fwidth[effc])
  201.         fwidth[effc] = i;
  202.         break;
  203.     case SPACE:
  204.         if (first && strip_delim)
  205.         break;
  206.         if (colfirst)
  207.         roff++;
  208.         else
  209.         coff++;
  210.         break;
  211.     case EOL:
  212.         curlen++;
  213.         roff = 0;
  214.         coff = 0;
  215.         first = TRUE;
  216.         if (colfirst) {
  217.         if (curlen >= len) {
  218.             curcol = c0;
  219.             currow += rinc;
  220.             curlen = 0;
  221.         } else {
  222.             curcol += cinc;
  223.         }
  224.         } else {
  225.         if (curlen >= len) {
  226.             currow = r0;
  227.             curcol += cinc;
  228.             curlen = 0;
  229.         } else {
  230.             currow += rinc;
  231.         }
  232.         }
  233.         break;
  234.     }
  235.     }
  236. }
  237.  
  238. int
  239. scan()
  240. {
  241.     register int c;
  242.     register char *p;
  243.     register int founddigit;
  244.  
  245.     p = token;
  246.     c = getchar();
  247.  
  248.     if (c == EOF)
  249.     return(END);
  250.  
  251.     if (c == '\n')
  252.     return(EOL);
  253.  
  254.     if (c == delim1 || c == delim2) {
  255.         if (strip_delim) {
  256.         while ((c = getchar()) && (c == delim1 || c == delim2))
  257.             ;
  258.         (void)ungetc(c, stdin);
  259.     } 
  260.     return(SPACE);
  261.     }
  262.  
  263.     if (c == '\"') {
  264.     while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
  265.         *p++ = c;
  266.     if (c != '\"')
  267.         (void)ungetc(c, stdin);
  268.     *p = '\0';
  269.     return(ALPHA);
  270.     }
  271.  
  272.     while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
  273.     *p++ = c;
  274.     c = getchar();
  275.     }
  276.     *p = '\0';
  277.     (void)ungetc(c, stdin);
  278.  
  279.     p = token;
  280.     c = *p;
  281.     founddigit = FALSE;
  282.     /*
  283.      * str_nums always returns numbers as strings
  284.      * plainnums returns 'numbers' with [-+eE] in them as strings
  285.      * lastprtnum makes sure a number ends in one of [0-9eE.]
  286.      */
  287.     if (!strnums && (isdigit(c) || c == '.' || c == '-' || c == '+')) {
  288.     int    lastprtnum = FALSE;
  289.  
  290.     while(isdigit(c) || c == '.' || (!plainnums && (c == '-' ||
  291.                     c == '+' || c == 'e' || c == 'E'))) {
  292.         if (isdigit(c)) 
  293.             lastprtnum = founddigit = TRUE;
  294.         else
  295.         if (!(c == '.' || c == 'e' || c == 'E'))
  296.             lastprtnum = FALSE;
  297.         c = *p++;
  298.     }
  299.     if (c == '\0' && founddigit && lastprtnum)
  300.         return(NUM);
  301.     else
  302.         return(ALPHA);
  303.     }
  304.  
  305.     return(ALPHA);
  306. }
  307.     
  308. /* turns [A-Z][A-Z] into a number */
  309. int
  310. getcol(p)
  311. char *p;
  312. {
  313.     register  col;
  314.  
  315.     col = 0;
  316.     if (!p)
  317.     return(0);
  318.     while(*p && !isalpha(*p)) 
  319.     p++; 
  320.     if (!*p)
  321.     return(0);
  322.     col = ((*p & 0137) - 'A');
  323.     if (isalpha(*++p)) 
  324.     col = (col + 1)*26 + ((*p & 0137) - 'A');
  325.     return(col);
  326. }
  327.  
  328. /* given a string turn it into a row number */
  329. int
  330. getrow(p)
  331. char *p;
  332. {
  333.     int row;
  334.  
  335.     row = 0;
  336.     if (!p)
  337.     return(0);
  338.     while(*p && !isdigit(*p))
  339.     p++; 
  340.     if (!*p)
  341.     return(0);
  342.     while(*p && isdigit(*p))
  343.     {    row = row * 10 + *p - '0';
  344.     p++;
  345.     }
  346.     return(row);
  347. }
  348.  
  349. /* turns a column number into [A-Z][A-Z] */
  350. char *
  351. coltoa(col)
  352. int col;
  353. {
  354.     static char rname[3];
  355.     register char *p = rname;
  356.  
  357.     if (col < 0 || col > 27*26)    /* A-Z, AA-ZZ */
  358.     (void) fprintf(stderr,"coltoa: invalid col: %d", col);
  359.  
  360.     if (col > 25) {
  361.     *p++ = col/26 + 'A' - 1;
  362.     col %= 26;
  363.     }
  364.     *p++ = col+'A';
  365.     *p = '\0';
  366.     return(rname);
  367. }
  368.