home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / MBASE / MBASE50.TAR / mbase / src / report.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-14  |  20.3 KB  |  726 lines

  1. /*
  2.  * METALBASE 5.0
  3.  *
  4.  * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  5.  *                                       [ t-richj@microsoft.com ]
  6.  *
  7.  * Special thanks go to Bruce Momjian (root@candle.uucp@ls.com) for his
  8.  * suggestions and code.
  9.  *
  10.  */
  11.  
  12. #include "mbase.h"
  13.  
  14. /*
  15.  * Definitions
  16.  *
  17.  */
  18.  
  19. #define usage() fprintf(stderr,"format: report [-k encryption_key] [templatename]%s", SNGCR)
  20. #define syntax(x) { fprintf(stderr,"syntax error in template: expected keyword '%s'%s", x, SNGCR);  mb_exit(3); }
  21.  
  22. #define comment() skip(templ,";"); while(skip(templ,"#")) goeol(templ,NULL);
  23. #define skipl(x) for (I=0; I<x; I++)  printf(SNGCR);
  24.  
  25. #define MAX_WIDTH  80
  26. #define FULL_WIDTH "%-79.79s"
  27.  
  28. #define NONE   0
  29. #define BEFORE 1
  30. #define DURING 2
  31. #define AFTER  4
  32.  
  33.  /* CREDIT is displayed as the variable system without "!date" or anything */
  34.  
  35. #define CREDIT "MetalBase 5.0 Report Writer"
  36.  
  37. /*
  38.  * Prototypes
  39.  *
  40.  */
  41.  
  42. #ifdef LONGARGS
  43.    void  parse_args (int, char **);
  44.    int   get_size   (long);
  45.    void  do_prints  (long, int);
  46.    int   fill_data  (dataptr, int, char *);
  47. #else
  48.    void  parse_args();
  49.    int   get_size();
  50.    void  do_prints();
  51.    int   fill_data();
  52. #endif
  53.  
  54. /*
  55.  * Variables
  56.  *
  57.  */
  58.  
  59. extern    long   _lpos;  /* These are from parse.c */
  60. extern    int    quoted; /* Referenced in libmb.a  */
  61.  
  62. int       templ, I;
  63. long      lpos = 0L;
  64. char      key[MAX_WIDTH] = "";
  65. relation *rel;
  66. long      l_pos = 0L;
  67. long      h_pos = 0L;
  68. long      f_pos = 0L;
  69. long      o_pos = 0L;
  70. int       keep_l = 0, keep_h = 0, keep_f = 0;
  71. dataptr   rec, buf;
  72.  
  73. int       num_col = 80;   /* 80-column (std pagesize) paper */
  74. int       num_row = 66;   /* 66-line (std pagesize) paper   */
  75. int       top_mar =  4;   /* 2/3" top margin by default     */
  76. int       bot_mar =  6;   /* 1" bottom margin by default    */
  77. int       lef_mar = 10;   /* 1" left margin by default      */
  78. int       rig_mar = 10;   /* 1" right margin by default     */
  79. int       wid;
  80. int       hgt;
  81. int       pageno  =  1;   /* Start with page 1, obviously   */
  82.  
  83. /*
  84.  * Main code
  85.  *
  86.  */
  87.  
  88. void
  89. main  (argc, argv)
  90. int    argc;
  91. char **argv;
  92. {
  93.    int    act, idx, numlines, lines, stop, dir, i, on_siz;
  94.    int    didother, doneone,  badrec;
  95.    char   temp[128];
  96.  
  97.    parse_args (argc, argv);
  98.  
  99.    comment();
  100.    if (! skip (templ, "data"))  syntax ("data");
  101.    strcpy (temp, getword(templ));
  102.    comment();
  103.  
  104.    if (! strcmp (&temp[strlen(temp)-4], ".rel"))
  105.       temp[strlen(temp)-4] = 0;
  106.    if ((rel = mb_inc (temp, strtokey (key))) == RNULL)
  107.     { fprintf (stderr, "Cannot open relation '%s' : %s\n", temp, mb_error);
  108.       close   (templ);
  109.       exit    (4);
  110.     }
  111.    if ((rec = (dataptr)malloc (2+rel->rec_len)) == NULL)
  112.     { fprintf (stderr, "Out of memory\n");
  113.       close   (templ);
  114.       mb_exit (4);
  115.     }
  116.    if ((buf = (dataptr)malloc (2+rel->rec_len)) == NULL)
  117.     { fprintf (stderr, "Out of memory\n");
  118.       free    (rec);
  119.       close   (templ);
  120.       mb_exit (4);
  121.     }
  122.  
  123.    for (didother = 0; ; )
  124.     {
  125.       if (skip (templ, ";") == -1)  break;
  126.       for (;;)
  127.        {
  128.          if (skip (templ, ";") == -1)  break;
  129.          comment();
  130.          if (skip (templ, "size"))
  131.           {
  132.             for (didother = 1; ; )
  133.              {
  134.                if (skip (templ, ";") == -1)  break;
  135.                comment();
  136.  
  137.                strcpy (temp, getword (templ));
  138.                if (! strcmp (temp, "columns"))  num_col = atoi(getword(templ));
  139.                else
  140.                if (! strcmp (temp, "rows"))     num_row = atoi(getword(templ));
  141.                else
  142.                if (! strcmp (temp, "top"))
  143.                 { skip (templ, "margin");  top_mar = atoi (getword (templ)); }
  144.                else
  145.                if (! strcmp (temp, "bottom"))
  146.                 { skip (templ, "margin");  bot_mar = atoi (getword (templ)); }
  147.                else
  148.                if (! strcmp (temp, "left"))
  149.                 { skip (templ, "margin");  lef_mar = atoi (getword (templ)); }
  150.                else
  151.                if (! strcmp (temp, "right"))
  152.                 { skip (templ, "margin");  rig_mar = atoi (getword (templ)); }
  153.                else
  154.                if (!strcmp (temp, "page")   || !strcmp (temp, "newpage") ||
  155.                    !strcmp (temp, "header") || !strcmp (temp, "last")    ||
  156.                    !strcmp (temp, "on")     || !strcmp (temp, "footer"))
  157.                 {
  158.                   putback(templ);  /* Go back before this word */
  159.                   break;
  160.                 }
  161.                else
  162.                 { fprintf (stderr, "token '%s' unrecognized in Size\n", temp);
  163.                   free    (rec);
  164.                   free    (buf);
  165.                   close   (templ);
  166.                   mb_exit (3);
  167.                 }
  168.                continue;
  169.              }
  170.           }
  171.          if (skip (templ, "newpage"))
  172.           {
  173.             didother = 1;
  174.             printf ("\f");
  175.             comment();
  176.             continue;
  177.           }
  178.          if (skip (templ, "page"))
  179.           {
  180.             didother = 1;
  181.             pageno = atoi (getword (templ));
  182.             comment();
  183.             continue;
  184.           }
  185.          if (skip (templ, "header"))
  186.           {
  187.             keep_h = skip (templ, "keep");
  188.             didother = 2;  /* Ignore errors until next keyword */
  189.             comment();
  190.             h_pos = lseek (templ, 0L, 1);  (void)getword(templ);
  191.             continue;
  192.           }
  193.          if (skip (templ, "last"))
  194.           {
  195.             keep_l = skip (templ, "keep");
  196.             didother = 2;  /* Ignore errors until next keyword */
  197.             comment();
  198.             l_pos = lseek (templ, 0L, 1);  (void)getword(templ);
  199.             continue;
  200.           }
  201.          if (skip (templ, "footer"))
  202.           {
  203.             keep_f = skip (templ, "keep");
  204.             didother = 2;  /* Ignore errors until next keyword */
  205.             comment();
  206.             f_pos = lseek (templ, 0L, 1);  (void)getword(templ);
  207.             continue;
  208.           }
  209.  
  210.          if (skip (templ, "on"))
  211.             break;
  212.  
  213.          if (! didother)
  214.           { fprintf (stderr,
  215.                "release 5.0 cannot use more than one relation%s", SNGCR);
  216.             close (templ);
  217.             syntax ("size");
  218.           }
  219.  
  220.          if (didother != 2)
  221.           { fprintf (stderr, "unexpected keyword '%s'%s",getword(templ),SNGCR);
  222.             close   (templ);
  223.             free    (rec);
  224.             free    (buf);
  225.             mb_exit (3);
  226.           }
  227.          (void)getword(templ);  /* Skip this one--it's in a header or etc */
  228.        }
  229.  
  230.       if (skip (templ, ";") == -1)  break;
  231.       didother = 1;
  232.       wid = num_col - rig_mar - lef_mar;
  233.       hgt = num_row - top_mar - bot_mar;
  234.  
  235. /*
  236.  * Perform ON clause.  We are currently sitting right after the keyword On,
  237.  * and the following are conditionals on the operation of this clause:
  238.  *   h_pos:  0L==no header - else, location of first print/skip command
  239.  *   l_pos:  0L==no last   - else, location of first print/skip command
  240.  *   f_pos:  0L==no footer - else, location of first print/skip command
  241.  *
  242.  */
  243.  
  244.       strcpy (temp, getword (templ));
  245.       if ((idx = idxnum (rel, temp)) < 0)
  246.        { fprintf (stderr, "invalid index '%s' referenced%s", temp, SNGCR);
  247.          free    (rec);
  248.          free    (buf);
  249.          close   (templ);
  250.          mb_exit (5);
  251.        }
  252.  
  253.       act = FIRST, stop = NONE;
  254.       dir = 0;
  255.       if (skip (templ, "<="))  act = FIRST, stop=AFTER;
  256.       if (skip (templ, "=<"))  act = FIRST, stop=AFTER;
  257.       if (skip (templ, "<"))   act = FIRST, stop=DURING|AFTER;
  258.       if (skip (templ, ">="))  act = GTEQ,  stop=NONE;
  259.       if (skip (templ, "=>"))  act = GTEQ,  stop=NONE;
  260.       if (skip (templ, ">"))   act = GTHAN, stop=NONE;
  261.       if (skip (templ, "=="))  act = EQUAL, stop=AFTER;
  262.       if (skip (templ, "="))   act = EQUAL, stop=AFTER;
  263.  
  264.       if (act != FIRST || stop != NONE)
  265.        { strcpy (temp, getword(templ));
  266.          if (!strcmp (temp, "print") || !strcmp (temp, "skip"))
  267.           { fprintf (stderr, "query requires comparison value%s", SNGCR);
  268.             free    (rec);
  269.             free    (buf);
  270.             close   (templ);
  271.             mb_exit (5);
  272.           }
  273.  
  274.          if (fill_data (rec, idx, temp))
  275.             fill_data (buf, idx, temp);
  276.          else
  277.           { act = FIRST;
  278.             stop = NONE;
  279.           }
  280.        }
  281.  
  282.       dir = NEXT;
  283.       if (skip (templ, "reverse"))
  284.        { dir = PREV;
  285.          switch (act)
  286.           { case FIRST:  if (stop == NONE)    act = LAST;
  287.                          if (stop == AFTER)   act = LTEQ,  stop = NONE;
  288.                          if (stop &  DURING)  act = LTHAN, stop = NONE;
  289.                         break;
  290.             case  GTEQ:  if (stop == NONE)    act = LAST,  stop = BEFORE;
  291.             case GTHAN:  if (stop == NONE)    act = LAST,  stop = DURING|BEFORE;
  292.           }
  293.        }
  294.  
  295.       o_pos    = lseek(templ,0L,1);
  296.       on_siz   = get_size(o_pos);
  297.       numlines = hgt - get_size(h_pos) - get_size(f_pos);
  298.  
  299.       doneone = 0;
  300.       for (lines = 0; ; )
  301.        { badrec = 0;
  302.          if (mb_sel (rel, idx, rec, act, buf) != MB_OKAY)
  303.             if (doneone || mb_errno != MB_NO_SUCH)  break;
  304.             else
  305.                badrec = 1;
  306.          doneone = 1;
  307.          if (badrec == 0 && stop != NONE)
  308.             if (((i = compare (rel, rec, buf, idx)) < 0 && stop&BEFORE) ||
  309.                  (i == 0 && stop&DURING) || (i >  0 && stop&AFTER))
  310.                break;
  311.          lseek (templ, o_pos, 0);
  312.  
  313.          if (lines+on_siz > numlines-1)
  314.            { skipl(numlines-lines);
  315.              do_prints(f_pos, 1);
  316.              lines=0; skipl(bot_mar); pageno++;
  317.            }
  318.          if (lines == 0) { skipl(top_mar); do_prints (h_pos, 1); }
  319.  
  320.          do_prints (o_pos, !badrec);
  321.          if (badrec)  break;
  322.          lines += on_siz;
  323.          act = dir;
  324.        }
  325.  
  326.       if (mb_errno != MB_NO_SUCH && mb_errno != MB_OKAY)
  327.        { fprintf (stderr, "aborted -- %s%s", mb_error, SNGCR);
  328.          free    (rec);
  329.          free    (buf);
  330.          close   (templ);
  331.          mb_exit (6);
  332.        }
  333.  
  334.       o_pos = lseek (templ, 0L, 1);
  335.       skipl (numlines-lines);
  336.       do_prints (l_pos ? l_pos : f_pos, 1);
  337.       lseek (templ, o_pos, 0);
  338.       skipl (bot_mar);  pageno++;
  339.  
  340.    didother = 2;  /* Skip stuff until valid keyword */
  341.  
  342. /*
  343.  * Done with this clause.  Erase current header/footer/last positions--they
  344.  * don't carry from one clause to another.  That is, unless they had 'keep'
  345.  * keywords...
  346.  *
  347.  */
  348.  
  349.       if (! keep_l)  l_pos = 0L;
  350.       if (! keep_f)  f_pos = 0L;
  351.       if (! keep_h)  h_pos = 0L;
  352.     }
  353.  
  354.    close   (templ);
  355.    free    (rec);
  356.    free    (buf);
  357.    mb_exit (0);
  358. }
  359.  
  360. /*
  361.  * Utilities
  362.  *
  363.  */
  364.  
  365. void
  366. parse_args (agc, agv)
  367. int         agc;
  368. char           **agv;
  369. {
  370.    char name[256];
  371.  
  372.    while (agc > 1 && agv[1][0] == '-')
  373.       {
  374.       switch (agv[1][1])
  375.          {
  376.          case 'k':  if (agv[1][2])
  377.                        strcpy (key, &agv[1][2]);
  378.                     else
  379.                      { agc--;  agv++;
  380.                        strcpy (key, agv[1]);
  381.                      }
  382.                    break;
  383.          default:   fprintf (stderr, "unrecognized option '%s'\n", agv[1]);
  384.                     usage   ();
  385.                     exit    (1);
  386.                    break;
  387.          }
  388.  
  389.       agc--;  agv++;
  390.       }
  391.  
  392.    if (agc != 2)
  393.     { usage ();
  394.       exit  (1);
  395.     }
  396.  
  397.    strcpy (name, agv[1]);
  398.    if (strcmp (&name[strlen(name)-4], ".rpt"))  strcat (name, ".rpt");
  399.    if ((templ = openx (name, O_RDONLY)) < 0)
  400.     { fprintf (stderr, "cannot open template '%s'\n", name);
  401.       exit    (2);
  402.     }
  403. }
  404.  
  405. /*
  406.  * get_size() reads from position 'pos' until it doesn't see a print or
  407.  * skip command--it keeps track of the number of lines used in the section,
  408.  * and returns it.  It's used to make headers and footers work well with
  409.  * top and bottom margins.
  410.  *
  411.  */
  412.  
  413. int
  414. get_size (pos)
  415. long      pos;
  416. {
  417.    int  num = 0;
  418.  
  419.    for (lseek (templ, pos, 0); ; )
  420.     {
  421.       if (skip (templ, ";") == -1)  break;
  422.       comment();
  423.       if (skip (templ, "print"))
  424.        {
  425.          if (! skip (templ, "continued"))
  426.           { if (! strcmp (":", getword(templ)))  num++;
  427.             else
  428.                if (! skip (templ, "continued"))  num++;
  429.           }
  430.  
  431.          for (;;)
  432.             if (skip (templ, ";"))  break;
  433.             else
  434.                (void)getword(templ);
  435.        }
  436.       else
  437.          if (skip (templ, "skip"))
  438.           {
  439.             num += atoi (getword (templ));
  440.             skip (templ, "lines");  skip (templ, "line");
  441.           }
  442.          else
  443.             break;
  444.     }
  445.  
  446.    return num;
  447. }
  448.  
  449. /*
  450.  * do_prints() actually performs the printings.  :)
  451.  *
  452.  */
  453.  
  454. void
  455. do_prints (pos, really)
  456. long       pos;
  457. int             really;
  458. {
  459.    long    lx;  /* typ == 1 */
  460.    double  fx;  /* typ == 2 */
  461.    mb_time tx;  /* typ == 3 */
  462.    mb_date dx;  /* typ == 4 */
  463.    int     cnt, jst, x, w, l, typ, fmt;
  464.    char    spc[128], temp[256], t2[128], t3[128], *p;
  465.  
  466.    if (! pos)  return;
  467.  
  468.    sprintf (spc, FULL_WIDTH, "");  spc[lef_mar] = 0;
  469.  
  470.    w = wid;  l = lef_mar;
  471.    for (lseek (templ, pos, 0); ; )
  472.       {
  473.       if (skip (templ, ";") == -1)  break;
  474.       comment();
  475.  
  476.       if (skip (templ, "skip"))
  477.          {
  478.          x = atoi (getword (templ));
  479.          skip (templ, "lines");  skip (templ, "line");
  480.          skip (templ, ";");
  481.          if (really)
  482.             for ( ; x > 0; x--)  printf (SNGCR);
  483.          continue;
  484.          }
  485.  
  486.       if (! skip (templ, "print"))
  487.          {
  488.          break;
  489.          }
  490.  
  491.       cnt = jst = 0;
  492.       if (skip (templ, "continued"))  cnt = 1;
  493.       if (skip (templ, "centered"))   jst = 1;
  494.       if (skip (templ, "continued"))  cnt = 1;
  495.       if (skip (templ, "right"))      jst = 2;
  496.       if (skip (templ, "continued"))  cnt = 1;
  497.  
  498.       skip (templ, ":");
  499.  
  500. /*
  501.  * process the print command
  502.  *
  503.  */
  504.  
  505.       for (temp[0] = 0; ; )
  506.          {
  507.          strcpy (t2, getword(templ));
  508.          if (! quoted && ! strcmp (t2, ";"))  break;
  509.  
  510.          if (quoted)
  511.             {
  512.             typ=0;
  513.             }
  514.          else
  515.             {
  516.             if (isdigit(t2[0]) || t2[0] == '.')
  517.                {
  518.                if (strchr (t2, '.'))  typ=2, fx=(double)atof(t2);
  519.                else                   typ=1, lx=(long)atol(t2);
  520.                }
  521.             else
  522.                {
  523.                if (!strcmp (t2, "column"))
  524.                 { sprintf (t2, FULL_WIDTH, "");
  525.                   x = atoi(getword(templ))-l-strlen(temp);
  526.                   if (x < 0)  x = 0;
  527.                   t2[x] = 0;  typ = 0;
  528.                 }
  529.                else
  530.                   {
  531.                   if (!strcmp (t2, ","))
  532.                      t2[0] = ' ', typ = 0;
  533.                   else
  534.                      {
  535.  
  536. /*
  537.  * It's a variable of some sort; make t2 the name and t3 any modifer.
  538.  *
  539.  */
  540.  
  541.                      fmt = 0;
  542.                      t3[0] = 0;
  543.                      if (p = strchr (t2, '!'))
  544.                         {
  545.                         strcpy (t3, p+1);
  546.                         *p = 0;
  547.                         }
  548.  
  549. /*
  550.  * That done, figure out what type it should be and assign it.
  551.  *
  552.  */
  553.                      typ = -1;
  554.  
  555.                      if (!strcmp (t2, "system"))
  556.                         {
  557.                         if (! strcmp (t3, "time"))
  558.                          { tx = curtime();  typ = 3; }
  559.                         else if (! strcmp (t3, "date"))
  560.                          { dx = curdate();  typ = 4; }
  561.                         else if (! strcmp (t3, "page"))
  562.                          { lx = pageno;     typ = 1; }
  563.                         else 
  564.                          { strcpy (t2, CREDIT);  typ = 0; }
  565.                         }
  566.  
  567. /*
  568. * If they use the relation name, trash it...
  569. *
  570. */
  571.  
  572.                      if (typ == -1 && (p = strchr (t2, '.')))
  573.                         {
  574.                         strcpy (spc, 1+p);
  575.                         strcpy (t2, spc);
  576.                         sprintf (spc, FULL_WIDTH, "");  spc[lef_mar] = 0;
  577.                         }
  578.  
  579.                      if (typ == -1)
  580.                         {
  581.                         for (x=0; x < rel->num_f; x++)
  582.                            if (! strcmp (rel->name[x], t2))  break;
  583.                         typ = 0;
  584.                         if (x != rel->num_f)
  585.                            {
  586.  
  587. /*
  588.  * It's a valid name, so use its data (field # is in x)
  589.  *
  590.  */
  591.  
  592.                            if (! t3[0])
  593.                               {
  594.                               p = (char *)rec + rel->start[x];
  595.  
  596.             switch (rel->type[x])
  597.                {
  598.                case T_SHORT:   lx = (long) *(short  *)p;  typ = 1;  break;
  599.                case T_USHORT:  lx = (long) *(ushort *)p;  typ = 1;  break;
  600.                case T_LONG:
  601.                case T_SERIAL:  lx = (long) *(long   *)p;  typ = 1;  break;
  602.                case T_ULONG:   lx = (long) *(ulong  *)p;  typ = 1;  break;
  603.                case T_FLOAT:   fx = (float)*(float  *)p;  typ = 2;  break;
  604.                case T_DOUBLE:
  605.                case T_MONEY:   fx = (float)*(double *)p;  typ = 2;  break;
  606.                case T_TIME:    tx =       *(mb_time *)p;  typ = 3;  break;
  607.                case T_DATE:    dx =       *(mb_date *)p;  typ = 4;  break;
  608.                default:        strcpy (t2, p);            typ = 0;  break;
  609.                }
  610.  
  611.                               }
  612.                            }
  613.                         }
  614.                      }
  615.                   }
  616.                }
  617.             }
  618.  
  619.          if (skip (templ, "using") || skip (templ, "format"))
  620.           { if (typ == 3 || typ == 4)
  621.                fmt = atoi (getword (templ));
  622.             else
  623.              { strcpy (t3, getword(templ));
  624.                switch (typ)
  625.                 { case 0:  strcpy  (spc, t2);
  626.                            sprintf (t2, t3, spc);  typ = 0;
  627.                            sprintf (spc,FULL_WIDTH,"");  spc[lef_mar]=0;
  628.                           break;
  629.                   case 1:  sprintf (t2, t3, lx);  typ = 0;  break;
  630.                   case 2:  sprintf (t2, t3, fx);  typ = 0;  break;
  631.                 }
  632.              }
  633.           }
  634.  
  635.          if (typ == 1)  sprintf (t2, "%ld", lx);
  636.          if (typ == 2)  sprintf (t2, "%lg", fx);
  637.          if (typ == 3)  strcpy  (t2, fmt_time (tx, fmt));
  638.          if (typ == 4)  strcpy  (t2, fmt_date (dx, fmt));
  639.  
  640.          if (skip (templ, "to"))
  641.           { sprintf (t3, FULL_WIDTH, "");
  642.             x = atoi (getword(templ)) - l - strlen (t2) - strlen (temp);
  643.             if (x < 0)  x = 0;
  644.             t3[x] = 0;
  645.             strcat (t2, t3);
  646.           }
  647.  
  648.          strcat (temp, t2);
  649.          }
  650.  
  651. /*
  652.  * and actually print it.
  653.  *
  654.  */
  655.  
  656.       if (really)
  657.          {
  658.          switch (jst)
  659.             {
  660.             case  0:  printf ("%s%s", spc, temp);  break;
  661.             case  1:  x = ((w - strlen (temp)) / 2);  x = max (x, 0);
  662.                       if (w == wid)  x += l;
  663.                       sprintf (t2, FULL_WIDTH, "");  t2[x] = 0;
  664.                       printf ("%s%s", t2, temp);   break;
  665.             case  2:  x = (w - strlen (temp)); x = max (x, 0);
  666.                       if (w == wid)  x += l;
  667.                       sprintf (t2, FULL_WIDTH, "");  t2[x] = 0;
  668.                       printf ("%s%s", t2, temp);   break;
  669.             }
  670.          if (! cnt)  w  = wid,           l  = lef_mar;
  671.          else        w -= strlen (temp), l += strlen (temp);
  672.          if (! cnt)  printf (SNGCR);
  673.          }
  674.       }
  675. }
  676.  
  677. int
  678. fill_data (ptr, idx, str)
  679. dataptr    ptr;
  680. int             idx;
  681. char                *str;
  682. {
  683.    char    temp[128], t2[5];
  684.    dataptr x;
  685.    long    y;
  686.    int     i, j, k, f;
  687.  
  688.    if (idx < 0 || idx >= rel->num_i)  return 0;
  689.  
  690.    i = 0;  /* Left edge of word in str */
  691.    for (k = 0; ; k++)
  692.       {
  693.       if (! str[i])  break;
  694.       for (j = i; str[j] && str[j] != ','; j++)
  695.          ;
  696.       strcpy (temp, &str[i]);  temp[j-i] = 0;  i = j;
  697.  
  698.       strzcpy (t2, &rel->idxs[idx][3*k +3], 3);  f = atoi (t2);
  699.  
  700.       x = (dataptr)((char *)ptr + rel->start[f]);  /* Position of field */
  701.  
  702.       switch (rel->type[f])
  703.          {
  704.          case T_SHORT:   *(short   *)x = (short) atoi (temp);  break;
  705.          case T_USHORT:  *(ushort  *)x = (ushort)atoi (temp);  break;
  706.          case T_LONG:    *(long    *)x = (long)  atol (temp);  break;
  707.          case T_ULONG:   *(ulong   *)x = (ulong) atol (temp);  break;
  708.          case T_FLOAT:   *(float   *)x = (float) atof (temp);  break;
  709.          case T_DOUBLE:
  710.          case T_MONEY:   *(double  *)x = (double)atof (temp);  break;
  711.          case T_TIME:    *(mb_time *)x = scn_time (temp);      break;
  712.          case T_DATE:    *(mb_date *)x = scn_date (temp);      break;
  713.          case T_SERIAL:  *(long    *)x = (long)  atol (temp);  break;
  714.          default:        strcpy (x, temp);                     break;
  715.          }
  716.  
  717.       if (rel->type[f] == T_MONEY)
  718.          {
  719.          y = (long)(100.0 * (double)atof (temp));
  720.          *(double *)x = (double)y / 100.0;
  721.          }
  722.       }
  723.    return 1;
  724. }
  725.  
  726.