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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  sc.c  -  Generation C ANSI-style routines with interpretator calls
  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.  *  Contact: gss@ispras.ru
  25.  *
  26.  */
  27. /* $Id: sc.c,v 1.248 1997/04/21 17:45:31 kml Exp $ */
  28. #include "setup_os.h"
  29. #include "global.h"
  30. #include "type_lib.h"
  31. #include <assert.h>
  32. #include "tassert.h"
  33. static FILE *ofile = NULL;
  34. static char *
  35. get_c_type (i4_t t)
  36. {
  37.   static char *c_type_names[] = {
  38. #define DEF_SQLTYPE(CODE,SQLTN,CTN,DYN_ID) CTN,
  39. #include "sql_type.def"
  40.     NULL
  41.   };
  42.   assert(t > 0 && t < sizeof(c_type_names)/sizeof(char*));
  43.   return c_type_names[t];
  44. }
  45. static void
  46. sc_prolog (char *modname,char *ext,char *host)
  47. {
  48.   fprintf (ofile,
  49.            "/*n"
  50.            " * %s.%s - SQL statement client stubsn"
  51.    " *n"
  52.            " *       Generated by GNU SQL compiler n"
  53.            " *       DON'T EDIT THIS FILE       n"
  54.            " */n"
  55.            "n"
  56.            "#include <sql.h>n"
  57.            "n"
  58.    "static struct module mdl = n"
  59.            "t{"%s",0,0,"%s"};n"
  60.            "n"
  61.            "n",
  62.    sql_prg,ext,
  63.            host,modname);
  64. }/*-----------------------------------------------------------------------*/
  65. static char *
  66. subst_name(i4_t object,i4_t method)
  67. {
  68.   static char buf[1024];
  69.   switch(object) {
  70.   case -2:     sprintf(buf,"_SQL_commit"); break;
  71.   case -1:     sprintf(buf,"_SQL_rollback"); break;
  72.   default:
  73.     sprintf(buf,"SQL__local_o%d_m%d",object,method);
  74.   }
  75.   return buf;
  76. }
  77. static char *
  78. parm_name(i4_t proto,char *par_name,i4_t id)
  79. {
  80.   static char buf[1024];
  81.   
  82.   assert (proto || *par_name);
  83.   
  84.   if (!proto)
  85.     return par_name;
  86.   sprintf(buf,"%s_%d",(*par_name?par_name:"SQL_par"),id);
  87.   return buf;
  88. }
  89. /*
  90.  * creating textual parameters list for given parameter disriptors.
  91.  *  Examples are given for the following case:
  92.  *    SMALLINT a; input parameter   
  93.  *    char b(...) INDICATOR c;  output parameter  
  94.  *    REAL d;     input parameter  
  95.  * list_style: 
  96.  *  MOD_PROTO(0)  -  ANSI prototype for module procedure 
  97.  *    (i2_t a, char *b, i4_t *c, float d)
  98.  *  EMB_PROTO(1)  -  extended prototype with sizeof's and indicators 
  99.  *                   for replacement procedure.
  100.  *    (i2_t a, char *b, i4_t sizeof_b, i4_t *c, float d)
  101.  *  EMB_CALL(2)   -  substitution actual params to call routine defined in
  102.  *                   EMB_PROTO style. if we omitted indicator of parameter
  103.  *                   any in call it replaced by 0(in) or NULL(out).
  104.  *    (a,0,b,sizeof(b),&c,d,0)
  105.  *
  106.  */
  107. typedef enum
  108. {
  109.   MOD_PROTO,
  110.   EMB_PROTO,
  111.   EMB_CALL,
  112. } parm_style_t;
  113. static char *
  114. get_param_list (descr_t *in, descr_t *out, parm_style_t list_style)
  115. {
  116.   register i4_t    cont,i;
  117.   static   char   bf[1024];
  118.   i4_t      count = in->descr_t_len + (out?out->descr_t_len:0); 
  119.   
  120.   assert(out || list_style==MOD_PROTO);
  121.   strcpy (bf, "(");
  122.   
  123. #define SP  sprintf
  124. #define BF  bf + strlen(bf)
  125.   for ( cont = i = 0 ;  i < count; i++)
  126.     {
  127.       prep_elem_t *ce;
  128.       i4_t          out_parm = 1;
  129.       assert ( i < in->descr_t_len || out); 
  130.       if ( i < in->descr_t_len )
  131.         {
  132.           ce = & (in->descr_t_val[i]);
  133.           if (!(list_style==MOD_PROTO && ce->nullable==-1))
  134.             out_parm = 0;
  135.         }
  136.       else /* if (out) */
  137.         ce = & (out->descr_t_val[i - in->descr_t_len]);
  138.         
  139.       if (cont)  strcat (bf, ",");
  140.       else       cont = 1;
  141.       if (list_style == MOD_PROTO || list_style == EMB_PROTO )
  142.         { /* if we generate prototype --> product type */
  143.           SP(BF,"%s ",get_c_type (ce->type));
  144.           if (out_parm && ce->type != SQLType_Char)
  145.             strcat (bf, "*");
  146.         }
  147.       else if (out_parm && ce->type != SQLType_Char)
  148.         strcat (bf, "&"); /* if we generate real call --> special processing */
  149.       /*                     for output parameters                           */
  150.       strcat (bf, parm_name (list_style!=EMB_CALL, ce->name,i));
  151.       if (list_style == EMB_PROTO)
  152.         {
  153.           if (out_parm && ce->type == SQLType_Char)
  154.             SP(BF,",i4_t sizeof_%s",
  155.                parm_name (list_style!=EMB_CALL, ce->name,i));
  156.           SP(BF,", i4_t %sind_of_%s",(out_parm?"*":""),
  157.              parm_name (list_style!=EMB_CALL, ce->name,i));
  158.         }
  159.       else if (list_style == EMB_CALL)
  160.         {
  161.           if (out_parm && ce->type == SQLType_Char)
  162.             SP(BF,",sizeof(%s)", parm_name (list_style!=EMB_CALL, ce->name,i));
  163.           strcat(bf,",");
  164.           if(!*ce->ind_name)
  165.             strcat(bf,(out_parm?"NULL":"0"));
  166.           else
  167.             {
  168.               if (out_parm)
  169.                 strcat(bf,"&");
  170.               strcat(bf,ce->ind_name);
  171.             }
  172.         }
  173.     }
  174.   if (!cont && (list_style == MOD_PROTO || list_style == EMB_PROTO ))
  175.     strcat (bf, "void");
  176.   strcat (bf, ")");
  177. #undef SP
  178. #undef BF
  179.   return bf;
  180. }
  181. /* 
  182.  * replace original call by call of stub correctly prototyped
  183.  * ANSI C function
  184.  * out_name -> &name and 
  185.  * out "string_name" -> "string_name, sizeof(string_name)"
  186.  */
  187. void
  188. subst_call(call_subst_t *subst, i4_t is_macro)
  189. {
  190. #define Nl      (is_macro?"\nt":"nt")
  191. #define NL(f,a,b) fprintf(ofile,"%s" f,Nl,a,b)
  192.   
  193.   NL("%s %s ;",
  194.      subst_name(subst->object,subst->method),
  195.      get_param_list(&(subst->in_sql_parm),&(subst->out_sql_parm),EMB_CALL));
  196.   {
  197.     i4_t i;
  198.     for (i = 0; i < subst->out_sql_parm.descr_t_len; i++ )
  199.       if (strstr (subst->out_sql_parm.descr_t_val[i].name, "SQLCODE") )
  200.         {
  201.           NL ("*%s = SQLCODE; /*%s*/",
  202.               subst->out_sql_parm.descr_t_val[i].name,
  203.               " ---- error codde -----> ");
  204.           break;
  205.         }
  206.   }
  207.   if (*subst->jmp_on_error)
  208.     NL("if (SQLCODE <  0  ) goto %s ;%s",subst->jmp_on_error,"");
  209.   if (*subst->jmp_on_eofscan)
  210.     NL("if (SQLCODE == 100) goto %s ;%s",subst->jmp_on_eofscan,"");
  211.   fprintf(ofile,"nn");
  212.   
  213. #undef Nl
  214. #undef NL
  215. }
  216. /*
  217.  * Generate stub to call particular object of module with explicit
  218.  * typed parameter list to give C compiler a chance to detect
  219.  * SQL call parameters type mismatch problems.
  220.  */
  221. static void 
  222. print_routine (descr_t in, descr_t out, i4_t object, i4_t method,i4_t options)
  223. {
  224.   int          pcount;
  225.   int          i;
  226.   
  227. #define Nl        fputs ("nt",ofile)
  228. #define L1(f,a)   fprintf (ofile,f,a)
  229. #define L2(f,a,b) fprintf (ofile,f,a,b)
  230. #define NL(s)     { Nl; fputs (s,ofile); }
  231. #define N1(f,a)   { Nl; L1(f,a); }
  232. #define N2(f,a,b) { Nl; L2(f,a,b); }
  233. #define A_       (out_parm || ce->type==SQLType_Char ?' ':'&')
  234. #define A_i      (out_parm                           ?' ':'&')
  235.   
  236.   L2("n"
  237.      "static voidn"
  238.      "%s %sn"
  239.      "{",
  240.      subst_name(object,method),
  241.      get_param_list (&in,&out, EMB_PROTO));
  242.   pcount = in.descr_t_len + out.descr_t_len; 
  243.   NL("gsql_parms ldata;");
  244.   if (pcount)
  245.     {
  246.       N1("gsql_parm  p[%d], *e;",pcount);
  247.       Nl;
  248.       NL("ldata.prm     = p;");
  249.       N1("ldata.count   = %d;",pcount);
  250.       N1("ldata.options = %d;",options);
  251.     }
  252.   else
  253.     {
  254.       NL("ldata.count   = 0;");
  255.       NL("ldata.options = 0;");
  256.       NL("ldata.prm     = NULL;");
  257.     }
  258.   N1("ldata.sectnum = %d;",object);
  259.   N1("ldata.command = %d;",method);
  260.   /* filling parameters fields */
  261.   for(i=0;i<pcount;i++)
  262.     {
  263.       int          out_parm = 0;
  264.       prep_elem_t *ce;
  265.       
  266.       if ( i < in.descr_t_len) 
  267.         ce = &(in.descr_t_val[i]);
  268.       else /* if current parameter is output */
  269.         {
  270.           out_parm = 1;
  271.           ce = &(out.descr_t_val[i - in.descr_t_len]);
  272.         }
  273.       
  274.       Nl;
  275.       N1("e = &p[%d];",i);
  276.       N1("e->type   = %d;",ce->type);
  277.       if (ce->type==SQLType_Char && out_parm)
  278.         N1("e->length = sizeof_%s;",parm_name (1, ce->name,i))
  279.       else
  280.         N1("e->length = %d;",ce->length);
  281.       
  282.       N1("e->flags  =  %d;",out_parm);
  283.       N2("e->valptr = (void*) %c %s;"       ,A_i,parm_name (1, ce->name,i));
  284.       N2("e->indptr =         %c ind_of_%s;",A_i,parm_name (1, ce->name,i));
  285.     }
  286.   /* make a finall call to runtime library */
  287.   Nl;
  288.   N1("SQL__runtime (&mdl, &ldata);n"
  289.      "}/*--- %s ----*/n"
  290.      "n",
  291.      subst_name(object,method));
  292. #undef Nl
  293. #undef N1
  294. #undef N2
  295. #undef L1
  296. #undef L2
  297. #undef A_
  298. #undef A_i
  299. }
  300. void
  301. gen_substitution (i4_t subst_to_c,char *host, compiled_t *prg)
  302. {
  303.   call_t            *call;
  304.   compiled_object_t *obj;
  305.   i4_t    st_uid;
  306.   errors = prg->errors;
  307.   /* open output file ----------------------------------------------------*/
  308.   open_file(&ofile,(subst_to_c?"c":"Sc"));
  309.   /* output prolog -------------------------------------------------------*/
  310.   sc_prolog (prg->stored.comp_data_t_u.module,(subst_to_c?"c":"Sc"),host);
  311.   /* output object interface routines ------------------------------------*/
  312.   for (obj = prg->objects; obj; obj = obj->next)
  313.     if (*obj->cursor_name) /* if compiled object is cursor */
  314.       {
  315.         descr_t zero = { 0 , NULL } ;
  316.         /*---- open ----------*/
  317.         print_routine (obj->descr_in, zero          , obj->object, 0,0);
  318.         /*---- fetch ---------*/
  319.         print_routine (zero         , obj->descr_out, obj->object, 1,
  320.                        /* if RO query - cached scan */
  321.                        (*obj->table_name? 0 : 50 )); 
  322.         /*---- close ---------*/
  323.         print_routine (zero         , zero          , obj->object, 2,0);
  324.         /*---- delete --------*/
  325.         if (*obj->table_name)
  326.           print_routine (zero       , zero          , obj->object, 3,0);
  327.       }
  328.     else
  329.       print_routine (obj->descr_in  , obj->descr_out, obj->object, 0,0);
  330.   /* output call substitutions -------------------------------------------*/
  331.   for (st_uid=0,call = prg->calls; call; call = call->next, st_uid++)
  332.     {
  333.       i4_t has_sqlcode_parm = 0;
  334.       /*----- call prolog ----------*/
  335.       if(!subst_to_c) /* if not module */
  336.         fprintf (ofile, "nn#define SQL__subst_%d ", st_uid);
  337.       if (!call->subst) /* if there is nothing to replace */
  338.         continue;
  339.       if (*call->subst->proc_name) /* if we compiled module */
  340.         { /* output the procedure title */
  341.           char params[4000];
  342.           assert(subst_to_c);
  343.           strcpy(params,
  344.                  get_param_list(&(call->subst->interface),NULL,MOD_PROTO));
  345.           assert(strlen(params)<sizeof(params));
  346.           has_sqlcode_parm = (NULL!=strstr(params,"SQLCODE"));
  347.           fprintf (ofile,
  348.                    "n"
  349.                    "voidn"
  350.                    "%s %s {n",call->subst->proc_name,params);
  351. #ifdef MOD_PROTO_OUTPUT
  352.           fprintf (hfile,"nvoid %s %s ;n",
  353.                    call->subst->proc_name,params);
  354. #endif
  355.         }
  356.       /*------- actual call substitution -------------*/
  357.       subst_call(call->subst,!subst_to_c);
  358.       /*------- call epilogue ------------------------*/
  359.       if (*call->subst->proc_name) /* if we compiled module */
  360.         { /* output the procedure end */
  361.           if(has_sqlcode_parm) 
  362.             fprintf (ofile,"t*SQLCODE_parm = SQLCODE;n");
  363.           fprintf (ofile,
  364.                    "treturn;n"
  365.                    "}n"
  366.                    "n");
  367.         }
  368.     }
  369.   /*---------------------  E  N  D  --------------------------------------*/
  370.   fprintf (ofile, "n/*--------------- End of file ------------------*/n");
  371.   fclose(ofile);
  372.   return;
  373. }/*-----------------------------------------------------------------------*/