LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - output.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 182 211 86.3 %
Date: 2019-09-19 02:07:14 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* src/interfaces/ecpg/preproc/output.c */
       2             : 
       3             : #include "postgres_fe.h"
       4             : 
       5             : #include "preproc_extern.h"
       6             : 
       7             : static void output_escaped_str(char *cmd, bool quoted);
       8             : static void output_cursor_name(char *str);
       9             : 
      10             : void
      11        4896 : output_line_number(void)
      12             : {
      13        4896 :     char       *line = hashline_number();
      14             : 
      15        4896 :     fprintf(base_yyout, "%s", line);
      16        4896 :     free(line);
      17        4896 : }
      18             : 
      19             : void
      20         270 : output_simple_statement(char *stmt, int whenever_mode)
      21             : {
      22         270 :     output_escaped_str(stmt, false);
      23         270 :     if (whenever_mode)
      24          20 :         whenever_action(whenever_mode);
      25         270 :     output_line_number();
      26         270 :     free(stmt);
      27         270 : }
      28             : 
      29             : 
      30             : /*
      31             :  * store the whenever action here
      32             :  */
      33             : struct when when_error,
      34             :             when_nf,
      35             :             when_warn;
      36             : 
      37             : static void
      38        1978 : print_action(struct when *w)
      39             : {
      40        1978 :     switch (w->code)
      41             :     {
      42             :         case W_SQLPRINT:
      43        1022 :             fprintf(base_yyout, "sqlprint();");
      44        1022 :             break;
      45             :         case W_GOTO:
      46           4 :             fprintf(base_yyout, "goto %s;", w->command);
      47           4 :             break;
      48             :         case W_DO:
      49         342 :             fprintf(base_yyout, "%s;", w->command);
      50         342 :             break;
      51             :         case W_STOP:
      52         582 :             fprintf(base_yyout, "exit (1);");
      53         582 :             break;
      54             :         case W_BREAK:
      55          26 :             fprintf(base_yyout, "break;");
      56          26 :             break;
      57             :         case W_CONTINUE:
      58           2 :             fprintf(base_yyout, "continue;");
      59           2 :             break;
      60             :         default:
      61           0 :             fprintf(base_yyout, "{/* %d not implemented yet */}", w->code);
      62           0 :             break;
      63             :     }
      64        1978 : }
      65             : 
      66             : void
      67        1940 : whenever_action(int mode)
      68             : {
      69        1940 :     if ((mode & 1) == 1 && when_nf.code != W_NOTHING)
      70             :     {
      71          58 :         output_line_number();
      72          58 :         fprintf(base_yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) ");
      73          58 :         print_action(&when_nf);
      74             :     }
      75        1940 :     if (when_warn.code != W_NOTHING)
      76             :     {
      77         286 :         output_line_number();
      78         286 :         fprintf(base_yyout, "\nif (sqlca.sqlwarn[0] == 'W') ");
      79         286 :         print_action(&when_warn);
      80             :     }
      81        1940 :     if (when_error.code != W_NOTHING)
      82             :     {
      83        1634 :         output_line_number();
      84        1634 :         fprintf(base_yyout, "\nif (sqlca.sqlcode < 0) ");
      85        1634 :         print_action(&when_error);
      86             :     }
      87             : 
      88        1940 :     if ((mode & 2) == 2)
      89        1860 :         fputc('}', base_yyout);
      90             : 
      91        1940 :     output_line_number();
      92        1940 : }
      93             : 
      94             : char *
      95        5472 : hashline_number(void)
      96             : {
      97             :     /* do not print line numbers if we are in debug mode */
      98        5472 :     if (input_filename
      99             : #ifdef YYDEBUG
     100             :         && !base_yydebug
     101             : #endif
     102             :         )
     103             :     {
     104             :         /* "* 2" here is for escaping '\' and '"' below */
     105        5472 :         char       *line = mm_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2);
     106             :         char       *src,
     107             :                    *dest;
     108             : 
     109        5472 :         sprintf(line, "\n#line %d \"", base_yylineno);
     110        5472 :         src = input_filename;
     111        5472 :         dest = line + strlen(line);
     112       75812 :         while (*src)
     113             :         {
     114       64868 :             if (*src == '\\' || *src == '"')
     115           0 :                 *dest++ = '\\';
     116       64868 :             *dest++ = *src++;
     117             :         }
     118        5472 :         *dest = '\0';
     119        5472 :         strcat(dest, "\"\n");
     120             : 
     121        5472 :         return line;
     122             :     }
     123             : 
     124           0 :     return EMPTY;
     125             : }
     126             : 
     127             : static char *ecpg_statement_type_name[] = {
     128             :     "ECPGst_normal",
     129             :     "ECPGst_execute",
     130             :     "ECPGst_exec_immediate",
     131             :     "ECPGst_prepnormal",
     132             :     "ECPGst_prepare",
     133             :     "ECPGst_exec_with_exprlist"
     134             : };
     135             : 
     136             : void
     137         760 : output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
     138             : {
     139         760 :     fprintf(base_yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks);
     140             : 
     141         760 :     if (st == ECPGst_prepnormal && !auto_prepare)
     142         362 :         st = ECPGst_normal;
     143             : 
     144             :     /*
     145             :      * In following cases, stmt is CSTRING or char_variable. They must be
     146             :      * output directly. - prepared_name of EXECUTE without exprlist -
     147             :      * execstring of EXECUTE IMMEDIATE
     148             :      */
     149         760 :     fprintf(base_yyout, "%s, ", ecpg_statement_type_name[st]);
     150         760 :     if (st == ECPGst_execute || st == ECPGst_exec_immediate)
     151          62 :         fprintf(base_yyout, "%s, ", stmt);
     152             :     else
     153             :     {
     154         698 :         fputs("\"", base_yyout);
     155         698 :         output_escaped_str(stmt, false);
     156         698 :         fputs("\", ", base_yyout);
     157             :     }
     158             : 
     159             :     /* dump variables to C file */
     160         760 :     dump_variables(argsinsert, 1);
     161         760 :     fputs("ECPGt_EOIT, ", base_yyout);
     162         760 :     dump_variables(argsresult, 1);
     163         760 :     fputs("ECPGt_EORT);", base_yyout);
     164         760 :     reset_variables();
     165             : 
     166         760 :     whenever_action(whenever_mode | 2);
     167         760 :     free(stmt);
     168         760 :     if (connection != NULL)
     169          46 :         free(connection);
     170         760 :     connection = NULL;
     171         760 : }
     172             : 
     173             : void
     174          94 : output_prepare_statement(char *name, char *stmt)
     175             : {
     176          94 :     fprintf(base_yyout, "{ ECPGprepare(__LINE__, %s, %d, ", connection ? connection : "NULL", questionmarks);
     177          94 :     output_escaped_str(name, true);
     178          94 :     fputs(", ", base_yyout);
     179          94 :     output_escaped_str(stmt, true);
     180          94 :     fputs(");", base_yyout);
     181          94 :     whenever_action(2);
     182          94 :     free(name);
     183          94 :     if (connection != NULL)
     184          14 :         free(connection);
     185          94 :     connection = NULL;
     186          94 : }
     187             : 
     188             : void
     189          76 : output_deallocate_prepare_statement(char *name)
     190             : {
     191          76 :     const char *con = connection ? connection : "NULL";
     192             : 
     193          76 :     if (strcmp(name, "all") != 0)
     194             :     {
     195          74 :         fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, ", compat, con);
     196          74 :         output_escaped_str(name, true);
     197          74 :         fputs(");", base_yyout);
     198             :     }
     199             :     else
     200           2 :         fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
     201             : 
     202          76 :     whenever_action(2);
     203          76 :     free(name);
     204          76 :     if (connection != NULL)
     205          10 :         free(connection);
     206          76 :     connection = NULL;
     207          76 : }
     208             : 
     209             : static void
     210        1574 : output_escaped_str(char *str, bool quoted)
     211             : {
     212        1574 :     int         i = 0;
     213        1574 :     int         len = 0;
     214             : 
     215        1574 :     if (str == NULL)
     216             :     {
     217          34 :         fputs("NULL", base_yyout);
     218             : 
     219          34 :         return;
     220             :     }
     221             : 
     222        1540 :     len = strlen(str);
     223             : 
     224        1540 :     if (quoted && str[0] == '"' && str[len - 1] == '"') /* do not escape quotes
     225             :                                                          * at beginning and end
     226             :                                                          * if quoted string */
     227             :     {
     228         214 :         i = 1;
     229         214 :         len--;
     230         214 :         fputs("\"", base_yyout);
     231             :     }
     232             : 
     233             :     /* output this char by char as we have to filter " and \n */
     234       54942 :     for (; i < len; i++)
     235             :     {
     236       53402 :         if (str[i] == '"')
     237          76 :             fputs("\\\"", base_yyout);
     238       53326 :         else if (str[i] == '\n')
     239          34 :             fputs("\\\n", base_yyout);
     240       53292 :         else if (str[i] == '\\')
     241             :         {
     242          38 :             int         j = i;
     243             : 
     244             :             /*
     245             :              * check whether this is a continuation line if it is, do not
     246             :              * output anything because newlines are escaped anyway
     247             :              */
     248             : 
     249             :             /* accept blanks after the '\' as some other compilers do too */
     250             :             do
     251             :             {
     252          38 :                 j++;
     253          38 :             } while (str[j] == ' ' || str[j] == '\t');
     254             : 
     255          38 :             if ((str[j] != '\n') && (str[j] != '\r' || str[j + 1] != '\n')) /* not followed by a
     256             :                                                                              * newline */
     257          38 :                 fputs("\\\\", base_yyout);
     258             :         }
     259       53254 :         else if (str[i] == '\r' && str[i + 1] == '\n')
     260             :         {
     261           0 :             fputs("\\\r\n", base_yyout);
     262           0 :             i++;
     263             :         }
     264             :         else
     265       53254 :             fputc(str[i], base_yyout);
     266             :     }
     267             : 
     268        1540 :     if (quoted && str[0] == '"' && str[len] == '"')
     269         214 :         fputs("\"", base_yyout);
     270             : }
     271             : 
     272             : /*
     273             :  * This is a tool function used by the output_cursor_statement function to print
     274             :  * cursor name after the string such as "ECPGopen(","ECPGfetch(","ECPGclose(".
     275             :  * This function filters escaped sequences such as \t, \n, \r to print cursor name cleanly
     276             :  */
     277             : static void
     278         262 : output_cursor_name(char *str)
     279             : {
     280         262 :     int         i = 0;
     281         262 :     int         len = 0;
     282             : 
     283         262 :     if (str == NULL)
     284             :     {
     285           0 :         fputs("NULL", base_yyout);
     286             : 
     287           0 :         return;
     288             :     }
     289             : 
     290         262 :     len = strlen(str);
     291         262 :     fputs("\"", base_yyout);
     292         262 :     if (str[0] == '\"' && str[len - 1] == '\"')
     293             :     {
     294           0 :         i = 1;
     295           0 :         len--;
     296           0 :         fputs("\\\"", base_yyout);
     297             : 
     298             :         /* output this char by char as we have to filter " and \n */
     299           0 :         for (; i < len; i++)
     300             :         {
     301           0 :             if (str[i] == '"')
     302           0 :                 fputs("\\\"", base_yyout);
     303           0 :             else if (str[i] == '\n')
     304           0 :                 fputs("\\\n", base_yyout);
     305           0 :             else if (str[i] == '\\')
     306             :             {
     307           0 :                 int         j = i;
     308             : 
     309             :                 /*
     310             :                  * check whether this is a continuation line if it is, do not
     311             :                  * output anything because newlines are escaped anyway
     312             :                  */
     313             : 
     314             :                 /* accept blanks after the '\' as some other compilers do too */
     315             :                 do
     316             :                 {
     317           0 :                     j++;
     318           0 :                 } while (str[j] == ' ' || str[j] == '\t');
     319             : 
     320           0 :                 if ((str[j] != '\n') && (str[j] != '\r' || str[j + 1] != '\n')) /* not followed by a
     321             :                                                                                  * newline */
     322           0 :                     fputs("\\\\", base_yyout);
     323             :             }
     324           0 :             else if (str[i] == '\r' && str[i + 1] == '\n')
     325             :             {
     326           0 :                 fputs("\\\r\n", base_yyout);
     327           0 :                 i++;
     328             :             }
     329             :             else
     330           0 :                 fputc(str[i], base_yyout);
     331             :         }
     332             : 
     333           0 :         fputs("\\\"", base_yyout);
     334             :     }
     335             :     else
     336         262 :         fputs(str, base_yyout);
     337             : 
     338         262 :     fputs("\"", base_yyout);
     339             : }
     340             : 
     341             : /*
     342             :  * Transform the EXEC SQL DECLARE STATEMENT into ECPGdeclare function
     343             :  */
     344             : void
     345          10 : output_declare_statement(char *name)
     346             : {
     347             :     /* connection is set in "at:" token in ecpg.trailer file */
     348          10 :     fprintf(base_yyout, "{ ECPGdeclare(__LINE__, %s, ", connection ? connection : "NULL");
     349          10 :     output_escaped_str(name, true);
     350          10 :     fputs(");", base_yyout);
     351             : 
     352          10 :     whenever_action(2);
     353          10 :     free(name);
     354          10 :     if (connection != NULL)
     355           4 :         free(connection);
     356          10 : }
     357             : 
     358             : /*
     359             :  * Transform the EXEC SQL CURSOR STATEMENT such as OPEN/FETCH/CLOSE cursor into
     360             :  * ECPGopen/ECPGfetch/ECPGclose function
     361             :  */
     362             : void
     363         262 : output_cursor_statement(int cursor_stmt, char *cursor_name, char *prepared_name, char *stmt, int whenever_mode, enum ECPG_statement_type st)
     364             : {
     365         262 :     switch (cursor_stmt)
     366             :     {
     367             :         case ECPGcst_open:
     368          72 :             fprintf(base_yyout, "{ ECPGopen(");
     369          72 :             output_cursor_name(cursor_name);
     370          72 :             fprintf(base_yyout, ", ");
     371          72 :             output_escaped_str(prepared_name, true);
     372         144 :             fprintf(base_yyout, ", __LINE__, %d, %d, %s, %d, ",
     373          72 :                     compat, force_indicator, connection ? connection : "NULL", questionmarks);
     374          72 :             break;
     375             :         case ECPGcst_fetch:
     376         122 :             fprintf(base_yyout, "{ ECPGfetch(");
     377         122 :             output_cursor_name(cursor_name);
     378         244 :             fprintf(base_yyout, ", __LINE__, %d, %d, %s, %d, ",
     379         122 :                     compat, force_indicator, connection ? connection : "NULL", questionmarks);
     380         122 :             break;
     381             :         case ECPGcst_close:
     382          68 :             fprintf(base_yyout, "{ ECPGclose(");
     383          68 :             output_cursor_name(cursor_name);
     384         136 :             fprintf(base_yyout, ", __LINE__, %d, %d, %s, %d, ",
     385          68 :                     compat, force_indicator, connection ? connection : "NULL", questionmarks);
     386          68 :             break;
     387             :     }
     388             : 
     389         262 :     if (st == ECPGst_execute || st == ECPGst_exec_immediate)
     390           0 :         fprintf(base_yyout, "%s, %s, ", ecpg_statement_type_name[st], stmt);
     391             :     else
     392             :     {
     393         262 :         if (st == ECPGst_prepnormal && auto_prepare)
     394           0 :             fputs("ECPGst_prepnormal, \"", base_yyout);
     395             :         else
     396         262 :             fputs("ECPGst_normal, \"", base_yyout);
     397             : 
     398         262 :         output_escaped_str(stmt, false);
     399         262 :         fputs("\", ", base_yyout);
     400             :     }
     401             : 
     402             :     /* dump variables to C file */
     403         262 :     dump_variables(argsinsert, 1);
     404         262 :     fputs("ECPGt_EOIT, ", base_yyout);
     405         262 :     dump_variables(argsresult, 1);
     406         262 :     fputs("ECPGt_EORT);", base_yyout);
     407         262 :     reset_variables();
     408             : 
     409         262 :     whenever_action(whenever_mode | 2);
     410         262 :     free(cursor_name);
     411         262 :     free(prepared_name);
     412         262 :     free(stmt);
     413         262 :     if (connection != NULL)
     414          88 :         free(connection);
     415         262 : }

Generated by: LCOV version 1.13