home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 168_01 / cmd.c < prev    next >
Text File  |  1985-08-21  |  21KB  |  855 lines

  1. /* SDB - command parser */
  2.  
  3. #include "stdio.h"
  4. #include "sdbio.h"
  5.  
  6. extern int dbv_token;
  7. extern char dbv_tstring[];
  8. extern int dbv_tvalue;
  9. extern struct ifile *dbv_ifp;
  10. extern struct macro *dbv_macros;
  11. extern int dbv_fold;
  12.  
  13. #ifdef Lattice
  14. int _fmode = 0;  /*dns*/
  15. #endif
  16.  
  17. /* db_parse - parse a command */
  18. int db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  19.   char *fmt;
  20. {
  21.     int sts;
  22.  
  23.     /* check for a command line */
  24.     if (fmt != NULL)
  25.         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
  26.  
  27.     /* determine the statement type */
  28.     switch (db_ntoken()) {
  29.     case ';':   sts = TRUE;
  30.                 break;
  31.     case COMPRESS:
  32.                 sts = db_squeeze(NULL);
  33.                 break;
  34.     case CREATE:
  35.                 sts = create();
  36.                 break;
  37.     case DEFINE:
  38.                 sts = mc_define();
  39.                 break;
  40.     case DELETE:
  41.                 sts = delete();
  42.                 break;
  43.     case EXIT:
  44.                 exit();
  45.     case EXPORT:
  46.                 sts = db_export(NULL);
  47.                 break;
  48.     case EXTRACT:
  49.                 sts = db_extract(NULL);
  50.                 break;
  51.     case HELP:
  52.                 sts = help();
  53.                 break;
  54.     case IMPORT:
  55.                 sts = db_import(NULL);
  56.                 break;
  57.     case INSERT:
  58.                 sts = insert();
  59.                 break;
  60.     case PRINT:
  61.                 sts = print();
  62.                 break;
  63.     case SELECT:
  64.                 sts = select();
  65.                 break;
  66.     case SET:
  67.                 sts = set();
  68.                 break;
  69.     case SHOW:
  70.                 sts = mc_show();
  71.                 break;
  72.     case SORT:
  73.                 sts = db_sort(NULL);
  74.                 break;
  75.     case UPDATE:
  76.                 sts = update();
  77.                 break;
  78.     default:
  79.                 return (db_ferror(SYNTAX));
  80.     }
  81.  
  82.     return (sts);
  83. }
  84.  
  85. /* help - print a short help message */
  86. static int help()
  87. {
  88.     FILE *fp;
  89.     int ch;
  90.  
  91.     if ((fp = fopen("sdb.hlp","r")) != NULL) {
  92.      /* while ((ch = agetc(fp)) != EOF)    dns */
  93.         while ((ch =  getc(fp)) != EOF)
  94.             putchar(ch);
  95.         fclose(fp);
  96.     }
  97.     else
  98.         printf("No online help available.  Read the manual\n");
  99.  
  100.     /* return successfully */
  101.     return (TRUE);
  102. }
  103.  
  104. /* create - create a new relation */
  105. static int create()
  106. {
  107.     struct relation *rptr;
  108.     char aname[STRINGMAX+1];
  109.     int atype;
  110.  
  111.     /* get relation name */
  112.     if (db_ntoken() != ID)
  113.         return (db_ferror(SYNTAX));
  114.  
  115.     /* start relation creation */
  116.     if ((rptr = db_rcreate(dbv_tstring)) == NULL)
  117.         return (FALSE);
  118.  
  119.     /* check for attribute list */
  120.     if (db_ntoken() != '(') {
  121.         free(rptr);
  122.         return (db_ferror(SYNTAX));
  123.     }
  124.  
  125.     /* parse the attributes */
  126.     while (TRUE) {
  127.  
  128.         /* get the attribute name */
  129.         if (db_ntoken() != ID) {
  130.             free(rptr);
  131.             return (db_ferror(SYNTAX));
  132.         }
  133.         strcpy(aname,dbv_tstring);
  134.  
  135.         /* get the attribute type */
  136.         db_ntoken();
  137.         if (dbv_token == CHAR)
  138.             atype = TCHAR;
  139.         else if (dbv_token == NUM)
  140.             atype = TNUM;
  141.         else {
  142.             free(rptr);
  143.             return (db_ferror(SYNTAX));
  144.         }
  145.  
  146.         /* get the attribute size */
  147.         if (db_ntoken() != NUMBER) {
  148.             free(rptr);
  149.             return (db_ferror(SYNTAX));
  150.         }
  151.  
  152.         /* add the attribute */
  153.         if (!db_rcattr(rptr,aname,atype,dbv_tvalue)) {
  154.             free(rptr);
  155.             return (FALSE);
  156.         }
  157.  
  158.         /* check for end of attributes */
  159.         if (db_token() != ID)
  160.             break;
  161.     }
  162.  
  163.     /* check for attribute list end */
  164.     if (db_ntoken() != ')') {
  165.         free(rptr);
  166.         return (db_ferror(SYNTAX));
  167.     }
  168.  
  169.     /* check for relation size */
  170.     if (db_ntoken() != NUMBER) {
  171.         free(rptr);
  172.         return (db_ferror(SYNTAX));
  173.     }
  174.  
  175.     /* finish relation creation */
  176.     if (!db_rcheader(rptr))
  177.         return (FALSE);
  178.     if (!db_rctuples(rptr,dbv_tvalue))
  179.         return (FALSE);
  180.     if (!db_rcdone(rptr))
  181.         return (FALSE);
  182.  
  183.     /* return successfully */
  184.     return (TRUE);
  185. }
  186.  
  187. /* insert - insert a tuple into a relation */
  188. static int insert()
  189. {
  190.     struct scan *sptr;
  191.     struct attribute *aptr;
  192.     char aname[ANSIZE+1],avalue[STRINGMAX+1];
  193.     int tcnt,astart,i;
  194.  
  195.     /* get relation name */
  196.     if (db_token() == ID)
  197.         db_ntoken();
  198.     else
  199.         strcpy(dbv_tstring,"sdbcur");
  200.  
  201.     /* make sure that the rest of the line is blank */
  202.     if (!db_flush())
  203.         return (FALSE);
  204.  
  205.     /* open the relation */
  206.     if ((sptr = db_ropen(dbv_tstring)) == NULL)
  207.         return (FALSE);
  208.  
  209.     /* insert tuples */
  210.     for (tcnt = 0; ; tcnt++) {
  211.  
  212.         /* print separator if not the first tuple */
  213.         if (tcnt != 0)
  214.             printf("----\n");
  215.  
  216.         /* get attribute values */
  217.         astart = 1;
  218.         for (i = 0; i < NATTRS; i++) {
  219.  
  220.             /* get a pointer to the current attribute */
  221.             aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
  222.  
  223.             /* check for the last attribute */
  224.             if (aptr->at_name[0] == 0)
  225.                 break;
  226.  
  227.             /* get the attribute name */
  228.             strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
  229.  
  230.             /* setup null prompt strings */
  231.             db_prompt(NULL,NULL);
  232.  
  233.             /* prompt and input attribute value */
  234.             while (TRUE) {
  235.                 if (dbv_ifp == NULL)
  236.                     if (strlen(aname) < 8)
  237.                         printf("%s\t\t: ",aname);
  238.                     else
  239.                         printf("%s\t: ",aname);
  240.                 if (db_gline(avalue) != NULL)
  241.                     break;
  242.             }
  243.  
  244.             /* check for last insert */
  245.             if (i == 0 && avalue[0] == EOS)
  246.                 break;
  247.  
  248.             /* store the attribute value */
  249.             db_aput(aptr,&sptr->sc_tuple[astart],avalue);
  250.  
  251.             /* update the attribute start */
  252.             astart += aptr->at_size;
  253.         }
  254.  
  255.         /* check for last insert */
  256.         if (avalue[0] == EOS)
  257.             break;
  258.  
  259.         /* store the new tuple */
  260.         if (!db_rstore(sptr)) {
  261.             db_rclose(sptr);
  262.             return (FALSE);
  263.         }
  264.     }
  265.  
  266.     /* close the relation */
  267.     db_rclose(sptr);
  268.  
  269.     /* check number of tuples inserted */
  270.     if (tcnt != 0) {
  271.  
  272.         /* print tuple count */
  273.         printf("[ %d inserted ]\n",tcnt);
  274.     }
  275.     else
  276.         printf("[ none inserted ]\n");
  277.  
  278.     /* return successfully */
  279.     return (TRUE);
  280. }
  281.  
  282. /* delete - delete tuples from a relation */
  283. static int delete()
  284. {
  285.     struct sel *slptr;
  286.     struct srel *srptr;
  287.     int tcnt;
  288.  
  289.     /* parse the retrieval clause */
  290.     if ((slptr = db_retrieve(NULL)) == NULL)
  291.         return (FALSE);
  292.  
  293.     /* loop through the retrieved tuples */
  294.     for (tcnt = 0; db_fetch(slptr); tcnt++)
  295.  
  296.         /* delete the retrieved tuples */
  297.         for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
  298.             if (!db_rdelete(srptr->sr_scan)) {
  299.                 db_done(slptr);
  300.                 return (FALSE);
  301.             }
  302.  
  303.     /* finish the retrieval */
  304.     db_done(slptr);
  305.  
  306.     /* check number of tuples deleted */
  307.     if (tcnt != 0) {
  308.  
  309.         /* print tuple count */
  310.         printf("[ %d deleted ]\n",tcnt);
  311.     }
  312.     else
  313.         printf("[ none deleted ]\n");
  314.  
  315.     /* return successfully */
  316.     return (TRUE);
  317. }
  318.  
  319. /* update - update tuples from a relation */
  320. static int update()
  321. {
  322.     struct sel *slptr;
  323.     struct sattr *saptr;
  324.     struct attribute *aptr;
  325.     char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap;
  326.     int tcnt;
  327.  
  328.     /* parse the selection clause */
  329.     if ((slptr = db_select(NULL)) == NULL)
  330.         return (FALSE);
  331.  
  332.     /* make sure that the rest of the line is blank */
  333.     if (!db_flush()) {
  334.         db_done(slptr);
  335.         return (FALSE);
  336.     }
  337.  
  338.     /* loop through the selected tuples */
  339.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  340.  
  341.         /* print separator if not the first tuple */
  342.         if (tcnt != 0)
  343.             printf("----\n");
  344.  
  345.         /* loop through the selected attributes */
  346.         for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  347.  
  348.             /* get the attribute pointer */
  349.             aptr = saptr->sa_attr;
  350.  
  351.             /* get the attribute name */
  352.             strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
  353.  
  354.             /* get the attribute value */
  355.             db_aget(aptr,saptr->sa_aptr,avalue);
  356.             for (ap = avalue; isspace(*ap); ap++)
  357.                 ;
  358.  
  359.             /* print it */
  360.             if (strlen(aname) < 8)
  361.                 printf("%s\t\t: %s\n",aname,ap);
  362.             else
  363.                 printf("%s\t: %s\n",aname,ap);
  364.  
  365.             /* setup null prompt strings */
  366.             db_prompt(NULL,NULL);
  367.  
  368.             /* prompt and input attribute value */
  369.             while (TRUE) {
  370.                 if (strlen(aname) < 8)
  371.                     printf("%s\t\t: ",aname);
  372.                 else
  373.                     printf("%s\t: ",aname);
  374.                 if (db_gline(avalue) != NULL)
  375.                     break;
  376.             }
  377.  
  378.             /* store the attribute value */
  379.             if (avalue[0] != EOS) {
  380.                 db_aput(aptr,saptr->sa_aptr,avalue);
  381.                 saptr->sa_srel->sr_update = TRUE;
  382.             }
  383.         }
  384.  
  385.         /* update the tuples */
  386.         db_update(slptr);
  387.     }
  388.  
  389.     /* finish the selection */
  390.     db_done(slptr);
  391.  
  392.     /* check number of tuples updated */
  393.     if (tcnt != 0) {
  394.  
  395.         /* print tuple count */
  396.         printf("[ %d updated ]\n",tcnt);
  397.     }
  398.     else
  399.         printf("[ none updated ]\n");
  400.  
  401.     /* return successfully */
  402.     return (TRUE);
  403. }
  404.  
  405. /* print - print tuples from a set of relations */
  406. static int print()
  407. {
  408.     struct sel *slptr;
  409.     FILE *ffp,*ofp;
  410.     int tcnt;
  411.  
  412.     /* parse the using clause */
  413.     if (!using(&ffp,".frm"))
  414.         return (FALSE);
  415.  
  416.     /* parse the select clause */
  417.     if ((slptr = db_select(NULL)) == NULL)
  418.         return (FALSE);
  419.  
  420.     /* parse the into clause */
  421.     if (!db_to(&ofp,".txt")) {
  422.         db_done(slptr);
  423.         return (FALSE);
  424.     }
  425.  
  426.     /* check for normal or formated output */
  427.     if (ffp == NULL)
  428.         tcnt = table(ofp,slptr);
  429.     else
  430.         tcnt = form(ofp,slptr,ffp);
  431.  
  432.     /* finish the selection */
  433.     db_done(slptr);
  434.  
  435.     /* close the form definition file */
  436.     if (ffp != NULL)
  437.         fclose(ffp);
  438.  
  439.     /* close the output file */
  440.     if (ofp != stdout)
  441.         fclose(ofp);
  442.  
  443.     /* check number of tuples selected */
  444.     if (tcnt != 0)
  445.         printf("[ %d found ]\n",tcnt);
  446.     else
  447.         printf("[ none found ]\n");
  448.  
  449.     /* return successfully */
  450.     return (TRUE);
  451. }
  452.  
  453. /* select - select tuples from a set of relations */
  454. static int select()
  455. {
  456.     struct sel *slptr;
  457.     struct relation *rptr;
  458.     struct sattr *saptr;
  459.     char *aname,*tbuf;
  460.     int tcnt,abase,i;
  461.  
  462.     /* parse the select clause */
  463.     if ((slptr = db_select(NULL)) == NULL)
  464.         return (FALSE);
  465.  
  466.     /* create a new relation */
  467.     if ((rptr = db_rcreate("sdbcur")) == NULL) {
  468.         db_done(slptr);
  469.         return (FALSE);
  470.     }
  471.  
  472.     /* create the selected attributes */
  473.     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  474.  
  475.         /* decide which attribute name to use */
  476.         if ((aname = saptr->sa_name) == NULL)
  477.             aname = saptr->sa_aname;
  478.  
  479.         /* add the attribute */
  480.         if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type,
  481.                                   saptr->sa_attr->at_size)) {
  482.             free(rptr);
  483.             db_done(slptr);
  484.             return (FALSE);
  485.         }
  486.     }
  487.  
  488.     /* create the relation header */
  489.     if (!db_rcheader(rptr)) {
  490.         db_done(slptr);
  491.         return (FALSE);
  492.     }
  493.  
  494.     /* allocate and initialize a tuple buffer */
  495.     if ((tbuf = calloc(1,rptr->rl_size)) == NULL) {
  496.         db_rcdone(rptr);
  497.         return (db_ferror(INSMEM));
  498.     }
  499.     tbuf[0] = ACTIVE;
  500.  
  501.     /* loop through the selected tuples */
  502.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  503.  
  504.         /* create the tuple from the selected attributes */
  505.         abase = 1;
  506.         for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  507.             for (i = 0; i < saptr->sa_attr->at_size; i++)
  508.                 tbuf[abase + i] = saptr->sa_aptr[i];
  509.             abase += i;
  510.         }
  511.  
  512.         /* write the tuple */
  513.         if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
  514.             db_rcdone(rptr);
  515.             free(tbuf);
  516.             return (db_ferror(INSBLK));
  517.         }
  518.         rptr->rl_tcnt++;
  519.         rptr->rl_tmax++;
  520.     }
  521.  
  522.     /* finish the selection */
  523.     db_done(slptr);
  524.  
  525.     /* finish relation creation */
  526.     if (!db_rcdone(rptr))
  527.         return (FALSE);
  528.  
  529.     /* check number of tuples selected */
  530.     if (tcnt != 0)
  531.         printf("[ %d found ]\n",tcnt);
  532.     else
  533.         printf("[ none found ]\n");
  534.  
  535.     /* return successfully */
  536.     return (TRUE);
  537. }
  538.  
  539. /* mc_define - define a macro */
  540. static int mc_define()
  541. {
  542.     struct macro *mptr,*mlast;
  543.     struct mtext *tptr,*tlast;
  544.     char textline[LINEMAX+1];
  545.  
  546.     /* get macro name */
  547.     if (db_xntoken() != ID)
  548.         return (db_ferror(SYNTAX));
  549.  
  550.     /* make sure that the rest of the line is blank */
  551.     if (!db_flush())
  552.         return (FALSE);
  553.  
  554.     /* find the macro in the macro table and free it */
  555.     for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast = mptr, mptr = mptr->mc_next)
  556.         if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
  557.             if (mlast == NULL)
  558.                 dbv_macros = mptr->mc_next;
  559.             else
  560.                 mlast->mc_next = mptr->mc_next;
  561.             mc_free(mptr);
  562.         }
  563.  
  564.     /* allocate and initialize a macro structure */
  565.     if ((mptr = malloc(sizeof(struct macro))) == NULL)
  566.         return (db_ferror(INSMEM));
  567.     if ((mptr->mc_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
  568.         free(mptr);
  569.         return (db_ferror(INSMEM));
  570.     }
  571.     strcpy(mptr->mc_name,dbv_tstring);
  572.     mptr->mc_mtext = NULL;
  573.  
  574.     /* setup null prompt strings */
  575.     db_prompt(NULL,"SDB-DEF> ");
  576.  
  577.     /* get definition text */
  578.     for (tlast = NULL; ; tlast = tptr) {
  579.  
  580.         /* get a line */
  581.         db_gline(textline);
  582.         if (textline[0] == EOS || textline[0] == '\n')
  583.             break;
  584.  
  585.         /* allocate a macro text structure */
  586.         if ((tptr = malloc(sizeof(struct mtext))) == NULL) {
  587.             mc_free(mptr);
  588.             return (db_ferror(INSMEM));
  589.         }
  590.         if ((tptr->mt_text = malloc(strlen(textline)+1)) == NULL) {
  591.             mc_free(mptr);
  592.             return (db_ferror(INSMEM));
  593.         }
  594.         strcpy(tptr->mt_text,textline);
  595.         tptr->mt_next = NULL;
  596.  
  597.         /* link it into the macro list */
  598.         if (tlast == NULL)
  599.             mptr->mc_mtext = tptr;
  600.         else
  601.             tlast->mt_next = tptr;
  602.     }
  603.  
  604.     /* link the new macro into the macro list */
  605.     if (tlast == NULL)
  606.         mc_free(mptr);
  607.     else {
  608.         mptr->mc_next = dbv_macros;
  609.         dbv_macros = mptr;
  610.     }
  611.  
  612.     /* return successfully */
  613.     return (TRUE);
  614. }
  615.  
  616. /* mc_show - show a macro */
  617. static int mc_show()
  618. {
  619.     struct macro *mptr;
  620.     struct mtext *tptr;
  621.  
  622.     /* get macro name */
  623.     if (db_xntoken() != ID)
  624.         return (db_ferror(SYNTAX));
  625.  
  626.     /* find the macro in the macro table */
  627.     for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
  628.         if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
  629.             for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next)
  630.                 printf("\t%s\n",tptr->mt_text);
  631.             break;
  632.         }
  633.  
  634.     /* check for successful search */
  635.     if (mptr == NULL)
  636.         printf("*** no macro named: %s ***\n",dbv_tstring);
  637.  
  638.     /* return successfully */
  639.     return (TRUE);
  640. }
  641.  
  642. /* mc_free - free a macro definition */
  643. static mc_free(mptr)
  644.   struct macro *mptr;
  645. {
  646.     struct mtext *tptr;
  647.  
  648.     while ((tptr = mptr->mc_mtext) != NULL) {
  649.         mptr->mc_mtext = tptr->mt_next;
  650.         free(tptr->mt_text);
  651.         free(tptr);
  652.     }
  653.     free(mptr->mc_name);
  654.     free(mptr);
  655. }
  656.  
  657. /* db_to - redirect output into a file */
  658. int db_to(pfp,ext)
  659.   FILE **pfp; char *ext;
  660. {
  661. #ifdef vms
  662.     int fd;
  663. #endif
  664.  
  665.     /* assume no into clause */
  666.     *pfp = stdout;
  667.  
  668.     /* check for "into <fname>" */
  669.     if (db_token() != INTO)
  670.         return (TRUE);
  671.     db_ntoken();
  672.     if (db_ntoken() == ID)
  673.         strcat(dbv_tstring,ext);
  674.     else if (dbv_token != STRING)
  675.         return (db_ferror(SYNTAX));
  676.  
  677.     /* open the output file */
  678. #ifdef vms
  679.     if ((fd = creat(dbv_tstring,0,"rfm=var","rat=cr")) == -1)
  680.         return (db_ferror(OUTCRE));
  681.     *pfp = fdopen(fd,"w");
  682. #else
  683. #ifdef Lattice
  684.     _fmode = 0x8000;  /*dns*/
  685. #endif
  686.     *pfp = fopen(dbv_tstring,"w");  /*dns*/
  687. #ifdef Lattice
  688.     _fmode = 0;       /*dns*/
  689. #endif
  690.     if (*pfp == NULL)               /*dns*/
  691.         return (db_ferror(OUTCRE)); /*dns*/
  692. #endif
  693.  
  694.     /* return successfully */
  695.     return (TRUE);
  696. }
  697.  
  698. /* using - get form definition file spec */
  699. static int using(pfp,ext)
  700.   FILE **pfp; char *ext;
  701. {
  702.     /* assume no using clause */
  703.     *pfp = NULL;
  704.  
  705.     /* check for "using <fname>" */
  706.     if (db_token() != USING)
  707.         return (TRUE);
  708.     db_ntoken();
  709.     if (db_ntoken() == ID)
  710.         strcat(dbv_tstring,ext);
  711.     else if (dbv_token != STRING)
  712.         return (db_ferror(SYNTAX));
  713.  
  714.     /* open the input file */
  715.     if ((*pfp = fopen(dbv_tstring,"r")) == NULL)
  716.         return (db_ferror(INPFNF));
  717.  
  718.     /* return successfully */
  719.     return (TRUE);
  720. }
  721.  
  722. /* table - output a relation table */
  723. static int table(fp,slptr)
  724.   FILE *fp; struct sel *slptr;
  725. {
  726.     int tcnt;
  727.  
  728.     /* loop through the selected tuples */
  729.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  730.  
  731.         /* print table head on first tuple selected */
  732.         if (tcnt == 0)
  733.             db_thead(fp,slptr);
  734.  
  735.         /* print the tuple */
  736.         db_tentry(fp,slptr);
  737.     }
  738.  
  739.     /* print table foot */
  740.     if (tcnt != 0)
  741.         db_tfoot(fp,slptr);
  742.  
  743.     /* return the tuple count */
  744.     return (tcnt);
  745. }
  746.  
  747. /* form - process a form */
  748. static int form(ofp,slptr,ffp)
  749.   FILE *ofp; struct sel *slptr; FILE *ffp;
  750. {
  751.     char aname[ANSIZE+1];
  752.     int ch,tcnt;
  753.  
  754.     /* loop through the selected tuples */
  755.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  756.  
  757.         /* reposition the form definition file */
  758.         fseek(ffp,0L,0);
  759.  
  760.         /* process the form */
  761.         while ((ch = getc(ffp)) != -1)
  762.             if (ch == '<') {
  763.                 get_aname(ffp,aname);
  764.                 put_avalue(ofp,slptr,aname);
  765.             }
  766.             else
  767.                 putc(ch,ofp);
  768.     }
  769.  
  770.     /* return the tuple count */
  771.     return (tcnt);
  772. }
  773.  
  774. /* get_aname - get an attribute name */
  775. static get_aname(fp,aname)
  776.   FILE *fp; char *aname;
  777. {
  778.     int ch;
  779.  
  780.     while ((ch = getc(fp)) != '>')
  781.         if (!isspace(ch))
  782.             *aname++ = ch;
  783.     *aname = 0;
  784. }
  785.  
  786. /* put_avalue - output attribute value */
  787. static put_avalue(fp,slptr,aname)
  788.   FILE *fp; struct sel *slptr; char *aname;
  789. {
  790.     struct sattr *saptr;
  791.     char *saname;
  792.     int i;
  793.  
  794.     /* loop through the selected attributes */
  795.     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  796.  
  797.         /* check the selected attribute name */
  798.         if ((saname = saptr->sa_name) == NULL)
  799.             saname = saptr->sa_aname;
  800.         if (db_scmp(saname,aname) == 0)
  801.             break;
  802.     }
  803.  
  804.     if (saptr == NULL) {
  805.         fprintf(fp,"<error>");
  806.         return;
  807.     }
  808.  
  809.     /* get the attribute value */
  810.     for (i = 0; i < saptr->sa_attr->at_size; i++)
  811.         if (saptr->sa_aptr[i] != 0)
  812.             putc(saptr->sa_aptr[i],fp);
  813.         else
  814.             putc(' ',fp);
  815. }
  816.  
  817. /* set - set internal parameters */
  818. static int set()
  819. {
  820.     int value;
  821.  
  822.     /* process each set request */
  823.     while (db_token() == ID) {
  824.  
  825.         /* skip the identifier */
  826.         db_ntoken();
  827.  
  828.         /* check for "no" */
  829.         if (db_scmp(dbv_tstring,"no") == 0) {
  830.             value = FALSE;
  831.             if (db_token() != ID)
  832.                 return (db_ferror(BADSET));
  833.             db_ntoken();
  834.         }
  835.         else
  836.             value = TRUE;
  837.  
  838.         /* check for parameter to set */
  839.         if (db_scmp(dbv_tstring,"fold") == 0)
  840.             dbv_fold = value;
  841.         else
  842.             return (db_ferror(BADSET));
  843.     }
  844.  
  845.     /* return successfully */
  846.     return (TRUE);
  847. }
  848.  
  849.                    Page 23
  850.  
  851.  
  852.         Function:
  853.         _________
  854.  
  855.         Fetch the next set of t