vcblib.c
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:17k
源码类别:

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  vcblib.c - tree library of GNU SQL compiler
  3.  *             Vocabulary support.
  4.  *
  5.  *  This file is a part of GNU SQL Server
  6.  *
  7.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  8.  *  Developed at the Institute of System Programming, 
  9.  *  This file is written by Michael Kimelman
  10.  *
  11.  *  This program is free software; you can redistribute it and/or modify
  12.  *  it under the terms of the GNU General Public License as published by
  13.  *  the Free Software Foundation; either version 2 of the License, or
  14.  *  (at your option) any later version.
  15.  *
  16.  *  This program is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *  GNU General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU General Public License
  22.  *  along with this program; if not, write to the Free Software
  23.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  *
  25.  *  Contact: gss@ispras.ru
  26.  *
  27.  */
  28. /* $Id: vcblib.c,v 1.245 1997/03/31 03:46:38 kml Exp $ */
  29. #include "trl.h"
  30. #include "vcblib.h"
  31. #include "trlinter.h"
  32. #include "cycler.h"
  33. #include "type_lib.h"
  34. #include <assert.h>
  35. #include "tassert.h"
  36. static void sort_clmns __P((TXTREF *list));
  37. void check_scan_cols(TXTREF tblptr);
  38. static VCBREF
  39. ind_table(VCBREF index)
  40. {
  41.   /*     table   column   colptr   given_index */
  42.   return COL_TBL(OBJ_DESC(DOWN_TRN(index      )));
  43. }
  44. /*
  45.  * Finding parameters, cursors etc. in vocabulary by only one name. 
  46.  * Each of this kind of nodes stores name as a first parameter.     
  47.  */
  48. VCBREF
  49. find_info( enum token code,LTRLREF l)     
  50. {                                         
  51. #define  VCB_NAME(v)  XLTR_TRN(v,0)       
  52.   register VCBREF vcb;                    
  53.   if     ( code==CURSOR )
  54.     vcb=VCB_ROOT;
  55.   else if( code==PARAMETER || code==SCAN )
  56.     vcb=LOCAL_VCB_ROOT;
  57.   else
  58.     {
  59.       if(code>=LAST_TOKEN)code=0;
  60.       lperror("Internal error: trl.find_info: Unrecognized token code %s n",
  61.               NAME(code));
  62.       return TNULL;
  63.     }
  64.   while(vcb)
  65.     {
  66.       if(CODE_TRN(vcb)==code)
  67.         if(VCB_NAME(vcb)==l || l==TNULL)
  68.           return vcb;
  69.       vcb=RIGHT_TRN(vcb);
  70.     }
  71.   if( code == PARAMETER )
  72.     vcb=VCB_ROOT;
  73.   while(vcb)
  74.     {
  75.     if(CODE_TRN(vcb)==code)
  76.       if(VCB_NAME(vcb)==l || l==TNULL)
  77.         {
  78.           vcb=copy_trn(vcb);
  79.           RIGHT_TRN(vcb)=LOCAL_VCB_ROOT;
  80.           LOCAL_VCB_ROOT=vcb;
  81.           return vcb;
  82.         }
  83.       vcb=RIGHT_TRN(vcb);
  84.     }
  85.   return TNULL;
  86. #undef VCB_NAME
  87. }
  88. /*
  89.  * Finding entry in the vocabulary, which would be equivalent to the 
  90.  * given one.
  91.  */
  92. VCBREF
  93. find_entry(VCBREF v)                      
  94. {                                         
  95.   register enum token code;
  96.   register VCBREF vcb;
  97.   
  98.   if(v==TNULL)return TNULL;
  99.   code=CODE_TRN(v);
  100.   switch(code)
  101.     {
  102.     case PARAMETER:
  103.     case CURSOR:
  104.       return find_info(code,XLTR_TRN(v,0));
  105.     case SCAN:
  106.       vcb=LOCAL_VCB_ROOT;
  107.       while(vcb)
  108. {
  109.           LTRLREF l = COR_NAME(v);
  110.   if(CODE_TRN(vcb)==SCAN)
  111.     if((COR_NO(vcb)   == COR_NO (v)) &&
  112.        (COR_TBL(vcb)  == COR_TBL(v)) &&
  113.                (COR_NAME(vcb) == l)
  114.                )
  115.       return vcb;
  116.   vcb=RIGHT_TRN(vcb);
  117. }
  118.       break;
  119.     case UNIQUE:
  120.     case PRIMARY:
  121.     case INDEX:
  122.       vcb = find_entry(ind_table(v));
  123.       if (!vcb)
  124.         return vcb; /* even adequate table not exist */
  125.       vcb = IND_INFO(vcb);
  126.       while(vcb)
  127. {
  128.   CODE_TRN(v) = CODE_TRN(vcb);
  129.   if (trn_equal_p(v,vcb))
  130.     {
  131.       CODE_TRN(v) = code;
  132.       return vcb;
  133.     }
  134.   vcb = RIGHT_TRN(vcb);
  135. }
  136.       CODE_TRN(v) = code;
  137.       break;
  138.     default:
  139.       if(Is_Table(v))
  140. return find_table(code,TBL_FNAME(v),TBL_NAME(v));
  141.       else if(Is_Column(v))
  142. {
  143.   vcb = COL_TBL(v);
  144.   if (!vcb)
  145.     return TNULL;
  146.   vcb=find_entry(vcb);
  147.           /*
  148.             if (!vcb) 
  149.     vcb = COR_TBL(v);
  150.             */
  151.   return find_column(vcb,COL_NAME(v));
  152. }
  153.       if(code<=UNKNOWN || code>=LAST_TOKEN)
  154. code=UNKNOWN;
  155.       fprintf(STDERR,"trl.entry: Unrecognized token code %s n",
  156.       NAME(code));
  157.       yyerror("Internal error #2");
  158.     }
  159.   return TNULL;
  160. }
  161. /*
  162.  * Finding tables, views and so on in the vocabulary by the desired code
  163.  * and 2 given names
  164.  */
  165. VCBREF
  166. find_table(enum token code,LTRLREF l,LTRLREF l1)
  167. {
  168.   register VCBREF vcb;
  169.   if((l==TNULL) && (l1==TNULL))return TNULL;
  170.   if     ( code==VIEW || code==TABLE || code==ANY_TBL )
  171.     vcb=VCB_ROOT;
  172.   else if( code==TMPTABLE )
  173.     vcb=LOCAL_VCB_ROOT;
  174.   else
  175.     {
  176.       char err[100];
  177.       if(code>=LAST_TOKEN)code=0;
  178.       
  179.       sprintf(err,"find_table: Unrecognized token code %s n",NAME(code));
  180.       yyerror(err);
  181.       return TNULL;
  182.     }
  183.   while(vcb)
  184.     {
  185.       register enum token Code=CODE_TRN(vcb);
  186.       if( Code==code || ( code==ANY_TBL && Is_Table(vcb) ))
  187.         if( (TBL_FNAME(vcb)==l || l==TNULL) && (TBL_NAME(vcb)==l1 || l1==TNULL) )
  188.           return vcb;
  189.       vcb=RIGHT_TRN(vcb);
  190.     }
  191.   return TNULL;
  192. }
  193. static void
  194. add_to_the_end(TXTREF *root,TXTREF node)
  195. {
  196.   register TXTREF c;
  197.   if(*root==TNULL)
  198.    *root=node;
  199.   else
  200.     {
  201.       for(c=*root;RIGHT_TRN(c);c=RIGHT_TRN(c));
  202.       RIGHT_TRN(c)=node;
  203.     }
  204.   RIGHT_TRN(node) = TNULL;
  205. }
  206. /*
  207.  * add information to the vocabulary with checking for existing of equivalent
  208.  * entries
  209.  */
  210. VCBREF
  211. add_info_l(VCBREF v)
  212. {
  213.   register VCBREF vcb;
  214.   register enum token code;
  215.   register i4_t  ins_no;
  216.   if(v==TNULL)return v;
  217.   code = CODE_TRN(v);
  218.   switch(code)
  219.     {
  220.     case CURSOR:
  221.       vcb=find_info(code,CUR_NAME(v));
  222.       if(vcb!=TNULL) return vcb;
  223.       add_to_the_end(&VCB_ROOT,v);
  224.       break;
  225.     case VIEW:
  226.     case TABLE:
  227.     case ANY_TBL:
  228.       vcb=find_table(code,TBL_FNAME(v),TBL_NAME(v));
  229.       if(vcb!=TNULL) return vcb;
  230.       add_to_the_end(&VCB_ROOT,v);
  231.       break;
  232.     case TMPTABLE:
  233.       vcb=find_table(code,TBL_FNAME(v),TBL_NAME(v));
  234.       if(vcb!=TNULL) return vcb;
  235.       if(TBL_FNAME(v)==TNULL)
  236.         TBL_FNAME(v)=GL_AUTHOR;
  237.       if(TBL_NAME(v)==TNULL)
  238.         {
  239.           static tmptblno=0;
  240.           char b[40];
  241.           sprintf(b,"tmp%d",++tmptblno);
  242.           TBL_NAME(v)=ltr_rec(b);
  243.         }
  244.       add_to_the_end(&LOCAL_VCB_ROOT,v);
  245.       break;
  246.     case PARAMETER:
  247.       vcb=find_info(code,PAR_NAME(v));
  248.       if(vcb!=TNULL) return vcb;
  249.       add_to_the_end(&LOCAL_VCB_ROOT,v);
  250.       break;
  251.     case SCAN: 
  252.       vcb=LOCAL_VCB_ROOT;
  253.       ins_no = 1;
  254.       while(vcb)
  255. {
  256.   if((CODE_TRN(vcb)==SCAN) && (COR_TBL(vcb)==COR_TBL(v)))
  257.             if (COR_NO(vcb) == COR_NO(v))
  258.               return vcb;
  259.             else if ( ins_no <= COR_NO(vcb) )
  260.               ins_no = COR_NO(vcb) + 1;
  261.   vcb=RIGHT_TRN(vcb);
  262. }
  263.       if(COR_NO(v) <0)
  264.         COR_NO(v)=ins_no;
  265.       add_to_the_end(&LOCAL_VCB_ROOT,v);
  266.       break;
  267.     case COLUMN:
  268.       {
  269.         TXTREF tbl = COL_TBL(v);
  270.         vcb=find_column(tbl,COL_NAME(v));
  271.         if(vcb!=TNULL)return vcb;
  272.         if(TstF_TRN(tbl,CHECKED_F)) /* if table contains information   */
  273.           {                          /*  from database                   */
  274.             yyerror("Internal error:"
  275.                     " it's impossible to change table information now");
  276.             return TNULL;
  277.           }
  278.         add_to_the_end(&TBL_COLS(COL_TBL(v)),v);
  279.         TBL_NCOLS(tbl)++;
  280.         break;
  281.       }
  282.     case SCOLUMN:
  283.       {
  284.         TXTREF scan = COL_TBL(v);
  285.         vcb=find_column(scan,COL_NAME(v));
  286.         if(vcb!=TNULL)
  287.           return vcb;
  288.         vcb = find_column(COR_TBL(scan),COL_NAME(v));
  289.         if (!vcb)
  290.           {
  291.             CODE_TRN(v) = COLUMN;
  292.             COL_TBL(v) = COR_TBL(scan);
  293.             add_info(v); /* if it's impossible we never back here */
  294.           }
  295.         add_column(scan,COL_NAME(v));
  296.         return find_column(scan,COL_NAME(v));
  297.       }
  298.     case PRIMARY:
  299.     case UNIQUE:
  300.     case INDEX:
  301.       vcb=find_entry(v);
  302.       if(vcb!=TNULL)
  303. {
  304.   CODE_TRN(vcb) = CODE_TRN(v);
  305.   return vcb;
  306. }
  307.       SetF_TRN(v,VCB_F);
  308.       add_to_the_end(&IND_INFO(ind_table(v)),v);
  309.       break;
  310.     default:
  311.       if(code>=LAST_TOKEN)code=0;
  312.       fprintf(STDERR,"trl.add_info: Unrecognized token code %s n",
  313.       NAME(code));
  314.       yyerror("Internal error #2");
  315.       return TNULL;
  316.     }
  317.   return v;
  318. }
  319. /* 
  320.  * add info to vocabulary and return status
  321.  */
  322. CODERT
  323. add_info(VCBREF v)                       
  324. {
  325.   enum token code = CODE_TRN(v);
  326.   VCBREF v1=add_info_l(v);
  327.   if(v1==v)
  328.     return 0;
  329.   if (code == SCOLUMN)
  330.     {
  331.       if (CODE_TRN(v)==SCOLUMN && trn_equal_p(v,v1))
  332.         return 0;
  333.       if (CODE_TRN(v)==COLUMN)
  334.         {
  335.           TXTREF vv=find_column(COR_TBL(COL_TBL(v1)),COL_NAME(v1));
  336.           if(vv==v)
  337.             return 0;
  338.         }
  339.     }
  340.   fprintf(STDERR,"n trl.add_info: Internal error "
  341.           "n -- duplicate vocabulary info n");
  342.   yyfatal("Abort.");
  343.   return -1; /* unreachable */
  344. }
  345. /*
  346.  * delete given node from vocabulary
  347.  */
  348. CODERT
  349. del_info(VCBREF v)                       
  350. {
  351.   register VCBREF *Vcb,vcb,cv;
  352.   register enum token code;
  353.   if(v==TNULL) return 0;     
  354.   if(!TstF_TRN(v,VCB_F))
  355.     {
  356.       fprintf(STDERR,"Impossible delete non vocabulary entry in del_infon");
  357.       return 1;
  358.     }
  359.   code = CODE_TRN(v);
  360.   cv=TNULL;
  361.   switch(code)
  362.     {
  363.     case CURSOR:
  364.     case VIEW:
  365.     case TABLE:
  366.     case ANY_TBL:
  367.       Vcb=&VCB_ROOT;
  368.       break;
  369.     case SCAN:
  370.     case PARAMETER:
  371.     case TMPTABLE:
  372.       Vcb=&LOCAL_VCB_ROOT;
  373.       break;
  374.     case COLUMN:
  375.       Vcb=&TBL_COLS(COL_TBL(v));
  376.       break;
  377.     case SCOLUMN:
  378.       Vcb=&COR_COLUMNS(COL_TBL(v));
  379.       break;
  380.     case PRIMARY:
  381.     case UNIQUE:
  382.     case INDEX:
  383.       Vcb=&IND_INFO(ind_table(v));
  384.     default:
  385.       fprintf(STDERR,"trl.del_info: Unrecognized token code =%d n",
  386.                      (i4_t)code);
  387.       yyerror("Internal error #2");
  388.       return -1;
  389.     }
  390.   vcb=*Vcb;
  391.   cv=TNULL;
  392.   if(vcb==v)
  393.     vcb=RIGHT_TRN(cv=v);
  394.   else LPROC(cv,vcb)
  395.     if(RIGHT_TRN(cv)==v)
  396.       {
  397.         RIGHT_TRN(cv)=RIGHT_TRN(v);
  398.         break;
  399.       }
  400.   if(cv==TNULL && code==PARAMETER)
  401.     {
  402.       Vcb=&VCB_ROOT;
  403.       vcb=*Vcb;
  404.       if(vcb==v)
  405.         vcb=RIGHT_TRN(cv = v);
  406.       else LPROC(cv,vcb)
  407.         if(RIGHT_TRN(cv)==v)
  408.           {
  409.             RIGHT_TRN(cv)=RIGHT_TRN(v);
  410.             break;
  411.           }
  412.     }
  413.   *Vcb=vcb;
  414.   if(cv==TNULL)
  415.     {
  416.       fprintf(STDERR,"Vocabulary entry not found in vocabulary !!!!n");
  417.       debug_trn(v);
  418.       return -1;
  419.     }
  420.   else
  421.     {
  422.       RIGHT_TRN(v)=TNULL;
  423.       if (CODE_TRN(v) == COLUMN)
  424.         TBL_NCOLS(COL_TBL(v))--;
  425.       free_line(v);
  426.     }
  427.   return 0;
  428. }
  429. /* 
  430.  * Finding column of the given table by name or by column number (DB info)
  431.  * tbl - reference to table;
  432.  * l   - name of column ;
  433.  * num - DB number of column;
  434.  * fl  - switcher for finding column by name or by number 
  435.  */
  436. static VCBREF
  437. find_column_A(TXTREF tbl,LTRLREF l,i4_t num,i4_t fl)
  438. {
  439.   register TXTREF vcb;
  440.   register enum token code;
  441.   if(tbl==TNULL) return TNULL;
  442.   code=CODE_TRN(tbl);
  443.   
  444.   if(l==TNULL && fl==0)return TNULL;
  445.   switch(code)
  446.   {
  447.   case SCAN:
  448.        vcb=COR_COLUMNS(tbl);
  449.        break;
  450.   default:
  451.       if(Is_Table(tbl))
  452.         {
  453.           vcb=TBL_COLS(tbl);
  454.           break;          
  455.         }
  456.       if(code>=LAST_TOKEN)code=0;
  457.       fprintf(STDERR,"trl.find_column: Unrecognized token code %s n",
  458.                      NAME(code));
  459.       yyerror("Internal error #2");
  460.       return TNULL;
  461.   }
  462.   for(; vcb ;vcb=RIGHT_TRN(vcb))
  463.     if( ((fl==0) && (l==COL_NAME(vcb))) ||
  464.         ((fl!=0) && (num==COL_NO(vcb)))
  465.       )
  466.       return vcb;
  467.   return TNULL;
  468. }
  469. VCBREF
  470. find_column(TXTREF tbl,LTRLREF l) 
  471. {
  472.   return find_column_A(tbl,l,0,0); 
  473. }
  474. VCBREF 
  475. find_column_by_number(TXTREF tbl,i4_t num)
  476. {
  477.   return find_column_A(tbl,0,num,1);
  478. }
  479. CODERT
  480. add_column(TXTREF tbl,LTRLREF l)       
  481. {
  482.   register TXTREF vcb,newv;
  483.   register i4_t    flag;
  484.   register enum token code;
  485.   if(tbl==TNULL)return SQL_ERROR;
  486.   if(l==TNULL)return SQL_ERROR;
  487.   code=CODE_TRN(tbl);
  488.   if(find_column(tbl,l))
  489.     {
  490.       lperror("Warning: add duplicate column '%s' to next table:n",
  491.               STRING(l));
  492.       debug_trn(tbl);
  493.       return SQL_ERROR;
  494.     }
  495.   switch(code)
  496.   {
  497.   case SCAN:
  498.        vcb=find_column(COR_TBL(tbl),l);
  499.        if(!vcb){
  500.          flag=add_column(COR_TBL(tbl),l);
  501.          if(flag)
  502.            return flag;
  503.          vcb=find_column(COR_TBL(tbl),l);
  504.        }
  505.        COPY_NODE(SCOLUMN,vcb,newv);
  506.        COL_TBL(newv)=tbl;
  507.        add_to_the_end(&COR_COLUMNS(tbl),newv);
  508.        sort_clmns(&COR_COLUMNS(tbl));
  509.        break;
  510.   case TABLE:
  511.   case VIEW:
  512.   case ANY_TBL:
  513.   case TMPTABLE:
  514.        if(TstF_TRN(tbl,CHECKED_F)) /* if table contains information   */
  515.        {                          /*  from database                   */
  516.          yyerror("Internal error: it's impossible to change table information now");
  517.          return -1;
  518.        }
  519.        newv=gen_node(COLUMN);
  520.        COL_TBL(newv)=tbl;
  521.        COL_NAME(newv)=l;
  522.        add_to_the_end(&TBL_COLS(tbl),newv);
  523.        TBL_NCOLS(tbl)++; 
  524.        break;
  525.   default:
  526.        if(code>=LAST_TOKEN)code=0;
  527.        fprintf(STDERR,"trl.add_column: Unrecognized token code %s n",
  528.                       NAME(code));
  529.        yyerror("Internal error #2");
  530.        return -1;
  531.   }
  532.   return 0;
  533. }
  534. #define NTYPE(n)  *(node_type(n))
  535. #define is_compatible(a,b)  is_casted(NTYPE(a),NTYPE(b))
  536. sql_type_t *
  537. node_type(TXTREF node)
  538. {
  539.   switch(CODE_TRN(node))
  540.     {
  541.     case COLPTR:    
  542.     case PARMPTR:   
  543.     case OPTR:      return node_type(OBJ_DESC(node));
  544.     case COLUMN:
  545.     case SCOLUMN:   return &COL_TYPE(node);
  546.     case PARAMETER: return &PAR_TTYPE(node);
  547.     case CONST:     return &CNST_TTYPE(node);
  548.     case NULL_VL:   return &NULL_TYPE(node);
  549.     case USERNAME:  return &USR_TYPE(node);
  550.     default:
  551.       if(Is_Operation(node) && Is_Typed_Operation(node))
  552.         return &OPRN_TYPE(node);
  553.       yyfatal("unexpected node in values list");
  554.     }
  555.   /* unreachable code */
  556.   return NULL;
  557. }
  558. static void
  559. type_comp(char *msg,TXTREF e,TXTREF t)
  560. {
  561.   if( !is_compatible(e,t) )
  562.     {
  563.       char err[256];
  564.       sprintf(err,"%sn%s(%s) - ",msg,NAME(CODE_TRN(t)),
  565.               type2str(NTYPE(t)));
  566.       sprintf(err + strlen(err),"%s(%s)n",NAME(CODE_TRN(e)),
  567.               type2str(NTYPE(e)));
  568.       yyerror(err);
  569.       toggle_mark1f(1);
  570.       debug_trn(t);
  571.       toggle_mark1f(1);
  572.       debug_trn(e);
  573.     }
  574.   else if ((NTYPE(t)).code==SQLType_0)
  575.     {
  576.       extern void put_type_to_tree  __P((TXTREF arg_node, sql_type_t *need_type));
  577.       put_type_to_tree(t,node_type(e));
  578.     }
  579. }
  580. #define SWAP(typ,a,b) { typ iv=a; a=b; b=iv;}
  581. void
  582. sort_list_by_col_no(TXTREF *list,TXTREF *l2,TXTREF *l3,
  583.     i4_t is_scols,char *msg2,char *msg3)
  584. {
  585.    TXTREF *elist, *el2 = NULL, *el3 = NULL, ce;
  586.    i4_t    n,i,j,doit,*nlist;
  587.    n=0;
  588.    for(ce=*list;ce;ce=RIGHT_TRN(ce))
  589.      n++;
  590.     if (!n)
  591.       return;
  592.     
  593.    elist = (TXTREF*)xmalloc(sizeof(TXTREF)*n);
  594.    nlist = (i4_t*)xmalloc(sizeof(i4_t)*n);
  595.    for(i=0,ce=*list;ce;ce=RIGHT_TRN(ce),i++)
  596.      {
  597.        elist[i]=ce;
  598.        nlist[i]=COL_NO(is_scols?ce:OBJ_DESC(ce));
  599.      }
  600.    if(l2)
  601.      {
  602.        el2 = (TXTREF*)xmalloc(sizeof(TXTREF)*n);
  603.        for(i=0,ce=*l2;ce && i<n;ce=RIGHT_TRN(ce),i++)
  604.          el2[i]=ce;
  605.        assert(i==n && ce==TNULL);
  606.      }
  607.    if(l3)
  608.      {
  609.        el3 = (TXTREF*)xmalloc(sizeof(TXTREF)*n);
  610.        for(i=0,ce=*l3;ce && i<n;ce=RIGHT_TRN(ce),i++)
  611.          el3[i]=ce;
  612.        assert(i==n && ce==TNULL);
  613.      }
  614.    for(doit=1,j=n;j && doit--;j--) 
  615.      for(i=1;i<j;i++)
  616.        if(nlist[i-1]>nlist[i])
  617.          {
  618.     SWAP(i4_t,nlist[i],nlist[i-1]);
  619.     SWAP(TXTREF,elist[i],elist[i-1]);
  620.     if(l2)
  621.       SWAP(TXTREF,el2[i],el2[i-1]);
  622.     if(l3)
  623.       SWAP(TXTREF,el3[i],el3[i-1]);
  624.     doit = 1;
  625.          }
  626.    if(l2)
  627.      {
  628.        for(i=0;i<n;i++)
  629.          type_comp(msg2,elist[i],el2[i]);
  630.        *l2   = el2[0];
  631.        for(i=0;i<n-1;i++)
  632.          RIGHT_TRN(el2[i])=el2[i+1];
  633.        RIGHT_TRN(el2[n-1])   = TNULL;
  634.        xfree(el2);
  635.      }
  636.    if(l3)
  637.      {
  638.        for(i=0;i<n;i++)
  639.          type_comp(msg3,elist[i],el3[i]);
  640.        *l3 = el3[0];
  641.        for(i=0;i<n-1;i++)
  642.          RIGHT_TRN(el3[i])=el3[i+1];
  643.        RIGHT_TRN(el3[n-1]) = TNULL;
  644.        xfree(el3);
  645.      }
  646.    *list = elist[0];
  647.    for(i=0;i<n-1;i++)
  648.      RIGHT_TRN(elist[i])=elist[i+1];
  649.    RIGHT_TRN(elist[n-1]) = TNULL;
  650.    xfree(elist);
  651.    xfree(nlist);
  652. }
  653. static void
  654. sort_clmns(TXTREF *list)
  655. {
  656.   sort_list_by_col_no(list,NULL,NULL,1,NULL,NULL);
  657. }
  658. i4_t 
  659. count_list(TXTREF list)
  660. {
  661.   register i4_t i;
  662.   for(i=0;list;list=RIGHT_TRN(list))
  663.     i++;
  664.   return i;
  665. }
  666. void
  667. check_scan_cols(TXTREF tblptr)
  668. {
  669.   TXTREF scan;
  670.   
  671.   TASSERT(CODE_TRN(tblptr) == TBLPTR, tblptr);
  672.   
  673.   scan = TABL_DESC(tblptr);
  674.   /* check table columns */
  675.   sort_clmns(&(TBL_COLS(COR_TBL(scan))));
  676.   if(count_list(TBL_COLS(COR_TBL(scan))) != TBL_NCOLS(COR_TBL(scan)))
  677.     {
  678.       yyfatal("table columns haven't been uploaded yet");
  679.     }
  680.   sort_clmns(&(COR_COLUMNS(scan)));
  681.   if (count_list(COR_COLUMNS(scan)) != TBL_NCOLS(COR_TBL(scan)))
  682.     {
  683.       TXTREF a,b,a0=TNULL;
  684.       a=COR_COLUMNS(scan);
  685.       b=TBL_COLS(COR_TBL(scan));
  686.       while(b)
  687.         {
  688.           if(!a || COL_NO(a) > COL_NO(b))
  689.             { /* add skipped column to scan column list */
  690.               extern TXTREF copy_tree(TXTREF); /* kitty/conv.c */
  691.               TXTREF c;
  692.               COPY_NODE (SCOLUMN, b, c);
  693.               COL_TBL (c) = scan;
  694.               COL_DEFAULT(c) = copy_tree(COL_DEFAULT(c));
  695.               
  696.               if(a0) COL_NEXT(a0)      = c;
  697.               else   COR_COLUMNS(scan) = c;
  698.               COL_NEXT(c) = a;
  699.               a0 =c;
  700.             }
  701.           else if (COL_NO(a) == COL_NO(b))
  702.             a=COL_NEXT(a0=a);
  703.           else /* IF COL_NO(a) < COL_NO(b) */
  704.             yyfatal("unexpected column number in scan ");
  705.           b=COL_NEXT(b);
  706.         }
  707.     }
  708. }