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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  trl.c  - tree library support for GNU SQL precompiler
  3.  *
  4.  *  This file is a part of GNU SQL Server
  5.  *
  6.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  7.  *  Developed at the Institute of System Programming
  8.  *  This file is written by Michael Kimelman
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  *
  24.  *  Contacts: gss@ispras.ru
  25.  *
  26.  */
  27. /* $Id: trl.c,v 1.246 1997/03/31 11:01:59 kml Exp $ */
  28. #include "vmemory.h"
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #include "trl.h"
  33. #include "tassert.h"
  34. #include "trlinter.h"
  35. #include "tree_gen.h"
  36. #include "type_lib.h"
  37. #include "cycler.h"
  38. #include "typeif.h"
  39. #include <assert.h>
  40. #include <fcntl.h>
  41. /*******==================================================*******
  42. *******             tree  node description                 *******
  43. *******==================================================*******/
  44. #define DEF_TOKEN(CODE,NAME,FORMAT,STRUCT,FLAGS)  
  45.       {NAME,FORMAT,STRUCT,FLAGS,0},
  46. struct tkn_info token_info[NUM_TRN_CODE] =
  47. {
  48. #include "treecode.def"
  49.   {"Last_token", "*", ' ', " ", 0}
  50. };
  51. /*******==================================================*******
  52. *******             tree  flags description                *******
  53. *******==================================================*******/
  54. #define DEF_FLAG_BIT(CODE,NAME,CLASS,BIT_NO)  DEF_FLAG(CODE,NAME,CLASS)
  55. #define DEF_FLAG(CODE,NAME,CLASS)             {NAME,CLASS,01L<<bt_##CODE},
  56. struct flag_info flg_info[NUMBER_OF_FLAGS] =
  57. {
  58. #include "treeflag.def"
  59.   {NULL, ' ', 0}
  60. };
  61. /*******==================================================*******
  62. *******           Static functions                         *******
  63. *******==================================================*******/
  64. static VADR tree_vm_segment = (VADR) NULL;
  65. static struct tree_root *trl_forest_descriptor = (struct tree_root *) NULL;
  66. static void
  67. trl_init (void)
  68. {
  69.   static i4_t init_trl = 0;
  70.   register i4_t no;
  71.   register enum token code;
  72.   register enum flags f, fb;
  73.   MASKTYPE msk;
  74.   if (init_trl)
  75.     return;
  76.   for (code = 0; code < LAST_TOKEN; code++)
  77.     {
  78.       no = LENGTH (code) = strlen (FORMAT (code));
  79.       msk = 0;
  80.       if (code == OPERAND)
  81.         continue;
  82.       for (f = 0; f < LAST_FLAG; f++)
  83.         if (compatible_tok_fl (code, f))
  84.           if (TstF (msk, f) == 0L)      /* if flag hasn't already been set */
  85.             SetF (msk, f);              /* set it                          */
  86.           else                          /* in other case                   */
  87.             for (fb = 0; fb < f; fb++)  /* check again all previous flags  */
  88.               if (TstF (FLAG_VALUE (f), fb))    /* to find source of       */
  89.                 /* collision               */
  90.                 fprintf (STDERR,        /* and type report about it        */
  91.                          "Internal error: misplaced flags '%s' and '%s'"
  92.                          " for code '%s'n",
  93.                          NAME_FL (f), NAME_FL (fb), NAME (code)
  94.                   );
  95.     }
  96.   init_trl = 1;
  97. }
  98. void
  99. init_tree (void)
  100. {
  101.   if (!tree_vm_segment)
  102.     install (NULL);
  103. }
  104. /*
  105.  * 'change_tree_segment' set internal  'current' segment pointer to the segment
  106.  * where 'ptr_inside' points into. The function also checks if this segment is 
  107.  * really tree segment. 'Action' is a code of additional activity with this 
  108.  * segment. 0 means just switch to this segment. 1 - means switch to the 
  109.  * segment and add its descriptor to the list of acceptable tree segment. 
  110.  * -1 means delete given segment from tree segment list
  111.  */
  112. static TXTREF 
  113. change_tree_segment(TXTREF ptr_inside,i4_t action)
  114. {
  115.   static struct t_seg { 
  116.     TXTREF         tree_id;
  117.     struct t_seg  *next,
  118.                   *prev;
  119.   }                 *head=NULL;
  120.   register TXTREF    seg;
  121.   register struct t_seg *cur;
  122.   
  123.   trl_init ();
  124.   assert( (-1<=action) && (action <=1));
  125.   seg = ptr_inside ? get_vm_segment_id(ptr_inside) : TNULL;
  126.   for( cur = head; cur && cur->tree_id != seg ; cur = cur->next);
  127.   if ( !cur && action != 1 )/* on attempt to switch to or delete             */
  128.                             /* unregistered segment                          */
  129.     return tree_vm_segment; /* do nothing - even don't become angry          */
  130.   if (cur && action == -1 ) /* delete some segment                           */
  131.     {
  132.       if (cur->prev == NULL)
  133. head=cur->next;
  134.       else 
  135. {
  136.   cur->prev->next=cur->next;
  137.   if (cur->next) 
  138.     cur->next->prev=cur->prev;
  139. }
  140.       xfree(cur);
  141.       cur = head;
  142.     }
  143.   else if ( !cur && action == 1 ) /* add segment which hasn't been found     */
  144.     {
  145.       cur=xmalloc(sizeof(*cur));
  146.       cur->tree_id = seg;
  147.       if (head)
  148. {
  149.   cur->next = head;
  150.   cur->next->prev = cur;
  151. }
  152.       head = cur;
  153.     }
  154.   /* right now 'cur' points to desirable segment so let's switch to it       */
  155.   if(!cur)  /* if there is no available segment                              */
  156.     {
  157.       tree_vm_segment = TNULL;
  158.       trl_forest_descriptor = 0;
  159.     }
  160.   else /* if everything is ok */
  161.     {
  162.       VADR vo = GET_CURRENT_SEGMENT_ID;
  163.       tree_vm_segment=cur->tree_id;
  164.       switch_to_segment (tree_vm_segment);
  165.       seg = resolve_local_reference ("_TRL_descriptor");
  166.       if (!seg) 
  167. {
  168.   seg = tree_vm_segment + vm_ob_alloc (sizeof(struct tree_root), 
  169.        sizeof(TXTREF));
  170.   register_export_address (seg,"_TRL_descriptor");
  171.   assert ( seg == resolve_local_reference ("_TRL_descriptor") );
  172.           {
  173.             /*
  174.              * because 'struct tree_root' is collection of TXTREFs we need
  175.              * to register them as relocate.
  176.              */
  177.             i4_t i = sizeof(struct tree_root)/sizeof(TXTREF);
  178.             while(i--)
  179.               register_relocation_address( seg + i*sizeof(TXTREF));
  180.           }
  181.         }
  182.       switch_to_segment (vo);
  183.       trl_forest_descriptor = (struct tree_root *) vpointer (seg);
  184.     }
  185.   return tree_vm_segment;
  186. }
  187. /*******==================================================*******
  188. *******           GLOBAL functions                         *******
  189. *******==================================================*******/
  190. TXTREF *
  191. Root_ptr (enum kind_of_root sel)
  192. {
  193.   switch(sel)
  194.     {
  195.     case Tree_Root:
  196.       return &(trl_forest_descriptor->root);
  197.     case Vcb_Root:
  198.       return &(trl_forest_descriptor->vcbroot);
  199.     case G_Author:
  200.       return &(trl_forest_descriptor->author);
  201.     case Hash_Tbl:
  202.       return &(trl_forest_descriptor->hash_tbl);
  203.     case Current_Tree_Segment:
  204.       return &(tree_vm_segment);
  205.     }
  206.   return (TXTREF*)NULL;
  207. }
  208. TXTREF  
  209. set_current_tree_segment(TXTREF ptr_inside)
  210. {
  211.   return change_tree_segment(ptr_inside,0);
  212. }
  213. TXTREF 
  214. get_current_tree_segment(void)
  215. {
  216.   return tree_vm_segment;
  217. }
  218. /*
  219.  * create new tree segment, mark them as a current one and return identifier 
  220.  * of it.
  221.  */
  222.  
  223. TXTREF 
  224. create_tree_segment(void)
  225. {
  226.   register TXTREF tr; 
  227.   if ( (tr = create_segment () ) == TNULL)
  228.     return TNULL;
  229.   assert( tr == change_tree_segment(tr,1));
  230.   GL_AUTHOR = ltr_rec (get_user_name ());
  231.   return tree_vm_segment;
  232. }
  233. /* do the same but load tree from buffer. */
  234. TXTREF 
  235. load_tree_segment(void *tree_buffer,i4_t len)
  236. {
  237.   register TXTREF tr; 
  238.   if ( (tr = link_segment (tree_buffer, len)) == TNULL)
  239.     return TNULL;
  240.   assert( tr == change_tree_segment(tr,1));
  241.   return tree_vm_segment; 
  242. }
  243. #define CHECK_TREE_DISPOSE_INTEGRITY
  244. void   
  245. dispose_tree_segment(TXTREF ptr_inside)
  246. {
  247.   VADR   sid;
  248.   TXTREF cs=tree_vm_segment,ds;
  249.   if (ptr_inside == TNULL)
  250.     return;
  251.   sid = get_vm_segment_id(ptr_inside);
  252.   if (cs == sid) cs = 0;
  253.   if (sid != change_tree_segment(ptr_inside,0))
  254.     return;
  255. #ifdef CHECK_TREE_DISPOSE_INTEGRITY
  256.   /* free space */
  257.   while (get_statement (1))
  258.     del_statement (1);
  259.   free_line (VCB_ROOT);
  260.   free_hash ();
  261.   ds = tree_vm_segment;
  262.   {
  263.     VADR seg = resolve_local_reference ("_TRL_descriptor");
  264.     if (seg && ds == get_vm_segment_id(seg)) 
  265.       vmfree(seg);
  266.   }
  267. #endif
  268.   change_tree_segment(ptr_inside,-1);
  269.   if (cs && cs != tree_vm_segment)
  270.     change_tree_segment(cs,0);
  271. #ifdef CHECK_TREE_DISPOSE_INTEGRITY
  272. /*
  273.  * The code below isn't really need but should work if all logic  is 
  274.  * correct. Now it isn't so. Therefore we have to avoid this testing 
  275.  * now to be able to check other parts of system.
  276.  */
  277.   if (!unlink_segment (ds, 0))
  278.     {
  279.       yyerror ("Note! freing memory isn't clean");
  280.       errors--;               /* !!!!!!! */
  281.       unlink_segment (ds, 1);
  282.     }
  283. #else
  284.   unlink_segment (ds, 1);
  285. #endif 
  286. }
  287. void *
  288. extract_tree_segment(TXTREF ptr_inside,i4_t *len)
  289. {
  290.   change_tree_segment(ptr_inside,-1);
  291.   return export_segment (ptr_inside, len, 1);
  292. }
  293. #define ERR(cond,msg) if (cond) { yyerror(msg); rc = SQL_ERROR; goto ERR_proc; }
  294. CODERT
  295. install (char *s)
  296. {
  297.   void *dump = NULL;
  298.   i4_t   len = 0;
  299.   FILE *fd; 
  300.   CODERT rc = SQL_SUCCESS; 
  301.   if (s)
  302.     {                           /* loading tree binary image from file */
  303.       fd= fopen (s, "r");
  304.       ERR(fd == NULL,"Can't open tree binary file");
  305.       fseek (fd, 0, SEEK_END);
  306.       len = ftell (fd);
  307.       fseek (fd, 0, SEEK_SET);
  308.       dump = xmalloc (len);
  309.       fread (dump, len, 1, fd);
  310.       fclose (fd);
  311.       if(!load_tree_segment(dump,len))
  312. {
  313.   fprintf (STDERR,
  314.    "Error occured during loading tree from module '%s'",
  315.    s);
  316.   return SQL_ERROR;
  317. }
  318.     }
  319.   else if(!create_tree_segment())
  320.     return SQL_ERROR;
  321. ERR_proc:
  322.   return rc;
  323. }
  324. CODERT
  325. finish (char *s)
  326. {
  327.   void  *dump = NULL;
  328.   i4_t    len = 0;
  329.   FILE  *fd;
  330.   CODERT rc = SQL_SUCCESS; 
  331.   if (s)
  332.     {
  333.       dump = extract_tree_segment (tree_vm_segment, &len);
  334.       ERR(!dump,"Error occured during packing tree to binary array");
  335.       fd = fopen (s, "w");
  336.       ERR(!fd,"Can't open output binary file");
  337.       fwrite (dump, len, 1, fd);
  338.       fclose (fd);
  339.     }
  340.   /* changed by dkv */
  341.   /*
  342.   else
  343.   dispose_tree_segment(tree_vm_segment);
  344.   */
  345. ERR_proc:
  346.   if (dump)
  347.     xfree(dump);
  348.   return rc;
  349. }
  350. #undef ERR
  351. /*******==================================================*******
  352. *******      Constructors and destructors                  *******
  353. *******==================================================*******/
  354. i4_t 
  355. trn_size(enum token code, MASKTYPE msk)
  356. {
  357.   register i4_t size;
  358.   
  359.   size = SIZE_TRN (code);
  360.   if (TstF (msk, PATTERN_F))
  361.     size += ADD_TRN_SIZE(code);
  362.   if (TstF(msk,ACTION_F))
  363.     size += ADD_TRN_SIZE(code);
  364.   return size;
  365.  }
  366. TXTREF
  367. gen_node1 (enum token code, MASKTYPE msk)
  368. {
  369.   static   i4_t scan_no = 0;
  370.   register i4_t size;
  371.   register TXTREF node = TNULL;
  372.   VADR     old ;
  373.   init_tree ();
  374.   if (code == UNKNOWN || code == NIL_CODE)
  375.     return TNULL;
  376.   
  377.   size = trn_size(code,msk);
  378.   /*-----------------------------*/
  379.   old = GET_CURRENT_SEGMENT_ID;
  380.   switch_to_segment (tree_vm_segment);
  381.   node = GET_CURRENT_SEGMENT_ID + vm_ob_alloc (size, sizeof (tr_union));
  382.   switch_to_segment (old);
  383.   /*-----------------------------*/
  384.   Ptree (node)->code = code;
  385.   MASK_TRN (node) = msk;
  386.   switch (code)
  387.     {
  388.     case NOOP:
  389.       XLNG_TRN(node,0) = 1;
  390.       break;
  391.     case USERNAME:
  392.       USR_TYPE(node) = pack_type(SQLType_Char,MAX_USER_NAME_LNG,0);
  393.       break;
  394.     case SCAN:
  395.       {
  396.         char str[100];
  397.         sprintf(str,"scan%d",scan_no++);
  398.         COR_NAME(node) = ltr_rec(str);
  399.       }
  400.       COR_NO(node) = -1;
  401.     case INDEX:
  402.     case UNIQUE:
  403.     case PRIMARY:
  404.     case CURSOR:
  405.     case PARAMETER:
  406.       SetF_TRN (node, VCB_F);
  407.       break;
  408.     default:
  409.       if (Is_Table (node) || Is_Column (node))
  410.         SetF_TRN (node, VCB_F);
  411.       if (Is_Column (node))
  412.         COL_NO(node) = -1;
  413.     }
  414.   {
  415.     register char  *p;
  416.     register i4_t   i;
  417.     for ( p=FORMAT(code),i=-1; *p; p++,i++) 
  418.       switch(*p){
  419.       case 't':case 'v':case 'V':case 'L':case 'T':case 's':
  420.       case 'r':case 'd':case 'P':case 'N':
  421. register_relocation_address( node + sizeof(tree_t) + i * sizeof(tr_union) );
  422.       }
  423.   }
  424.   return node;
  425. }
  426. TXTREF
  427. gen_node (enum token code)
  428. {
  429.   return gen_node1 (code, 0);
  430. }
  431. void
  432. free_node (TXTREF node)
  433. {
  434.   if (!node)
  435.     return;
  436.   if ( tree_memory_mode_state )
  437.     {
  438.       fprintf (STDERR, ">>>>>>>Freeing node at %X ...", (u4_t) node);
  439.       debug_trn (node);
  440.       fprintf (STDERR, "<<<<<<<======================n");
  441.     }
  442.   if (!Ptree(node))
  443.     {
  444.       fprintf (STDERR, "warning (internal problem): "
  445.                "attemp to free unused memoryn");
  446.       return;
  447.     }
  448.   vmfree (node);
  449. }
  450. TXTREF
  451. gen_vect (i4_t len)              /* generate vector     */
  452. {
  453.   register i4_t s;
  454.   register TXTREF vec;
  455.   init_tree ();
  456.   s = sizeof (struct trvec_def) + (len - 1) * sizeof (tr_union);
  457.     {
  458.       VADR old = GET_CURRENT_SEGMENT_ID;
  459.       switch_to_segment (tree_vm_segment);
  460.       vec = GET_CURRENT_SEGMENT_ID + vm_ob_alloc (s, sizeof (tr_union));
  461.       switch_to_segment (old);
  462.     }
  463.   VLEN (vec) = len;
  464.   return vec;
  465. }
  466. TXTREF
  467. realloc_vect (TXTREF n, i4_t newlen)
  468. {
  469.   register TXTREF v;
  470.   register i4_t l;
  471.   v = gen_vect (newlen);
  472.   for ( l = gmin(VLEN(n),newlen)  ; l--;)
  473.     VOP (v, l) = VOP (n, l);
  474.   free_vect (n);
  475.   return v;
  476. }
  477. void
  478. free_vect (TXTREF vec)
  479. {
  480.   vmfree (vec);
  481. }
  482. PNODE
  483. Pnode (register TXTREF n)
  484. {
  485.   return (PNODE) vpointer (n);
  486. }
  487. TXTREF
  488. gen_const_node (SQLType code, char *info)
  489. {
  490.   TXTREF n;
  491.   n = gen_node1 (CONST, 0);
  492.   if (info)
  493.     CNST_NAME (n) = ltr_rec (info);
  494.   switch (code)
  495.     {
  496.     case SQLType_Char:
  497.       CNST_STYPE (n) = pack_type (code, info ? strlen (info) : 0 , 0);
  498.       break;
  499.     case SQLType_Int:
  500.     case SQLType_Long:
  501.     case SQLType_Short:
  502.       if ( strlen(info) > 5 )
  503.         CNST_STYPE (n) = pack_type (SQLType_Int, 0, 0);
  504.       else
  505.         CNST_STYPE (n) = pack_type (SQLType_Short, 0, 0);
  506.       break;
  507.     case SQLType_Num:
  508. #if 1
  509.       {
  510.         register i4_t l, i = strlen (info);
  511.         register char *p = info + i;
  512.         for (l = i; i >= 0; p--, i--)
  513.           if (*p == '.')
  514.             break;
  515.         CNST_STYPE (n) = pack_type (code, l - 1, l - i - 1);
  516.       }
  517.       break;
  518. #else
  519.       code = SQLType_Real;
  520. #endif
  521.     default:
  522.       CNST_STYPE (n) = pack_type (code, 0, 0);
  523.     }
  524.   return n;
  525. }
  526. /*******==================================================*******
  527. *******   Common tree and vocabulary structure support     *******
  528. *******==================================================*******/
  529. CODERT
  530. add_statement (TXTREF p)
  531. {
  532.   TXTREF cp;
  533.   if (CODE_TRN(p) != CUR_AREA)
  534.     SetF_TRN(p,HAS_VCB_F);
  535.   if (!ROOT)
  536.     {
  537.       ROOT = p;
  538.       STMT_UID (p) = 0;
  539.     }
  540.   else
  541.     {
  542.       cp = ROOT;
  543.       while (RIGHT_TRN (cp) != (TNULL))
  544.         cp = RIGHT_TRN (cp);
  545.       RIGHT_TRN (cp) = p;
  546.       STMT_UID (p) = STMT_UID (cp) + 1;
  547.     }
  548.   RIGHT_TRN (p) = TNULL;
  549.   return 0;
  550. }
  551. CODERT
  552. del_statement (i4_t number)
  553. {
  554.   register TXTREF pt = TNULL, t = ROOT;
  555.   if (number <= 0)
  556.     yyfatal ("Internal error: attempt to delete statement with ID < 0");
  557.   while (--number && t)
  558.     {
  559.       /* if(STMT_UID(t)==number) return t; */
  560.       pt = t;
  561.       t = RIGHT_TRN (t);
  562.     }
  563.   if (!t)
  564.     return 0;
  565.   if (!pt)
  566.     ROOT = RIGHT_TRN (t);
  567.   else
  568.     RIGHT_TRN (pt) = RIGHT_TRN (t);
  569.   free_tree (t);
  570.   return 0;
  571. }
  572. TXTREF
  573. get_statement (i4_t number)
  574. {
  575.   register TXTREF t = ROOT;
  576.   while (--number && t)
  577.     {
  578.       /* if(STMT_UID(t)==number) return t; */
  579.       t = RIGHT_TRN (t);
  580.     }
  581.   return t;
  582. }
  583. void
  584. free_line (TXTREF c)
  585. {
  586.   register TXTREF t;
  587.   if ( ! c )
  588.     return;
  589.   if (!Ptree(c))
  590.     {
  591.       fprintf (STDERR, 
  592.        "warning (internal problem): attemp to free unused memoryn");
  593.       return;
  594.     }
  595.   if ( TstF_TRN (c, VCB_F))
  596.     {
  597.       enum token code = CODE_TRN(c);
  598.       if (Is_Table (c))
  599. {
  600.   if (((code == VIEW) ||
  601.        (code == TMPTABLE)) &&
  602.       (VIEW_QUERY (c)))
  603.     {
  604.       t = VIEW_QUERY (c);
  605.       VIEW_QUERY (c) = TNULL;
  606.       free_tree (t);
  607.     }
  608.   else if (( code == TABLE) &&
  609.    (TBL_CONSTR (c) ))
  610.     {
  611.       t = TBL_CONSTR (c); 
  612.       TBL_CONSTR (c) = TNULL;
  613.       free_line (t);
  614.     }
  615. }
  616.       else if (code == COLUMN)
  617. {
  618.           t = COL_DEFAULT(c); 
  619.   COL_DEFAULT (c) = TNULL;
  620.   free_node (t);
  621. }
  622.       else if ( code == UNIQUE || code == PRIMARY || code == INDEX)
  623. {
  624.   t=DOWN_TRN(c);
  625.   DOWN_TRN(c) = TNULL;
  626.   free_line(t);
  627. }
  628.     }
  629.   t = RIGHT_TRN(c);
  630.   RIGHT_TRN(c) = TNULL;
  631.   free_line(t);
  632.   if (Is_Scan (c))
  633.     {
  634.       COR_TBL(c) = TNULL;
  635.       t = COR_COLUMNS(c);
  636.       COR_COLUMNS(c) = TNULL;
  637.       free_line (t);
  638.     }
  639.   else if (Is_Table (c))
  640.     {
  641.       free_line (IND_INFO(c));
  642.       IND_INFO(c) = TNULL;
  643.       t = TBL_COLS (c);
  644.       TBL_COLS(c) = TNULL;
  645.       free_line (t);
  646.     }
  647.   if (TstF_TRN (c, VCB_F))
  648.     free_node (c);
  649.   else
  650.     free_tree (c);
  651. }
  652. void
  653. free_tree (TXTREF root)
  654. {
  655.   register TXTREF t;
  656.   if (!root)
  657.     {
  658.       fprintf (STDERR, "warning (internal problem): "
  659.                "null pointer is tried to freen");
  660.       return;
  661.     }
  662.   if (!Ptree(root))
  663.     {
  664.       fprintf (STDERR, "warning (internal problem): "
  665.                "attemp to free unused memoryn");
  666.       return;
  667.     }
  668.   
  669.   if (TstF_TRN (root, VCB_F))
  670.     return;
  671.   if (HAS_DOWN (root))
  672.     {
  673.       t = DOWN_TRN (root);
  674.       DOWN_TRN(root) = TNULL;
  675.       ARITY_TRN(root) = 0;
  676.       free_line(t);
  677.     }
  678.   
  679.   {
  680.     register char *fmt = FORMAT (CODE_TRN (root));
  681.     register i4_t   i, l;
  682.     for (i = 0; *fmt; fmt++, i++)
  683.       {
  684. #define TST_PAT_BIT(n) TST_BIT(XLNG_TRN(root,PTRN_OP(CODE_TRN(root),n)),PTRN_BIT(n))
  685.         if ( TstF_TRN(root,ACTION_F) && TST_PAT_BIT(i) )
  686.           continue;
  687.         switch (*fmt)
  688.           {
  689.           case 'N':
  690.             if (XTXT_TRN (root, i))
  691.       {
  692. free_line (XTXT_TRN (root, i));
  693. XTXT_TRN(root,i) = TNULL;
  694.       }
  695.             break;
  696.           case 't':
  697.   case 'P':
  698.             if (XTXT_TRN (root, i))
  699.       {
  700. free_tree (XTXT_TRN (root, i));
  701. XTXT_TRN(root,i) = TNULL;
  702.       }
  703.             break;
  704.           case 'T':
  705.             if (XVEC_TRN (root, i))
  706.               for (l = 0; l < XLEN_VEC (root, i); l++)
  707. {
  708.   free_tree (XVECEXP (root, i, l));
  709.   XVECEXP (root, i, l) = TNULL;
  710. }
  711.           case 'L':
  712.             if (XVEC_TRN (root, i))
  713.       {
  714. free_vect (XVEC_TRN (root, i));
  715. XVEC_TRN (root, i) = TNULL;
  716.       }
  717.             break;
  718.           default:
  719.             break;
  720.           }
  721.       }
  722.   }
  723.   if (Is_Statement (root))
  724.     {
  725.       if (CODE_TRN (root) == CUR_AREA)
  726. del_info (STMT_VCB (root));
  727.       else
  728. free_line (STMT_VCB (root));
  729.       STMT_VCB(root) = TNULL;
  730.     }
  731.   if ( CODE_TRN(root) == NOOP)
  732.     {
  733.       XLNG_TRN(root,0)--;
  734.       if (XLNG_TRN(root,0)>0)
  735. return;
  736.     }
  737.   free_node (root);
  738. }
  739. /*******==================================================*******
  740. *******            Other functions                         *******
  741. *******==================================================*******/
  742. int
  743. compatible_tok_fl (enum token code, enum flags fcode)
  744. {
  745.   register char *p;
  746.   if (code == OPERAND)
  747.     return 1;
  748.   for (p = FLAGS (code); *p; p++)
  749.     if (*p == CLASS (fcode))
  750.       return 1;
  751.   return 0;
  752. }
  753. TXTREF
  754. copy_tree (TXTREF src)
  755. {
  756.   TXTREF dest, last_oper, src_oper;
  757.   if(!src)
  758.     return TNULL;
  759.   
  760.   last_oper = TNULL;
  761.   dest = copy_trn (src);
  762.   
  763.   if (dest && HAS_DOWN (dest))
  764.     {
  765.       ARITY_TRN (dest) = ARITY_TRN (src);
  766.       
  767.       for (src_oper = DOWN_TRN (src);
  768.            src_oper;
  769.            src_oper = RIGHT_TRN (src_oper)
  770.            )
  771.         if (last_oper)
  772.           last_oper = RIGHT_TRN (last_oper) = copy_tree (src_oper);
  773.         else
  774.           last_oper = DOWN_TRN (dest)       = copy_tree (src_oper);
  775.       
  776.       RIGHT_TRN (last_oper) = TNULL;
  777.     }
  778.   return dest;
  779. }
  780. #define CHECK_VCB {copy = add_info_l(copy);TASSERT(copy == tmp_trn,copy);}
  781. TXTREF
  782. copy_trn(register TXTREF orig)
  783. {
  784.   register TXTREF copy;
  785.   register enum token code;
  786.     
  787.   DECL_STACK (copy_trn_st, TXTREF);
  788.   
  789.   if (!orig)
  790.     return orig;
  791.   /* Vocabulary check */
  792.   code = CODE_TRN (orig);
  793.   copy = TNULL;
  794.  
  795.   if (TstF_TRN (orig, VCB_F))
  796.     {
  797.       TXTREF c;
  798.       copy = find_entry(orig);
  799.       if (copy)      /* local copy */
  800.         return copy;
  801.       COPY_NODE (code, orig, copy);
  802.       switch(code)
  803.         {
  804.         case TABLE:
  805.         case VIEW:
  806.         case TMPTABLE:
  807.         case ANY_TBL:
  808.           TBL_FNAME(copy) = ltr_rec(STRING(TBL_FNAME(orig)));
  809.           TBL_NAME(copy) = ltr_rec(STRING(TBL_NAME(orig)));
  810.           break;
  811.         case SCAN:
  812.           COR_NAME(copy) = (COR_NAME(orig)?ltr_rec(STRING(COR_NAME(orig))):TNULL);
  813.           COR_TBL(copy)  = copy_trn(COR_TBL(orig));
  814.           break;
  815.         case PRIMARY:
  816.         case UNIQUE:
  817.         case INDEX:
  818.           break;
  819.         case COLUMN:
  820.         case SCOLUMN:
  821.           COL_TBL(copy) = copy_trn(COL_TBL(copy));
  822.         case PARAMETER:
  823.         case CURSOR:
  824.           /* col_name is equivalent here to par_name, CUR_name */
  825.           COL_NAME(copy) = ltr_rec(STRING(COL_NAME(orig)));
  826.           break;
  827.         default:
  828.           lperror("unexpected vcb node: '%s' ",NAME(code));
  829.           return copy;
  830.         }
  831.       c = find_entry(copy);
  832.       if(!c && code==SCOLUMN)
  833.         c = add_info_l(copy);
  834.       if (c)      /* has already copyed to new segment */
  835.         {
  836.           if(c!=copy)
  837.             free_node(copy);
  838.           return c;
  839.         }
  840.     }
  841.   if (TstF_TRN (orig, MARK_F))
  842.     {
  843.       yyerror("attempt to copy cycled tree");
  844.       ClrF_TRN (orig, MARK_F);
  845.       debug_trn (orig);
  846.       SetF_TRN (orig, MARK_F);
  847.       return TNULL;
  848.     }
  849.   if (Is_Statement (orig))
  850.     {
  851.       PUSHS (copy_trn_st, LOCAL_VCB_ROOT);
  852.       LOCAL_VCB_ROOT = TNULL;
  853.     }
  854.   if (!copy)
  855.     COPY_NODE (code, orig, copy);
  856.   if (TstF_TRN (orig, VCB_F) && Is_Table(copy))
  857.     {
  858.       TXTREF tmp_trn = copy;
  859.       if(TstF_TRN(orig,CHECKED_F))
  860.         ClrF_TRN(copy,CHECKED_F);
  861.       CHECK_VCB;
  862.     }
  863.   SetF_TRN (orig, MARK_F);
  864.   {
  865.     register char *fmt;
  866.     register i4_t i;
  867.     fmt = FORMAT (code);
  868.     for (i = 0; *fmt; fmt++, i++)
  869.       switch (*fmt)
  870.         {
  871.         case 's':
  872.         case 'S':
  873.   XLTR_TRN(copy,i) = ((XLTR_TRN(orig,i)  != 0) ?
  874.       ltr_rec(STRING(XLTR_TRN(orig,i))) : 
  875.       TNULL);
  876.           break;
  877.         case 'N':
  878.           {
  879.             TXTREF v,v1;
  880.             
  881.             v=XTXT_TRN (orig, i);
  882.             v1 = XTXT_TRN (copy, i) = copy_trn (v);
  883.             while(v && RIGHT_TRN(v))
  884.               {
  885.                 v = RIGHT_TRN(v);
  886.                 RIGHT_TRN(v1) = copy_trn(v);
  887.                 v1 = RIGHT_TRN(v1);
  888.               }
  889.           }
  890.           break;
  891.         case 't':
  892.         case 'v':
  893.         case 'P':
  894.           XTXT_TRN (copy, i) = copy_trn (XTXT_TRN (orig, i));
  895.           break;
  896.         case 'V':
  897.           XTXT_TRN (copy, i) = TNULL;
  898.           break;
  899.         case 'r':
  900.           RIGHT_TRN (copy) = TNULL;
  901.           break;
  902.         case 'd':
  903.           DOWN_TRN (copy) = TNULL;
  904.           break;
  905.         case 'a':
  906.           ARITY_TRN (copy) = 0;
  907.           break;
  908.         case 'L':
  909.         case 'T':
  910.           {
  911.             register TXTREF vec, vec1;
  912.             register i4_t j;
  913.             vec = XTXT_TRN (orig, i);
  914.             j = VLEN (vec);
  915.             XTXT_TRN (copy, i) = vec1 = gen_vect (j);
  916.             while (j--)
  917.               if (*fmt == 'T')
  918.                 VOP (vec1, j).txtp = copy_trn (VOP (vec, j).txtp);
  919.               else
  920.                 VOP (vec1, j) = VOP (vec, j);
  921.             break;
  922.           }
  923.         default:
  924.           break;
  925.         }
  926.   }
  927.   /* Vocabulary check */
  928.   if (TstF_TRN (copy, VCB_F))
  929.     {
  930.       TXTREF tmp_trn = copy;
  931.       switch (code)
  932.         {
  933.         case COLUMN:
  934.           break;
  935.         case SCOLUMN:           /* link all backward reference */
  936.         case PARAMETER:
  937.         case CURSOR:
  938.         case SCAN:
  939.           CHECK_VCB;
  940.           break;
  941.         default:
  942.           if (Is_Table (copy))
  943.             {
  944.       if(TstF_TRN(orig,CHECKED_F))
  945. SetF_TRN(copy,CHECKED_F);
  946.             }                   /* Is_Table */
  947.         }
  948.     }
  949. #undef CHECK_VCB
  950.   ClrF_TRN (orig, MARK_F);
  951.   if (!copy)
  952.     {
  953.       debug_trn (orig);
  954.       yyfatal("Panic: null copy of subtree (see above) produced");
  955.     }
  956.   if (Is_Statement (copy))
  957.     {
  958.       STMT_VCB (copy) = LOCAL_VCB_ROOT;
  959.       POPS (copy_trn_st, LOCAL_VCB_ROOT);
  960.     }
  961.   return copy;
  962. }
  963. /* 
  964.  * Return 1 if X and Y are identical-looking trn's. This is the Lisp function
  965.  * EQUAL for TXTREF arguments.  
  966.  */
  967. int
  968. trn_equal_p (TXTREF x, TXTREF y)
  969. {
  970.   register i4_t i;
  971.   register enum token code;
  972.   register char *fmt;
  973.   register TXTREF parmx, parmy;
  974.   if (x == y)
  975.     return 1;
  976.   if (x == 0 || y == 0)
  977.     return 0;
  978.   code = CODE_TRN (x);
  979.  /* call itself and swap parameters to avoid NOOPs */
  980.   if (code == NOOP)
  981.     return trn_equal_p (y,DOWN_TRN(x));
  982.   /* Trn's of different codes cannot be equal.  */
  983.   if (code != CODE_TRN (y))
  984.     return 0;
  985.   {
  986.     MASKTYPE msk, msk1, msk2;
  987.     msk1 = 0;
  988.     SetF (msk1, PATTERN_F);
  989.     msk1 = 2 * msk1 - 1;
  990.     msk = MASK_TRN (x);
  991.     msk CLRVL msk1;             /* clear all bits less than PATTERN_F */
  992.     ClrF (msk, MARK_F);
  993.     msk2 = MASK_TRN (y);
  994.     msk2 CLRVL msk1;            /* clear all bits less than PATTERN_F */
  995.     ClrF (msk2, MARK_F);
  996.     if (msk != msk2)
  997.       return 0;
  998.   }
  999.   /* Compare the elements.  If any pair of corresponding elements fail to
  1000.      match, return 0 for the whole things.  */
  1001.   fmt = FORMAT (code);
  1002.   for (i = LENGTH (code) - 1; i >= 0; i--)
  1003.     {
  1004.       switch (fmt[i])
  1005.         {
  1006.         case 'i':
  1007.         case 'f':
  1008.         case 'l':
  1009.         case 'a':               /* because they must has equal number of params*/
  1010.           if (XLNG_TRN (x, i) != XLNG_TRN (y, i))
  1011.             return 0;
  1012.           break;
  1013.   
  1014.         case 's':               /* because identical literals save just once   */
  1015.           if (XLNG_TRN (x, i) == XLNG_TRN (y, i))
  1016.     break;
  1017.           if (strcmp(STRING(XLTR_TRN (x, i)),STRING(XLTR_TRN (y, i))))
  1018.             return 0;
  1019.   break;
  1020.         case 't':
  1021.         case 'v':
  1022.         case 'P':
  1023.           if (trn_equal_p (XTXT_TRN (x, i), XTXT_TRN (y, i)) == 0)
  1024.             return 0;
  1025.           break;
  1026.         case 'V':
  1027.         case 'p':
  1028.         case '0':
  1029.         case 'd':
  1030.         case 'r':
  1031. case 'x':
  1032.         case 'R':
  1033.   break;
  1034.   
  1035.         case 'y':
  1036.   if (XLNG_TRN (x, i) != XLNG_TRN(y, i))
  1037.     return 0;
  1038.   break;
  1039.       
  1040.         case 'L':
  1041.   {
  1042.     TXTREF patvect=XVEC_TRN(x,i);
  1043.     TXTREF invect=XVEC_TRN(y,i);
  1044.     i4_t j=VLEN(patvect);
  1045.     if(j!=VLEN(invect))
  1046.       return 0;
  1047.     for(;j;j--)
  1048.       if(VOP(patvect,j).l != VOP(invect,j).l)
  1049. return 0;
  1050.   }
  1051.     break;
  1052.         case 'T':               /* array of longs and TXTREF's */
  1053.    { 
  1054.     TXTREF patvect=XVEC_TRN(x,i);
  1055.     TXTREF invect=XVEC_TRN(y,i);
  1056.     i4_t j=VLEN(patvect);
  1057.     if(j!=VLEN(invect))
  1058.       return 0;
  1059.     for(;j;j--)
  1060.       if(VOP(patvect,j).txtp != VOP(invect,j).txtp)
  1061. return 0;
  1062.   }
  1063.           break;
  1064.         default:
  1065.           yyfatal ("TRL.trn_equal_p: unexpected format character");
  1066.         }
  1067.     }
  1068.   /* param's check */
  1069.   if (HAS_DOWN (x))
  1070.     for (
  1071.       i = ARITY_TRN (x),
  1072. parmx = DOWN_TRN (x),
  1073. parmy = DOWN_TRN (y);
  1074.       i && parmx && parmy;
  1075.       i--,
  1076. parmx = RIGHT_TRN (parmx),
  1077. parmy = RIGHT_TRN (parmy)
  1078.       )
  1079.       if (trn_equal_p (parmx, parmy) == 0)
  1080.         return 0;
  1081.   return 1;
  1082. }
  1083. /*******==================================================*******
  1084. *******            Compiler limit functions                *******
  1085. *******==================================================*******/
  1086. int
  1087. trl_wrn (char *msg, char *file, i4_t line, trn ptr)
  1088. {
  1089.   fprintf (STDERR, "nn%s:%d: %s nn", file, line, msg);
  1090.   debug_trn_d (ptr);
  1091.   return 0;
  1092. }
  1093. int
  1094. trl_err (char *msg, char *file, i4_t line, trn ptr)
  1095. {
  1096.   trl_wrn (msg, file, line, ptr);
  1097.   yyfatal ("Abort");            /* ==> Exit */
  1098.   /* Unreachable */
  1099.   assert(0);
  1100.   return 0;
  1101. }
  1102. int
  1103. fmt_eq (char *fmt, char *tst)
  1104. {
  1105.   register char *f = fmt, *t = tst;
  1106.   while (*t)
  1107.     if (*(f++) != *(t++))
  1108.       return 0;
  1109.   return 1;
  1110. }
  1111. #ifdef CHECK_TRL
  1112. trn
  1113. test_exist (trn node, i4_t n, char *_FILE__, i4_t _LINE__)
  1114. {
  1115.   register i4_t l;
  1116.   enum token code = CODe_TRN1 (node);
  1117.   l = LENGTH (code);
  1118.   if (Tstf_TRN (node, PATTERN_F))
  1119.     l += PTRN_ELEM (code);
  1120.   if (Tstf_TRN (node, ACTION_F))
  1121.     l += PTRN_ELEM (code);
  1122.   if (n < l)
  1123.     return node;
  1124.   trl_err ("TRL: number of operand is too much in ", _FILE__, _LINE__, node);
  1125.   /* unreachable code */
  1126.   return 0;
  1127. }
  1128. trn
  1129. test_node (trn node, char *f, i4_t l)
  1130. {
  1131.   register enum token code;
  1132.   if (node == NULL)
  1133.     trl_err ("TRL: null tree reference ", f, l, NULL);
  1134.   code = node->code;
  1135.   if (code <= UNKNOWN || code >= LAST_TOKEN)
  1136.     trl_err ("TRL: unexpected tree code ", f, l, NULL);
  1137.   return node;
  1138. }
  1139. int
  1140. tstv_exist (trvec vec, i4_t n, char *_FILE__, i4_t _LINE__)
  1141. {
  1142.   if (n < VLEn1 (vec))
  1143.     return n;
  1144.   fprintf (STDERR,
  1145.         "nnInternal error: %s:%d: number of vector element is too muchn",
  1146.            _FILE__, _LINE__);
  1147.   yyfatal ("Abort");            /* ==> Exit */
  1148.   /* Unreached */
  1149.   return 0;
  1150. }
  1151. trvec
  1152. tstv_vec (trvec vec, char *f, i4_t l)
  1153. {
  1154.   if (vec)
  1155.     return vec;
  1156.   trl_err ("TRL: null vector reference ", f, l, NULL);
  1157.   /* unreachable code */
  1158.   return NULL;
  1159. }
  1160. tr_union *
  1161. xOp_parm (trn node, i4_t n, char c, char *_FILE__, i4_t _LINE__)
  1162. {
  1163.   register char *fmt = FORMAT (CODe_TRN1 (node));
  1164.   register i4_t nn = n;
  1165.   if (fmt[nn] != c)
  1166.     {
  1167.       for (nn = 0; fmt[nn]; nn++)
  1168.         if (fmt[nn] == c)
  1169.           break;
  1170.       if (fmt[nn] == 0)
  1171.         trl_err ("TRL: incorrect format request in ", _FILE__, _LINE__, node); /* ==>exit */
  1172.     }
  1173.   return &(node->operands[nn]);
  1174. }
  1175. tr_union *
  1176. xOp_parms (trn node, i4_t n, char *s, char *_FILE__, i4_t _LINE__)
  1177. {
  1178.   if (fmt_eq (FORMAT (CODe_TRN1 (node)) + n, s))
  1179.     return &(node->operands[n]);
  1180.   trl_err ("TRL: incorrect struct format request in ", _FILE__, _LINE__, node);
  1181.   return NULL;
  1182. }
  1183. #endif