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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  kitty.c -  tree recognizer and modification procedure generator
  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 Andrew Yahin.
  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: kitty.c,v 1.246 1997/03/31 11:03:47 kml Exp $ */
  28. #include <assert.h>
  29. #include "kitty.h"
  30. #include "cycler.h"
  31. #define TEST_VAR(s)      STRING(XLTR_TRN(s,0))
  32. #define BUFFER_VAR(s)     STRING(XLTR_TRN(s,3))
  33. #define  RULENAME(fl,str,r) 
  34.   fprintf(fl,"n%sTXTREFnrule_%s(i4_t *done,TXTREF in_tree)",str,RULE_NAME(r))
  35. FILE *yout = NULL, *yhout = NULL;
  36. static i4_t   line_no = 0;
  37. static FILE *y1out; /* stream to emit out rule_1 functions */
  38. static int
  39. skip_c_code(FILE *infile)
  40. {
  41.   register i4_t c;
  42.   if(yout)
  43.     fprintf(yout,"n#line %d "%s.k"n", line_no+1,progname);
  44.   while ((c = getc (infile)) != EOF)
  45.     {
  46.       if (c == '/')
  47. {
  48.   register i4_t prevc;
  49.   
  50.   putc(c,yout);
  51.   c = getc (infile);
  52.   if (c=='*') /* comment begins */
  53.     {
  54.       putc(c,yout);
  55.               prevc = 0;
  56.       while ((c = getc (infile)) != EOF)
  57. {
  58.   if ( c=='/' && prevc=='*')
  59.     break;
  60.   if (c=='n')
  61.     line_no ++;
  62.   putc(c,yout);
  63.   prevc = c;
  64. }
  65.     }
  66. }
  67.       if (c == '#')
  68.         {
  69.           c = getc (infile);
  70.           ungetc(c,infile);
  71.           if ( c == '(')
  72.             return c;
  73.           c = '#';
  74.         }
  75.       if (c == 'n')
  76.         {
  77. #define BUF_SIZE 1024
  78.           char buffer[BUF_SIZE], *buf_ptr=buffer;
  79.           i4_t  passed_d = 0;
  80.           
  81.           line_no ++;
  82.           putc(c,yout);
  83.           while ((*buf_ptr++ = c = getc (infile)) != EOF)
  84.             {
  85.               if (buf_ptr - buffer >=BUF_SIZE/2)
  86.                 break;
  87.               if (c == '#' && !passed_d)
  88.                 passed_d = 1;
  89.               else if ( c == '(' && passed_d)
  90.                 {
  91.                   ungetc(c,infile);
  92.                   return c;
  93.                 }
  94.               else if ( c != 't' && c != ' ')
  95.                 break;
  96.             }
  97.           *(--buf_ptr)=0;
  98.           fputs(buffer,yout);
  99. #undef BUF_SIZE
  100.           ungetc(c,infile);
  101.           continue;
  102.         }
  103.       if (c == EOF)
  104. return c;
  105.       putc(c,yout);
  106.     }
  107.   return EOF;
  108. }
  109. static TXTREF
  110. get_next_tree(i4_t is_preprocessor, FILE *infile)
  111. {
  112.   if (is_preprocessor)
  113.       if(skip_c_code(infile)==EOF)
  114. return TNULL;
  115.   if(LOCAL_VCB_ROOT)
  116.     free_line(LOCAL_VCB_ROOT);
  117.   LOCAL_VCB_ROOT = TNULL;
  118.   return read_trn(infile,&line_no,FLAG_VALUE(ACTION_F));
  119. }
  120. static TXTREF
  121. cook_switch_list(TXTREF n, i4_t f)
  122. {
  123.   typedef struct s1 
  124.   {
  125.     LTRLREF    sel; 
  126.     struct s1 *next;
  127.   } check_list_t;
  128.   static check_list_t  *switch_list;
  129.   
  130.   register check_list_t *cp;
  131.   register LTRLREF v ; 
  132.   
  133.   if ( f==0)  /* init loop */
  134.     {
  135.       switch_list = NULL;
  136.       cycler (n, cook_switch_list, CYCLER_LD); /* go walk */
  137.       while(switch_list)
  138. {
  139.   cp = switch_list;
  140.   switch_list = switch_list->next;
  141.   xfree(cp);
  142. }
  143.     }
  144.   else if ( f==CYCLER_LD )  /* inside cycler loop */
  145.     {
  146.       if (CODE_TRN (n) != OPERAND)
  147. return n;
  148.       
  149.       v = XLTR_TRN (n, 0);
  150.       if (!v)
  151. return n;
  152.       
  153.       for (cp = switch_list; cp; cp = cp->next)
  154. if (cp->sel == v)
  155.   return n; /* everything has already done */
  156.       fprintf (y1out, "    case %d : return %s(node);n",
  157.        (i4_t) v, STRING (v));
  158.       /* add new node in list */
  159.       cp=(check_list_t *) xmalloc (sizeof (check_list_t));
  160.       cp->next = switch_list;
  161.       cp->sel = v;
  162.       switch_list = cp;
  163.     }
  164.   else
  165.     yyfatal("'switch_list_cook' MUST NOT be here");
  166.   return n;
  167. }
  168. static void 
  169. make_rule_1 (TXTREF pattern,char *title)
  170. /* this routine generate function rule_Rname_1 as a alias for
  171.    Op:n "test_function_or_macro_name"). Actually this function
  172.    must look like :
  173.    static int
  174.    rule_rname_1(TXTREF node,i4_t sel)
  175.    {
  176.      switch(sel){
  177.      case 1:  return test_function_name1(node);
  178.      case 34: return test_function_name2(node);
  179.      }
  180.      -- default:
  181.      fprintf(stderr,"horrible internal fatal error");
  182.      return 0;
  183.    }
  184.  */
  185. {
  186.   assert(y1out!=NULL);
  187.   fprintf (y1out, 
  188.    "n"
  189.    "static intn"
  190.    "rule_%s_1(TXTREF node,i4_t sel)n"
  191.    "{n"                  
  192.            "  switch(sel){n"
  193.            ,title);
  194.   cook_switch_list(pattern,0);
  195.   fprintf (y1out,
  196.    "  }n"
  197.    "  fprintf(stderr,n"
  198.    "          "
  199. ""Internal error: unexpected selector value %%x in rule '%%s'",n"
  200.    "          sel,"%s");n"
  201.            "  return 0;n"
  202.            "}n"
  203.            , title);
  204. }
  205. static TXTREF
  206. emit_lcc(TXTREF n,i4_t f)
  207. {
  208.   static i4_t need_lcc;
  209.   if(f==0)
  210.     {
  211.       need_lcc = 0;
  212.       cycler(n,emit_lcc,CYCLER_LD);
  213.       if (need_lcc)
  214. fputs("  i4_t kitty_lcc;n"
  215.               , yout);
  216.     }
  217.   else if (f==CYCLER_LD)
  218.     {
  219.       switch(CODE_TRN(n))
  220. {
  221. case TRLcmd_SWITCH:
  222.   cycler_skip_subtree = 1;
  223.   break;
  224. case RUN_RULE:
  225.   need_lcc = 1 ;
  226. default:
  227.           break;
  228. }
  229.       if(need_lcc)
  230. cycler_skip_subtree = 1;
  231.     }
  232.   else
  233.     yyfatal("Emit_lcc should not be here");
  234.   return n;
  235. }
  236. static TXTREF
  237. emit_rule1(TXTREF n,i4_t f)
  238. {
  239.   static i4_t need_rule1;
  240.   if(f==0)
  241.     {
  242.       need_rule1 = 0;
  243.       cycler(RULE_PATTERN (n),emit_rule1,CYCLER_LD);
  244.       return need_rule1;
  245.     }
  246.   else if (f==CYCLER_LD)
  247.     {
  248.       switch(CODE_TRN(n))
  249. {
  250. case OPERAND:
  251.           if (XLTR_TRN(n,0))
  252.             need_rule1 = 1;
  253.   break;
  254. default:
  255.           break;
  256. }
  257.       if(need_rule1)
  258. cycler_skip_subtree = 1;
  259.     }
  260.   else
  261.     yyfatal("Emit_rule1 should not be here");
  262.   return n;
  263. }
  264. static void
  265. make_rule (TXTREF r)
  266. {
  267.   char *str;
  268.   char rule1_name[100];
  269.   TXTREF action;
  270.   if ( emit_rule1(r,0) )
  271.     {
  272.       make_rule_1(RULE_PATTERN (r), RULE_NAME(r));
  273.       sprintf(rule1_name,"rule_%s_1",RULE_NAME(r));
  274.     }
  275.   else
  276.     strcpy(rule1_name,"NULL");
  277.   
  278.   RULENAME (yout, "", r);
  279.   
  280.   fputs ( "n{n"
  281.   "  static TXTREF pat=TNULL;n"
  282.   "  TXTREF Op[15],Rop=in_tree;n"
  283.   ,yout);
  284.   emit_lcc(r, 0);
  285.   fputs(  "  n"
  286.   "  if(!pat){n"
  287.   "    pat=n"
  288.   "       ", yout);
  289.   
  290.   emit_trn_constructor (RULE_PATTERN (r), 0); /* emit pattern tree */
  291.   fprintf (yout, ";n"                        
  292.    "    register_pattern(&pat);n"
  293.    "  }n"
  294.    "  if (!t_compare(pat,in_tree,Op,%s))n" /* check pattern */
  295.    "     FAIL;n",rule1_name);
  296.   str = STRING (RULE_STR (r));
  297.   if (RULE_STR (r))
  298.     fprintf (yout, "  if(!(%s))FAIL;n", str);  /* additional check */
  299.   /* ACTIONS */
  300.   for (action = DOWN_TRN (r); action; action = RIGHT_TRN (action))
  301.     {
  302.       TXTREF t = action;
  303.       i4_t n = OPs_IND (t);
  304.       switch (CODE_TRN (t))
  305. {
  306. case TRLcmd_CCODE:
  307. case TRLcmd_REMOVE:
  308.   if (n >= 0)
  309.     yyerror ("Unexpected return specification in ccode or Remove node");
  310.   break;
  311. default:
  312.   if ((OPs_IND (t) < 0) || (CODE_TRN (t) == OPERAND))
  313.     fprintf (yout, "ntRop=");
  314.   break;
  315. }
  316.       emit_trn_constructor (t, 0);
  317.       if (CODE_TRN (t) != TRLcmd_CCODE)
  318. fputs (";n", yout);
  319.     }
  320.   fputs (
  321.   "n"
  322.   "  goto SUCCESS_EXIT;n"
  323.   " FATAL_EXIT:n"
  324.   "  *done=0;n"
  325.   "  return in_tree;n"
  326.   " SUCCESS_EXIT:n"
  327.   "  *done=1;n"
  328.   "  return Rop;n"
  329.   "}n", yout);
  330.   fprintf (yout, "/* end of %s */n", RULE_NAME (r));
  331. }
  332. i4_t 
  333. main (i4_t argc, char **argv)
  334. {
  335.   TXTREF r;
  336.   char  *result = NULL;
  337.   char   wf_name[100];
  338.   FILE  *infile=NULL;
  339.   i4_t    preprocessor_mode = 0;
  340.   
  341. #if 0
  342.   extern i4_t debug_vmemory;
  343.   
  344.   debug_vmemory = 1; 
  345. #endif
  346.   
  347.   yout = yhout = stdout;
  348.   
  349.   if (argc < 2)
  350.     yyfatal("Usage: kitty pattern_file_name");
  351.   
  352.   if ((infile = fopen (argv[1], "r")) == NULL)
  353.     {
  354.       fprintf (STDERR, "Can't open '%s'n", argv[1]);
  355.       exit (FATAL_EXIT_CODE);
  356.     }
  357.   
  358.   result = argv[1] + strlen (argv[1]);
  359.   while ((result > argv[1]) && (*result != '.') && (*result != '/'))
  360.     result--;
  361.   preprocessor_mode = strcmp(result,".k")==0;
  362.   if (*result == '.')
  363.     *result = 0;
  364.   while ((result > argv[1]) && (*result != '/'))
  365.     result--;
  366.   if (*result == '/')
  367.     result++;
  368.   strcpy (wf_name, result);
  369.   strcat (wf_name, ".c");
  370.   if ((yout = fopen (wf_name, "w")) == NULL)
  371.     yyfatal ("Can't open output file");
  372.   strcpy (wf_name, result);
  373.   strcat (wf_name, ".h");
  374.   if ((yhout = fopen (wf_name, "w")) == NULL)
  375.     yyfatal ("Can't open output file");
  376.   y1out = preprocessor_mode? yhout : yout;
  377.  
  378.   progname = result;
  379.   fprintf (yout,
  380.    "/* n"
  381.            " *  %s.c - generated by kitty n"
  382.            " *  n"
  383.    " *  DON'T EDIT THIS FILE      n"
  384.    " */n"
  385.            "n"
  386.    "#define  __%s_C__n"
  387.    "#include  "%s.h"n"
  388.    "#undef   __%s_C__n"
  389.            "n"
  390.    "#define FAIL    goto FATAL_EXIT n"
  391.    "#define RETURN  goto SUCCESS_EXIT n"
  392.    "#define RET(v)  { Rop=v;RETURN;} n"
  393.            "n",
  394.    result, result,result,result);
  395.   fprintf (yhout,
  396.    "/*n"
  397.            " *  %s.h - generated by kitty n"
  398.    " *  DON'T EDIT THIS FILE n"
  399.    " */n"
  400.            "n"
  401.    "#ifndef __%s_H__n"
  402.    "#define __%s_H__n"
  403.    "#include "kitty.h"n"
  404.    ,result,result,result);
  405.   while ((r = get_next_tree(preprocessor_mode,infile)) != TNULL)
  406.     {
  407.       switch (CODE_TRN (r))
  408. {
  409. case RULE:
  410.   {
  411.     i4_t static_rule = TstF_TRN (r, STATIC_F);
  412.     
  413.     if (static_rule)
  414.       fprintf(yhout,"n#ifdef __%s_C__n",result);
  415.     RULENAME (yhout, static_rule? "static ":"", r);
  416.     fputs (";n", yhout);
  417.     if (static_rule)
  418.       fputs("#endifn",yhout);
  419.   }
  420.   
  421.   fprintf (yout, "/* ---------- Rule '%s' ------------ */n",
  422.    RULE_NAME (r));
  423.   y1out = yout;
  424.   make_rule (r);
  425.   break;
  426.   
  427. case TRLcmd_CCODE:
  428.   fputs (STRING (XLTR_TRN (r, 0)), yout);
  429.   break;
  430.           
  431. case IF:
  432.   {
  433.     static i4_t uid = 0;
  434.     char       nm[100],rule1_nm[100];
  435.     sprintf(nm,"%s_if_%d",result,uid++);
  436.             
  437.     y1out = yhout;
  438.             if (emit_rule1(RULE_PATTERN(r),0))
  439.               {
  440.                 fprintf (yhout,"#ifdef __%s_C__n",result);
  441.                 make_rule_1(RULE_PATTERN(r),nm);
  442.                 fprintf (yhout,"#endifn");
  443.                 sprintf(rule1_nm,"rule_%s_1,",nm);
  444.               }
  445.             else
  446.               strcpy(rule1_nm,"NULL");
  447.             
  448.     fprintf ( yout, "  if (!t_compare(ANONYM_P("%s",",nm);
  449.     emit_trn_constructor(RULE_PATTERN(r),0);
  450.     fprintf ( yout, "),%s,%s,%s);n"
  451.       "          break;n",
  452.       TEST_VAR(r),BUFFER_VAR(r),rule1_nm);
  453.     break;
  454.   }
  455.           
  456. default:
  457.   if(preprocessor_mode)
  458.     emit_trn_constructor(r,0);
  459.   else
  460.     fprintf (stderr,
  461.      "Unexpected statement node '%s' in rule program '%s'n",
  462.      NAME (CODE_TRN (r)), result);
  463. }
  464.       
  465.       free_tree(r);
  466.       if(LOCAL_VCB_ROOT)
  467. free_line(LOCAL_VCB_ROOT);
  468.       LOCAL_VCB_ROOT = TNULL;
  469.     }
  470.   
  471.   fprintf (yhout, 
  472.    "nn"
  473.    "#endif /*  __%s_H__ */n"
  474.    ,result);
  475.   fclose(infile);
  476.   fclose (yout);
  477.   fclose (yhout);
  478.   finish (NULL);
  479.   return (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
  480. }