Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members  

application.cc

00001 /*
00002 *  Name:      application.cc
00003 *  Author:    Rafael Jesus Alcantara Perez
00004 *  Summary:   UESQLC application
00005 *  Date:      $Date: 2003/10/06 13:21:36 $
00006 *  Revision:  $Revision: 1.65 $
00007 *
00008 *  Copyright (C) 1996-2003  Rafael Jesus Alcantara Perez <rafa@dedalo-ing.com>
00009 *
00010 *  This program is free software; you can redistribute it and/or modify
00011 *  it under the terms of the GNU General Public License as published by
00012 *  the Free Software Foundation; either version 2 of the License, or
00013 *  (at your option) any later version.
00014 *
00015 *  This program is distributed in the hope that it will be useful,
00016 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 *  GNU General Public License for more details.
00019 *
00020 *  You should have received a copy of the GNU General Public License
00021 *  along with this program; if not, write to the Free Software
00022 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00023 *  MA 02111-1307, USA.
00024 */
00025 
00026 #include <cstdio>
00027 #include <cstdlib>
00028 #include <cstring>
00029 #include <fstream>
00030 #include <mpcl/system/all.hh>
00031 #include <mpcl/text/codegen/clause_body_string.hh>
00032 #include <mpcl/text/codegen/instruction_body.hh>
00033 #include "application.hh"
00034 #include "defs.hh"
00035 #include "stack_value.hh"
00036 #include "uesql_parser.h"
00037 
00038 
00039 //
00040 //  V A R I A B L E   I N I T I A L I Z A T I O N
00041 //
00042 
00043 const char* const   TApplication::_pkcExtension = ".uesql";
00044 
00045 
00046 //
00047 //  C O N S T R U C T O R S
00048 //
00049 
00050 TApplication::TApplication ( const char*  pkcAPPLICATION_NAME    ,
00051                              const char*  pkcAPPLICATION_RELEASE ,
00052                              int          iPARAMETER_COUNT       ,
00053                              const char** ppkcPARAMETERS         )               :
00054   TAbstractApplication             (pkcAPPLICATION_NAME, pkcAPPLICATION_RELEASE) ,
00055   gCfgComplementaryFiles           (false)                                       ,
00056   gCfgHelp                         (false)                                       ,
00057   gCfgLineDirectives               (false)                                       ,
00058   gCfgMainFile                     (false)                                       ,
00059   gCfgOutputCdml                   (false)                                       ,
00060   gCfgOutputCdmlSkel               (false)                                       ,
00061   gCfgParameters                   (false)                                       ,
00062   gCfgSyntaxCheckOnly              (false)                                       ,
00063   gCfgVersion                      (false)                                       ,
00064   gCompilationOk                   (true)                                        ,
00065   gReusingTarget                   (false)                                       ,
00066   ptRuntimeParametersMap           (NULL)                                        ,
00067   tCodeParametersMap               ()                                            ,
00068   tConfigProcessor                 (iPARAMETER_COUNT, ppkcPARAMETERS)            ,
00069   tInvariantVerifier               ()                                            ,
00070   tReservedWordMap                 ()                                            ,
00071   tTargetToCodeGeneratorMap        ()                                            ,
00072   tTargetToRuntimeParametersMapMap ()                                            ,
00073   uiCfgDebug                       (0)                                           ,
00074   yCfgCdmlPath                     ()                                            ,
00075   yCfgComplementaryFileDirectory   ()                                            ,
00076   yCfgLanguage                     ()                                            ,
00077   yCfgTarget                       ()                                            ,
00078   yCurrentInputFileName            ()                                            ,
00079   yCurrentTarget                   ()                                            ,
00080   yLastToken                       ()                                            ,
00081   yOutputCode                      ()                                            ,
00082   yPostfixOutputCode               ()                                            ,
00083   yPrefixOutputCode                ()                                            ,
00084   zEmbeddedIntroducerLine          (0)
00085 {
00086 
00087   //
00088   //  Subsection 5.2: <token> and <separator>. 
00089   //
00090 
00091   //
00092   //  Non-Terminal:  <reserved word>
00093   //
00094   tReservedWordMap.bind ("ABSOLUTE",          RW_ABSOLUTE);
00095   tReservedWordMap.bind ("ACTION",            RW_ACTION);
00096   tReservedWordMap.bind ("ADD",               RW_ADD);
00097   tReservedWordMap.bind ("ALLOCATE",          RW_ALLOCATE);
00098   tReservedWordMap.bind ("ALL",               RW_ALL);
00099   tReservedWordMap.bind ("ALTER",             RW_ALTER);
00100   tReservedWordMap.bind ("AND",               RW_AND);
00101   tReservedWordMap.bind ("ANY",               RW_ANY);
00102   tReservedWordMap.bind ("ASC",               RW_ASC);
00103   tReservedWordMap.bind ("ASSERTION",         RW_ASSERTION);
00104   tReservedWordMap.bind ("AS",                RW_AS);
00105   tReservedWordMap.bind ("AT",                RW_AT);
00106   tReservedWordMap.bind ("AUTHORIZATION",     RW_AUTHORIZATION);
00107   tReservedWordMap.bind ("AVG",               RW_AVG);
00108   tReservedWordMap.bind ("BETWEEN",           RW_BETWEEN);
00109   tReservedWordMap.bind ("BIT_LENGTH",        RW_BIT_LENGTH);
00110   tReservedWordMap.bind ("BIT",               RW_BIT);
00111   tReservedWordMap.bind ("BOTH",              RW_BOTH);
00112   tReservedWordMap.bind ("BY",                RW_BY);
00113   tReservedWordMap.bind ("CASCADED",          RW_CASCADED);
00114   tReservedWordMap.bind ("CASCADE",           RW_CASCADE);
00115   tReservedWordMap.bind ("CASE",              RW_CASE);
00116   tReservedWordMap.bind ("CAST",              RW_CAST);
00117   tReservedWordMap.bind ("CATALOG",           RW_CATALOG);
00118   tReservedWordMap.bind ("CHARACTER_LENGTH",  RW_CHARACTER_LENGTH);
00119   tReservedWordMap.bind ("CHARACTER",         RW_CHARACTER);
00120   tReservedWordMap.bind ("CHAR_LENGTH",       RW_CHAR_LENGTH);
00121   tReservedWordMap.bind ("CHAR",              RW_CHAR);
00122   tReservedWordMap.bind ("CHECK",             RW_CHECK);
00123   tReservedWordMap.bind ("CLOSE",             RW_CLOSE);
00124   tReservedWordMap.bind ("COALESCE",          RW_COALESCE);
00125   tReservedWordMap.bind ("COLLATE",           RW_COLLATE);
00126   tReservedWordMap.bind ("COLLATION",         RW_COLLATION);
00127   tReservedWordMap.bind ("COLUMN",            RW_COLUMN);
00128   tReservedWordMap.bind ("COMMIT",            RW_COMMIT);
00129   tReservedWordMap.bind ("CONDITION",         RW_CONDITION);
00130   tReservedWordMap.bind ("CONNECTION",        RW_CONNECTION);
00131   tReservedWordMap.bind ("CONNECT",           RW_CONNECT);
00132   tReservedWordMap.bind ("CONSTRAINTS",       RW_CONSTRAINTS);
00133   tReservedWordMap.bind ("CONSTRAINT",        RW_CONSTRAINT);
00134   tReservedWordMap.bind ("CONTINUE",          RW_CONTINUE);
00135   tReservedWordMap.bind ("CONVERT",           RW_CONVERT);
00136   tReservedWordMap.bind ("CORRESPONDING",     RW_CORRESPONDING);
00137   tReservedWordMap.bind ("COUNT",             RW_COUNT);
00138   tReservedWordMap.bind ("CREATE",            RW_CREATE);
00139   tReservedWordMap.bind ("CROSS",             RW_CROSS);
00140   tReservedWordMap.bind ("CURRENT_DATE",      RW_CURRENT_DATE);
00141   tReservedWordMap.bind ("CURRENT_TIMESTAMP", RW_CURRENT_TIMESTAMP);
00142   tReservedWordMap.bind ("CURRENT_TIME",      RW_CURRENT_TIME);
00143   tReservedWordMap.bind ("CURRENT_USER",      RW_CURRENT_USER);
00144   tReservedWordMap.bind ("CURRENT",           RW_CURRENT);
00145   tReservedWordMap.bind ("CURSOR",            RW_CURSOR);
00146   tReservedWordMap.bind ("DATE",              RW_DATE);
00147   tReservedWordMap.bind ("DAY",               RW_DAY);
00148   tReservedWordMap.bind ("DEALLOCATE",        RW_DEALLOCATE);
00149   tReservedWordMap.bind ("DECIMAL",           RW_DECIMAL);
00150   tReservedWordMap.bind ("DECLARE",           RW_DECLARE);
00151   tReservedWordMap.bind ("DEC",               RW_DEC);
00152   tReservedWordMap.bind ("DEFAULT",           RW_DEFAULT);
00153   tReservedWordMap.bind ("DEFERRABLE",        RW_DEFERRABLE);
00154   tReservedWordMap.bind ("DEFERRED",          RW_DEFERRED);
00155   tReservedWordMap.bind ("DELETE",            RW_DELETE);
00156   tReservedWordMap.bind ("DESCRIBE",          RW_DESCRIBE);
00157   tReservedWordMap.bind ("DESCRIPTOR",        RW_DESCRIPTOR);
00158   tReservedWordMap.bind ("DESC",              RW_DESC);
00159   tReservedWordMap.bind ("DIAGNOSTICS",       RW_DIAGNOSTICS);
00160   tReservedWordMap.bind ("DISCONNECT",        RW_DISCONNECT);
00161   tReservedWordMap.bind ("DISTINCT",          RW_DISTINCT);
00162   tReservedWordMap.bind ("DOMAIN",            RW_DOMAIN);
00163   tReservedWordMap.bind ("DOUBLE",            RW_DOUBLE);
00164   tReservedWordMap.bind ("DROP",              RW_DROP);
00165   tReservedWordMap.bind ("ELSE",              RW_ELSE);
00166   tReservedWordMap.bind ("END",               RW_END);
00167   tReservedWordMap.bind ("ESCAPE",            RW_ESCAPE);
00168   tReservedWordMap.bind ("EXCEPTION",         RW_EXCEPTION);
00169   tReservedWordMap.bind ("EXCEPT",            RW_EXCEPT);
00170   tReservedWordMap.bind ("EXECUTE",           RW_EXECUTE);
00171   tReservedWordMap.bind ("EXISTS",            RW_EXISTS);
00172   tReservedWordMap.bind ("EXTRACT",           RW_EXTRACT);
00173   tReservedWordMap.bind ("FALSE",             RW_FALSE);
00174   tReservedWordMap.bind ("FETCH",             RW_FETCH);
00175   tReservedWordMap.bind ("FIRST",             RW_FIRST);
00176   tReservedWordMap.bind ("FLOAT",             RW_FLOAT);
00177   tReservedWordMap.bind ("FOREIGN",           RW_FOREIGN);
00178   tReservedWordMap.bind ("FOR",               RW_FOR);
00179   tReservedWordMap.bind ("FOUND",             RW_FOUND);
00180   tReservedWordMap.bind ("FROM",              RW_FROM);
00181   tReservedWordMap.bind ("FULL",              RW_FULL);
00182   tReservedWordMap.bind ("GET",               RW_GET);
00183   tReservedWordMap.bind ("GLOBAL",            RW_GLOBAL);
00184   tReservedWordMap.bind ("GOTO",              RW_GOTO);
00185   tReservedWordMap.bind ("GO",                RW_GO);
00186   tReservedWordMap.bind ("GRANT",             RW_GRANT);
00187   tReservedWordMap.bind ("GROUP",             RW_GROUP);
00188   tReservedWordMap.bind ("HAVING",            RW_HAVING);
00189   tReservedWordMap.bind ("HOUR",              RW_HOUR);
00190   tReservedWordMap.bind ("IMMEDIATE",         RW_IMMEDIATE);
00191   tReservedWordMap.bind ("INDICATOR",         RW_INDICATOR);
00192   tReservedWordMap.bind ("INITIALLY",         RW_INITIALLY);
00193   tReservedWordMap.bind ("INNER",             RW_INNER);
00194   tReservedWordMap.bind ("INPUT",             RW_INPUT);
00195   tReservedWordMap.bind ("INSENSITIVE",       RW_INSENSITIVE);
00196   tReservedWordMap.bind ("INSERT",            RW_INSERT);
00197   tReservedWordMap.bind ("INTEGER",           RW_INTEGER);
00198   tReservedWordMap.bind ("INTERSECT",         RW_INTERSECT);
00199   tReservedWordMap.bind ("INTERVAL",          RW_INTERVAL);
00200   tReservedWordMap.bind ("INTO",              RW_INTO);
00201   tReservedWordMap.bind ("INT",               RW_INT);
00202   tReservedWordMap.bind ("IN",                RW_IN);
00203   tReservedWordMap.bind ("ISOLATION",         RW_ISOLATION);
00204   tReservedWordMap.bind ("IS",                RW_IS);
00205   tReservedWordMap.bind ("JOIN",              RW_JOIN);
00206   tReservedWordMap.bind ("KEY",               RW_KEY);
00207   tReservedWordMap.bind ("LAST",              RW_LAST);
00208   tReservedWordMap.bind ("LEADING",           RW_LEADING);
00209   tReservedWordMap.bind ("LEFT",              RW_LEFT);
00210   tReservedWordMap.bind ("LEVEL",             RW_LEVEL);
00211   tReservedWordMap.bind ("LIKE",              RW_LIKE);
00212   tReservedWordMap.bind ("LOCAL",             RW_LOCAL);
00213   tReservedWordMap.bind ("LOWER",             RW_LOWER);
00214   tReservedWordMap.bind ("MATCH",             RW_MATCH);
00215   tReservedWordMap.bind ("MAX",               RW_MAX);
00216   tReservedWordMap.bind ("MIN",               RW_MIN);
00217   tReservedWordMap.bind ("MINUTE",            RW_MINUTE);
00218   tReservedWordMap.bind ("MONTH",             RW_MONTH);
00219   tReservedWordMap.bind ("NAMES",             RW_NAMES);
00220   tReservedWordMap.bind ("NATIONAL",          RW_NATIONAL);
00221   tReservedWordMap.bind ("NATURAL",           RW_NATURAL);
00222   tReservedWordMap.bind ("NCHAR",             RW_NCHAR);
00223   tReservedWordMap.bind ("NEXT",              RW_NEXT);
00224   tReservedWordMap.bind ("NOT",               RW_NOT);
00225   tReservedWordMap.bind ("NO",                RW_NO);
00226   tReservedWordMap.bind ("NULLIF",            RW_NULLIF);
00227   tReservedWordMap.bind ("NULL",              RW_NULL);
00228   tReservedWordMap.bind ("NUMERIC",           RW_NUMERIC);
00229   tReservedWordMap.bind ("OCTET_LENGTH",      RW_OCTET_LENGTH);
00230   tReservedWordMap.bind ("OF",                RW_OF);
00231   tReservedWordMap.bind ("ONLY",              RW_ONLY);
00232   tReservedWordMap.bind ("ON",                RW_ON);
00233   tReservedWordMap.bind ("OPEN",              RW_OPEN);
00234   tReservedWordMap.bind ("OPTION",            RW_OPTION);
00235   tReservedWordMap.bind ("ORDER",             RW_ORDER);
00236   tReservedWordMap.bind ("OR",                RW_OR);
00237   tReservedWordMap.bind ("OUTER",             RW_OUTER);
00238   tReservedWordMap.bind ("OUTPUT",            RW_OUTPUT);
00239   tReservedWordMap.bind ("OVERLAPS",          RW_OVERLAPS);
00240   tReservedWordMap.bind ("PARTIAL",           RW_PARTIAL);
00241   tReservedWordMap.bind ("POSITION",          RW_POSITION);
00242   tReservedWordMap.bind ("PRECISION",         RW_PRECISION);
00243   tReservedWordMap.bind ("PREPARE",           RW_PREPARE);
00244   tReservedWordMap.bind ("PRESERVE",          RW_PRESERVE);
00245   tReservedWordMap.bind ("PRIMARY",           RW_PRIMARY);
00246   tReservedWordMap.bind ("PRIOR",             RW_PRIOR);
00247   tReservedWordMap.bind ("PRIVILEGES",        RW_PRIVILEGES);
00248   tReservedWordMap.bind ("PUBLIC",            RW_PUBLIC);
00249   tReservedWordMap.bind ("READ",              RW_READ);
00250   tReservedWordMap.bind ("REAL",              RW_REAL);
00251   tReservedWordMap.bind ("REFERENCES",        RW_REFERENCES);
00252   tReservedWordMap.bind ("RELATIVE",          RW_RELATIVE);
00253   tReservedWordMap.bind ("RESTRICT",          RW_RESTRICT);
00254   tReservedWordMap.bind ("REVOKE",            RW_REVOKE);
00255   tReservedWordMap.bind ("RIGHT",             RW_RIGHT);
00256   tReservedWordMap.bind ("ROLLBACK",          RW_ROLLBACK);
00257   tReservedWordMap.bind ("ROWS",              RW_ROWS);
00258   tReservedWordMap.bind ("SCHEMA",            RW_SCHEMA);
00259   tReservedWordMap.bind ("SCROLL",            RW_SCROLL);
00260   tReservedWordMap.bind ("SECOND",            RW_SECOND);
00261   tReservedWordMap.bind ("SELECT",            RW_SELECT);
00262   tReservedWordMap.bind ("SESSION_USER",      RW_SESSION_USER);
00263   tReservedWordMap.bind ("SESSION",           RW_SESSION);
00264   tReservedWordMap.bind ("SET",               RW_SET);
00265   tReservedWordMap.bind ("SIZE",              RW_SIZE);
00266   tReservedWordMap.bind ("SMALLINT",          RW_SMALLINT);
00267   tReservedWordMap.bind ("SOME",              RW_SOME);
00268   tReservedWordMap.bind ("SQLERROR",          RW_SQLERROR);
00269   tReservedWordMap.bind ("SQL",               RW_SQL);
00270   tReservedWordMap.bind ("SUBSTRING",         RW_SUBSTRING);
00271   tReservedWordMap.bind ("SUM",               RW_SUM);
00272   tReservedWordMap.bind ("SYSTEM_USER",       RW_SYSTEM_USER);
00273   tReservedWordMap.bind ("TABLE",             RW_TABLE);
00274   tReservedWordMap.bind ("TEMPORARY",         RW_TEMPORARY);
00275   tReservedWordMap.bind ("THEN",              RW_THEN);
00276   tReservedWordMap.bind ("THROW",             RW_THROW);
00277   tReservedWordMap.bind ("TIMESTAMP",         RW_TIMESTAMP);
00278   tReservedWordMap.bind ("TIMEZONE_HOUR",     RW_TIMEZONE_HOUR);
00279   tReservedWordMap.bind ("TIMEZONE_MINUTE",   RW_TIMEZONE_MINUTE);
00280   tReservedWordMap.bind ("TIME",              RW_TIME);
00281   tReservedWordMap.bind ("TO",                RW_TO);
00282   tReservedWordMap.bind ("TRAILING",          RW_TRAILING);
00283   tReservedWordMap.bind ("TRANSACTION",       RW_TRANSACTION);
00284   tReservedWordMap.bind ("TRANSLATE",         RW_TRANSLATE);
00285   tReservedWordMap.bind ("TRANSLATION",       RW_TRANSLATION);
00286   tReservedWordMap.bind ("TRIM",              RW_TRIM);
00287   tReservedWordMap.bind ("TRUE",              RW_TRUE);
00288   tReservedWordMap.bind ("UNION",             RW_UNION);
00289   tReservedWordMap.bind ("UNIQUE",            RW_UNIQUE);
00290   tReservedWordMap.bind ("UNKNOWN",           RW_UNKNOWN);
00291   tReservedWordMap.bind ("UPDATE",            RW_UPDATE);
00292   tReservedWordMap.bind ("UPPER",             RW_UPPER);
00293   tReservedWordMap.bind ("USAGE",             RW_USAGE);
00294   tReservedWordMap.bind ("USER",              RW_USER);
00295   tReservedWordMap.bind ("USING",             RW_USING);
00296   tReservedWordMap.bind ("VALUES",            RW_VALUES);
00297   tReservedWordMap.bind ("VALUE",             RW_VALUE);
00298   tReservedWordMap.bind ("VARCHAR",           RW_VARCHAR);
00299   tReservedWordMap.bind ("VARYING",           RW_VARYING);
00300   tReservedWordMap.bind ("VIEW",              RW_VIEW);
00301   tReservedWordMap.bind ("WHENEVER",          RW_WHENEVER);
00302   tReservedWordMap.bind ("WHEN",              RW_WHEN);
00303   tReservedWordMap.bind ("WHERE",             RW_WHERE);
00304   tReservedWordMap.bind ("WITH",              RW_WITH);
00305   tReservedWordMap.bind ("WORK",              RW_WORK);
00306   tReservedWordMap.bind ("WRITE",             RW_WRITE);
00307   tReservedWordMap.bind ("YEAR",              RW_YEAR);
00308 
00309 }  // TApplication()
00310 
00311 
00312 void TApplication::closeFiles (void)
00313 {
00314 
00315   using std::fclose;
00316 
00317   //
00318   //  yyin is always distinct from stdin.
00319   //
00320   if ( yyin && ( yyin != stdin ) )
00321   {
00322     fclose (yyin);
00323   }
00324   if ( !gCfgSyntaxCheckOnly )
00325   {
00326     if ( yyout && ( yyout != stdout ) )
00327     {
00328       fclose (yyout);
00329     }
00330   }
00331 
00332 }  // closeFiles()
00333 
00334 
00335 mpcl::text::TString TApplication::collapseStringLiteral (const char* pkcSOURCE_TEXT)
00336 {
00337 
00338   char                  cQuoteCharacter;
00339   bool                  gBetweenParts;
00340   mpcl::text::TString   yCollapsedStringLiteral;
00341   const char*           pkcIterator = pkcSOURCE_TEXT;
00342 
00343   //
00344   //  If the first character is 'N', 'B' or 'X', then
00345   //  let's eat that character.
00346   //
00347   if ( ( *pkcIterator == 'N' ) ||
00348        ( *pkcIterator == 'B' ) ||
00349        ( *pkcIterator == 'X' )  )
00350   {
00351     ++pkcIterator;
00352   }
00353 
00354   //
00355   //  Select quote/double-quote character.
00356   //
00357   cQuoteCharacter = *pkcIterator;
00358 
00359   //
00360   //  Eat the quote/double-quote character.
00361   //
00362   ++pkcIterator;
00363   if ( cQuoteCharacter == '"' )
00364   {
00365     //
00366     //  <delimited identifier> ::=
00367     //    <double quote> <delimited identifier body> <double quote>
00368     //
00369     yCollapsedStringLiteral = pkcSOURCE_TEXT + 1;
00370     yCollapsedStringLiteral.replaceAll ("\"\"", "\"");
00371     yCollapsedStringLiteral [yCollapsedStringLiteral.length() - 1] = '\0';
00372   }
00373   else
00374   {
00375     //
00376     //  <character string literal> ::=
00377     //    [ <introducer><character set specification> ]
00378     //    <quote> [ <character representation>... ] <quote>
00379     //    [ { <separator>... <quote> [ <character representation>... ] <quote> }... ]
00380     //
00381     //  <national character string literal> ::=
00382     //    N <quote> [ <character representation>... ] <quote>
00383     //    [ { <separator>... <quote> [ <character representation>... ] <quote> }... ]
00384     //
00385     //  <bit string literal> ::=
00386     //    B <quote> [ <bit>... ] <quote>
00387     //    [ { <separator>... <quote> [ <bit>... ] <quote> }... ]
00388     //
00389     //  <hex string literal> ::=
00390     //    X <quote> [ <hexit>... ] <quote>
00391     //    [ { <separator>... <quote> [ <hexit>... ] <quote> }... ]
00392     //
00393  
00394     //
00395     //  Copy (collapsing if needed) the rest of the string.
00396     //
00397     while ( *pkcIterator )
00398     {
00399       if ( *pkcIterator == '\"' )
00400       {
00401         //
00402         //  Escapes the '\"'.
00403         //
00404         yCollapsedStringLiteral.append ("\\\"");
00405         ++pkcIterator;
00406         continue;
00407       }
00408       if ( *pkcIterator != cQuoteCharacter )
00409       {
00410         yCollapsedStringLiteral.append (1, *pkcIterator);
00411         ++pkcIterator;
00412       }
00413       else if ( *(pkcIterator + 1) == cQuoteCharacter )
00414       {
00415         //
00416         //  Preserves the symbol {quote_symbol} as is.
00417         //
00418         yCollapsedStringLiteral.append (2, cQuoteCharacter);
00419         pkcIterator += 2;
00420       }
00421       else
00422       {
00423         //
00424         //  Eats quote/double-quote character.
00425         //
00426         ++pkcIterator;
00427 
00428         //
00429         //  If  there  is  anything  after  quote,   then  it  is  a  multipart
00430         //  string_literal.  The  only thing that can be between string_literal
00431         //  parts, is {separator}+. Where separator is defined as:
00432         //
00433         //    {separator} ::= ({comment}|{space}|{newline}|{tabulator})+
00434         //
00435         if ( *pkcIterator )
00436         {
00437           gBetweenParts = true;
00438           while ( gBetweenParts )
00439           {
00440             switch (*pkcIterator)
00441             {
00442               case '-':
00443               {
00444                 //
00445                 //  Eat {comment} terminal.
00446                 //
00447                 ++pkcIterator;
00448                 while ( *pkcIterator != '\n' ) ++pkcIterator;
00449                 break;
00450               }
00451               case ' ':
00452               case '\t':
00453               case '\n':
00454               {
00455                 //
00456                 //  Eat {tabulator}, {space} and {newline}.
00457                 //
00458                 ++pkcIterator;
00459                 break;
00460               }
00461               case '\'':
00462               {
00463                 //
00464                 //  Exit loop whenever a new string_literal part begins.
00465                 //
00466                 gBetweenParts = false;
00467                 ++pkcIterator;
00468                 break;
00469               }
00470               default:
00471               {
00472                 throw TErrorException ("bad charater between string_literal parts", __FILE__, __LINE__);
00473               }
00474             }
00475           }
00476         }
00477       }
00478     }
00479   }
00480   return yCollapsedStringLiteral;
00481   
00482 }  // collapseStringLiteral()
00483 
00484 
00485 void TApplication::handleTarget (const mpcl::text::TString& rkySOURCE_TEXT)
00486 {
00487 
00488   using mpcl::text::TString;
00489 
00490   //
00491   //  Saves the line number for the embedded introducer.
00492   //
00493   zEmbeddedIntroducerLine = yylineno;
00494   if ( !yCfgTarget.empty() )
00495   {
00496     //
00497     //  Loads CDML file.
00498     //
00499     loadCodeGenerator (yCfgTarget);
00500   }
00501   else
00502   {
00503     //
00504     //  If there is no global target, then it loads the proper target.
00505     //
00506 
00507     size_t    zEnd;
00508     size_t    zBegin = 0;
00509     TString   yText (rkySOURCE_TEXT);
00510 
00511     //
00512     //  Remove one-line comments from text.
00513     //
00514     while ( TString::npos != (zBegin = yText.find ("//", zBegin)) )
00515     {
00516       zEnd = yText.find ('\n', zBegin);
00517       if ( TString::npos == zEnd )
00518       {
00519         //
00520         //  Warning:  This is a fatal error condition.
00521         //
00522         zBegin = zEnd;
00523       }
00524       else
00525       {
00526         yText.erase (zBegin, (zEnd - zBegin) + 1);
00527       }
00528     }
00529     
00530     //
00531     //  Extract target.
00532     //
00533     zBegin = yText.find ('"') + std::strlen ("UESQL::") + 1;
00534     zEnd   = yText.find ('"', zBegin);
00535     yText  = yText.substr (zBegin, zEnd - zBegin);
00536     if ( yText == "default" )
00537     {
00538       if ( gCfgSyntaxCheckOnly )
00539       {
00540         //
00541         //  Loads identity CDML file.
00542         //
00543         loadCodeGenerator ("base-identity");
00544       }
00545       else
00546       {
00547         throw TFatalException ("there is no target");
00548       }
00549     }
00550     else
00551     {
00552       //
00553       //  Loads CDML file.
00554       //
00555       loadCodeGenerator (yText);
00556     }
00557   }
00558   if ( ptRuntimeParametersMap->empty() )
00559   {
00560     //
00561     //  Copies the variables from current pattern based code generator onto
00562     //  runtime parameters map. Before that, variables are preprocessed, to
00563     //  substitute entity values.
00564     //
00565     tTargetToCodeGeneratorMap [yCurrentTarget]->preprocessVariables();
00566     *ptRuntimeParametersMap = tTargetToCodeGeneratorMap [yCurrentTarget]->variables();
00567   }
00568   
00569 }  // handleTarget()
00570 
00571 
00572 int TApplication::identifyToken (const char* pkcSOURCE_TEXT, unsigned int uiPERIOD_COUNT)
00573 {
00574 
00575   int       iToken;
00576   TString   yToken (pkcSOURCE_TEXT);
00577 
00578   yToken.uppercase();
00579   if ( uiPERIOD_COUNT )
00580   {
00581     iToken               = splitToken (uiPERIOD_COUNT);
00582     yylval.yCode         = yToken;
00583     yylval.yOriginalText = pkcSOURCE_TEXT;
00584     switch (iToken)
00585     {
00586       case SECOND_LEVEL_IDENTIFIER:
00587       {
00588         pushTokenName ("SECOND_LEVEL_IDENTIFIER");
00589         break;
00590       }
00591       case THIRD_LEVEL_IDENTIFIER:
00592       {
00593         pushTokenName ("THIRD_LEVEL_IDENTIFIER");
00594         break;
00595       }
00596       case FOURTH_LEVEL_IDENTIFIER:
00597       {
00598         pushTokenName ("FOURTH_LEVEL_IDENTIFIER");
00599         break;
00600       }
00601     }
00602   }
00603   else
00604   {
00605     TMap<TString, long int>::const_iterator   I (tReservedWordMap.find (yToken));
00606 
00607     if ( I != tReservedWordMap.end() )
00608     {
00609       iToken = I->second;
00610       pushTokenName ("RW_" + yToken);
00611     }
00612     else
00613     {
00614       iToken               = IDENTIFIER_BODY;
00615       yylval.yCode         = yToken;
00616       yylval.yOriginalText = pkcSOURCE_TEXT;
00617       pushTokenName ("IDENTIFIER_BODY");
00618     }
00619   }
00620   printDebugInformation();
00621   return iToken;
00622 
00623 }  // identifyToken()
00624 
00625 
00626 void TApplication::initCodeParameters (void)
00627 {
00628 
00629   TVariableString   yTarget (yCurrentTarget, TVariableString::eOptional);
00630 
00631   //
00632   //  Initiate code parameters from CDML variables.
00633   //
00634   tCodeParametersMap.clear();
00635   tCodeParametersMap.bind ("__target__", yTarget);
00636   if ( !ptRuntimeParametersMap->empty() )
00637   {
00638     TStringToVariableMap::const_iterator   ktIter = ptRuntimeParametersMap->begin();
00639     TStringToVariableMap::const_iterator   ktEnd  = ptRuntimeParametersMap->end();
00640     
00641     for (; ( ktIter != ktEnd ) ;++ktIter)
00642     {
00643       tCodeParametersMap.insert (*ktIter);
00644     }
00645   }
00646 
00647 }  // initCodeParameters()
00648 
00649 
00650 void TApplication::initialize (void)
00651 {
00652 
00653   //
00654   //  Create options with their default values.
00655   //
00656   tConfigProcessor.addOption ("cdml-path",                    "m", PKGDATADIR);
00657   tConfigProcessor.addOption ("complementary-files",          "c");
00658   tConfigProcessor.addOption ("complementary-file-directory", "w", ".");
00659   tConfigProcessor.addOption ("debug",                        "d", "0");
00660   tConfigProcessor.addOption ("entry-sql",                    "e");
00661   tConfigProcessor.addOption ("full-sql",                     "f");
00662   tConfigProcessor.addOption ("help",                         "h");
00663   tConfigProcessor.addOption ("intermediate-sql",             "i");
00664   tConfigProcessor.addOption ("language",                     "a", "c++");
00665   tConfigProcessor.addOption ("line-directives",              "l");
00666   tConfigProcessor.addOption ("main-file",                    "n");
00667   tConfigProcessor.addOption ("output-cdml",                  "u");
00668   tConfigProcessor.addOption ("output-cdml-skel",             "s");
00669   tConfigProcessor.addOption ("parameters",                   "p");
00670   tConfigProcessor.addOption ("relaxed-syntax",               "r");
00671   tConfigProcessor.addOption ("syntax-check-only",            "y");
00672   tConfigProcessor.addOption ("target",                       "t", "");
00673   tConfigProcessor.addOption ("version",                      "V");
00674 
00675   //
00676   //  Processes configuration and gets arguments, if any.
00677   //
00678   tConfigProcessor.processOptions();
00679   
00680   //
00681   //  Gets options values.
00682   //
00683   yCfgCdmlPath                   = tConfigProcessor ["cdml-path"].getValue();
00684   yCfgComplementaryFileDirectory = tConfigProcessor ["complementary-file-directory"].getValue();
00685   yCfgLanguage                   = tConfigProcessor ["language"].getValue();
00686   yCfgTarget                     = tConfigProcessor ["target"].getValue();
00687   uiCfgDebug                     = (unsigned int) atoi (tConfigProcessor ["debug"].getValue().c_str());
00688   gCfgComplementaryFiles         = ( tConfigProcessor ["complementary-files"].isAtCmdLine() );
00689   gCfgHelp                       = ( tConfigProcessor ["help"].isAtCmdLine() );
00690   gCfgLineDirectives             = ( tConfigProcessor ["line-directives"].isAtCmdLine() );
00691   gCfgMainFile                   = ( tConfigProcessor ["main-file"].isAtCmdLine() );
00692   gCfgOutputCdml                 = ( tConfigProcessor ["output-cdml"].isAtCmdLine() );
00693   gCfgOutputCdmlSkel             = ( tConfigProcessor ["output-cdml-skel"].isAtCmdLine() );
00694   gCfgParameters                 = ( tConfigProcessor ["parameters"].isAtCmdLine() );
00695   gCfgSyntaxCheckOnly            = ( tConfigProcessor ["syntax-check-only"].isAtCmdLine() );
00696   gCfgVersion                    = ( tConfigProcessor ["version"].isAtCmdLine() );
00697   
00698   //
00699   //  Clears conformance level set.
00700   //  Sets strict SQL 92 syntax if no relaxing option has passed.
00701   //
00702   tInvariantVerifier.clearConformanceLevelSet();
00703   if ( !tConfigProcessor ["relaxed-syntax"].isAtCmdLine() )
00704   {
00705     tInvariantVerifier.addConformanceLevel (eSTRICT_SQL_92);
00706   }
00707 
00708   //
00709   //  Selects from the three SQL levels of conformance:
00710   //
00711   //    Full SQL conformance
00712   //    Intermediate SQL conformance
00713   //    Entry SQL conformance
00714   //
00715   //  And defaults to Full SQL Level if there is no user selection.
00716   //
00717   if ( tConfigProcessor ["entry-sql"].isAtCmdLine() )
00718   {
00719     tInvariantVerifier.addConformanceLevel (eFULL_SQL_LEVEL);
00720     tInvariantVerifier.addConformanceLevel (eINTERMEDIATE_SQL_LEVEL);
00721     tInvariantVerifier.addConformanceLevel (eENTRY_SQL_LEVEL);
00722   }
00723   else if ( tConfigProcessor ["intermediate-sql"].isAtCmdLine() )
00724   {
00725     tInvariantVerifier.addConformanceLevel (eFULL_SQL_LEVEL);
00726     tInvariantVerifier.addConformanceLevel (eINTERMEDIATE_SQL_LEVEL);
00727   }
00728   else
00729   {
00730     tInvariantVerifier.addConformanceLevel (eFULL_SQL_LEVEL);
00731   }
00732   
00733 }  // initialize()
00734 
00735 
00736 void TApplication::loadCodeGenerator (const mpcl::text::TString& rkyTARGET)
00737 {
00738 
00739   using mpcl::system::tSystem;
00740   using std::vector;
00741   
00742   gReusingTarget =
00743     ( tTargetToCodeGeneratorMap.end() != tTargetToCodeGeneratorMap.find (rkyTARGET) );
00744   if ( !gReusingTarget )
00745   {
00746     TString                       yCdmlPath;
00747     QTPatternBasedCodeGenerator   qtCodeGenerator;
00748     
00749     //
00750     //  Composes  the  path as the  base  path concatenated with  the  selected
00751     //  language, and the base path only.
00752     //
00753     yCdmlPath =
00754       yCfgCdmlPath + tSystem.getDirectorySeparator() + yCfgLanguage +
00755       tSystem.getPathSeparator()                                    +
00756       yCfgCdmlPath                                                  ;
00757 
00758     //
00759     //  Creates the pattern-based code-generator from the former path.
00760     //
00761     qtCodeGenerator =
00762       new TPatternBasedCodeGenerator (rkyTARGET + ".cdmlo", yCdmlPath);
00763 
00764     //
00765     //  Registers the new code-generator.
00766     //
00767     tTargetToRuntimeParametersMapMap.bind (rkyTARGET, TStringToVariableMap());
00768     tTargetToCodeGeneratorMap.bind        (rkyTARGET, qtCodeGenerator);
00769   }
00770   yCurrentTarget         = rkyTARGET;
00771   ptRuntimeParametersMap = &tTargetToRuntimeParametersMapMap [yCurrentTarget];
00772 
00773 }  // loadCodeGenerator()
00774 
00775 
00776 void TApplication::openFiles ( const mpcl::text::TString& rkyINPUT_FILE_NAME  ,
00777                                const mpcl::text::TString& rkyOUTPUT_FILE_NAME )
00778 {
00779 
00780   using mpcl::text::Format;
00781   using std::fopen;
00782 
00783   yyin  = NULL;
00784   yyout = NULL;
00785 
00786   //
00787   //  Open input file name.
00788   //
00789   if ( rkyINPUT_FILE_NAME == "-" )
00790   {
00791     yCurrentInputFileName = "stdin";
00792     yyin                  = stdin;
00793   }
00794   else
00795   {
00796     yCurrentInputFileName = rkyINPUT_FILE_NAME;
00797     yyin                  = fopen (rkyINPUT_FILE_NAME.c_str(), "r");
00798     if ( yyin == NULL )
00799     {
00800       TString   yMessage;
00801 
00802       yMessage = Format ("could not read file '%s'", rkyINPUT_FILE_NAME.c_str());
00803       throw TFatalException (yMessage);
00804     }
00805   }
00806 
00807   if ( !gCfgSyntaxCheckOnly )
00808   {
00809     //
00810     //  Opens output file name.
00811     //
00812     if ( rkyOUTPUT_FILE_NAME == "-" )
00813     {
00814       yyout = stdout;
00815     }
00816     else
00817     {
00818       yyout = fopen (rkyOUTPUT_FILE_NAME.c_str(), "w");
00819       if ( yyout == NULL )
00820       {
00821         TString   yMessage;
00822 
00823         yMessage = Format ("could not write file '%s'", rkyOUTPUT_FILE_NAME.c_str());
00824         throw TFatalException (yMessage);
00825       }
00826     }
00827   }
00828 
00829 }  // openFiles()
00830 
00831 
00832 void TApplication::outputCode (const char* pkcSOURCE_TEXT, size_t zLENGTH)
00833 {
00834 
00835   if ( zLENGTH )
00836   {
00837     yOutputCode.append (pkcSOURCE_TEXT, zLENGTH);
00838   }
00839   else
00840   {
00841     yOutputCode.append (pkcSOURCE_TEXT);
00842   }
00843 
00844 }  // outputCode()
00845 
00846 
00847 int TApplication::splitToken (unsigned int uiPERIOD_COUNT)
00848   throw (TFatalException)
00849 {
00850 
00851   using mpcl::text::Uppercase;
00852 
00853   int           iToken;
00854   const char*   pkcPeriod;
00855   const char*   pkcText = yytext;
00856   
00857   switch (uiPERIOD_COUNT)
00858   {
00859     case 3:
00860     {
00861       iToken                   = FOURTH_LEVEL_IDENTIFIER;
00862       pkcPeriod                = strchr (pkcText, '.');
00863       yylval.yFourthIdentifier = Uppercase (TString (pkcText, (pkcPeriod - pkcText)));
00864       pkcText                  = pkcPeriod + 1;
00865       pkcPeriod                = strchr (pkcText, '.');
00866       yylval.yThirdIdentifier  = Uppercase (TString (pkcText, (pkcPeriod - pkcText)));
00867       pkcText                  = pkcPeriod + 1;
00868       pkcPeriod                = strchr (pkcText, '.');
00869       yylval.ySecondIdentifier = Uppercase (TString (pkcText, (pkcPeriod - pkcText)));
00870       yylval.yFirstIdentifier  = Uppercase (TString (pkcPeriod + 1));
00871       break;
00872     }
00873     case 2:
00874     {
00875       iToken                   = THIRD_LEVEL_IDENTIFIER;
00876       pkcPeriod                = strchr (pkcText, '.');
00877       yylval.yThirdIdentifier  = Uppercase (TString (pkcText, (pkcPeriod - pkcText)));
00878       pkcText                  = pkcPeriod + 1;
00879       pkcPeriod                = strchr (pkcText, '.');
00880       yylval.ySecondIdentifier = Uppercase (TString (pkcText, (pkcPeriod - pkcText)));
00881       yylval.yFirstIdentifier  = Uppercase (TString (pkcPeriod + 1));
00882       break;
00883     }
00884     case 1:
00885     {
00886       iToken                   = SECOND_LEVEL_IDENTIFIER;
00887       pkcPeriod                = strchr (pkcText, '.');
00888       yylval.ySecondIdentifier = Uppercase (TString (pkcText, (pkcPeriod - pkcText)));
00889       yylval.yFirstIdentifier  = Uppercase (TString (pkcPeriod + 1));
00890       break;
00891     }
00892     default:
00893     {
00894       iToken = 0;
00895       throw TFatalException ("bad token", __FILE__, __LINE__);
00896     }
00897   }
00898   return iToken;
00899 
00900 }  // splitToken()
00901 
00902 
00903 int TApplication::start (void)
00904 {
00905 
00906   using mpcl::system::tSystem;
00907   using mpcl::text::Format;
00908   using std::cout;
00909   using std::endl;
00910   using std::fwrite;
00911   using std::strlen;
00912 
00913   TString              yInputFile;
00914   TString              yOutputFile;
00915   TString::size_type   zFragmentPosition;
00916   int                  iExitCode = 1;
00917   bool                 gContinue = true;
00918 
00919   if ( gContinue && gCfgVersion )
00920   {
00921     cout << release() << endl;
00922     gContinue = false;
00923   }
00924   if ( gContinue && gCfgParameters )
00925   {
00926     printParameters();
00927     gContinue = false;
00928   }
00929   if ( gContinue && gCfgHelp )
00930   {
00931     printUsage();
00932     gContinue = false;
00933   }
00934   if ( gContinue )
00935   {
00936     switch (uiCfgDebug)
00937     {
00938       case 0:
00939       case 1:
00940       {
00941         break;
00942       }
00943       case 2:
00944       {
00945         yydebug = 1;
00946         break;
00947       }
00948       default:
00949       {
00950         throw TFatalException ("bad value for debug level");
00951       }
00952     }
00953   }
00954   
00955   //
00956   //  Checks number of arguments.
00957   //
00958   if ( tConfigProcessor.numberOfArguments() > 1 )
00959   {
00960     throw TFatalException ("wrong number of arguments");
00961   }
00962   if ( gContinue )
00963   {
00964     if ( gCfgOutputCdml )
00965     {
00966       if ( yCfgTarget.empty() )
00967       {
00968         throw TFatalException ("there is no target");
00969       }
00970       else
00971       {
00972         loadCodeGenerator (yCfgTarget);
00973         cout << *tTargetToCodeGeneratorMap [yCfgTarget];
00974         iExitCode = 0;
00975       }
00976     }
00977     else if ( gCfgOutputCdmlSkel )
00978     {
00979       if ( yCfgTarget.empty() )
00980       {
00981         throw TFatalException ("there is no target");
00982       }
00983       else
00984       {
00985         loadCodeGenerator (yCfgTarget);
00986         tTargetToCodeGeneratorMap [yCfgTarget]->clearCode();
00987         cout << *tTargetToCodeGeneratorMap [yCfgTarget];
00988         iExitCode = 0;
00989       }
00990     }
00991     else if ( gCfgComplementaryFiles )
00992     {
00993       //
00994       //  Creates complementary files (if any).
00995       //
00996       if ( yCfgTarget.empty() )
00997       {
00998         throw TFatalException ("there is no target");
00999       }
01000       else
01001       {
01002         //
01003         //  Loads the proper target and its runtime parameters.
01004         //
01005         handleTarget (yCfgTarget);
01006         createComplementaryFiles();
01007         iExitCode = 0;
01008       }
01009     }
01010     else
01011     {
01012       for (unsigned int I = 0; ( I < tConfigProcessor.numberOfArguments() ) ;++I)
01013       {
01014         yInputFile         = tConfigProcessor.argumentValue (I);
01015         yOutputFile        = yInputFile;
01016 
01017         //
01018         //  Compute output file name stripping '.uesql' from input file name.
01019         //
01020         zFragmentPosition = yOutputFile.rfind (_pkcExtension);
01021         if ( zFragmentPosition == std::string::npos )
01022         {
01023           TString   yMessage;
01024 
01025           yMessage = Format ("input file has no '%s' in its name", _pkcExtension);
01026           throw TFatalException (yMessage);
01027         }
01028         else
01029         {
01030           yOutputFile.erase (zFragmentPosition, strlen (_pkcExtension));
01031         }
01032 
01033         //
01034         //  Remove path from output file name.
01035         //
01036         zFragmentPosition = yOutputFile.rfind (tSystem.getDirectorySeparator());
01037         if ( zFragmentPosition != std::string::npos )
01038         {
01039           yOutputFile.erase (0, zFragmentPosition + 1);
01040         }
01041         openFiles (yInputFile, yOutputFile);
01042 
01043         //
01044         //  Compile each file.
01045         //
01046         try
01047         {
01048           iExitCode = yyparse();
01049         }
01050         catch (const mpcl::invariant::TViolationException& rktEXCEPTION)
01051         {
01052           const char*   pkcViolatedLevel;
01053           TString       yMessage;
01054         
01055           switch (rktEXCEPTION.violatedConformanceLevel())
01056           {
01057             //
01058             //  Strict SQL 92 syntax checking.
01059             //    The basic syntax rules.
01060             //
01061             //  Full SQL (High conformance).
01062             //    The complete database language specified in this
01063             //    International Standard.
01064             //
01065             //  Intermediate SQL (Intermediate conformance).
01066             //    Intermediate SQL is a subset of Full SQL as
01067             //    specified in the Leveling Rules.
01068             //
01069             //  Entry SQL (Low conformance).
01070             //    Entry SQL is a subset of Intermediate SQL as spec-
01071             //    ified in the Leveling Rules.
01072             //
01073             case eSTRICT_SQL_92:
01074             {
01075               pkcViolatedLevel = "Basic SQL-92 syntax violated";
01076               break;
01077             }
01078             case eFULL_SQL_LEVEL:
01079             {
01080               pkcViolatedLevel = "Full SQL level violated";
01081               break;
01082             }
01083             case eINTERMEDIATE_SQL_LEVEL:
01084             {
01085               pkcViolatedLevel = "Intermediate SQL level violated";
01086               break;
01087             }      
01088             case eENTRY_SQL_LEVEL:
01089             {
01090               pkcViolatedLevel = "Entry SQL level violated";
01091               break;
01092             }
01093           }
01094           yMessage = Format ( "%s: %d: near '%s'; %s: %s\n"              ,
01095                               yInputFile.c_str()                         ,
01096                               yylineno                                   ,
01097                               yLastToken.c_str()                         ,
01098                               pkcViolatedLevel                           ,
01099                               rktEXCEPTION.specificDescription().c_str() );
01100           throw TFatalException (yMessage);
01101         }
01102         if ( compilationFailed() )
01103         {
01104           iExitCode = 1;
01105           if ( !gCfgSyntaxCheckOnly && ( yyout != stdout ) )
01106           {
01107             //
01108             //  Removes output file due to be not a successful compilation.
01109             //
01110             std::remove (yOutputFile.c_str());
01111           }
01112         }
01113 //       gCompilationOk = ( iExitCode == 0 );
01114 
01115         if ( !gCfgSyntaxCheckOnly )
01116         {
01117           //
01118           //  If fwrite() returns 1, then it means that it could write one item
01119           //  of yCode.length() bytes.
01120           //
01121       
01122           //
01123           //  Write prefix output code.
01124           //
01125           if ( !yPrefixOutputCode.empty() )
01126           {
01127             if ( fwrite (yPrefixOutputCode.c_str(), yPrefixOutputCode.length(), 1, yyout) != 1 )
01128             {
01129               throw TFatalException ("could not write output file");
01130             }
01131           }
01132       
01133           //
01134           //  Write body output code.
01135           //
01136           if ( fwrite (yOutputCode.c_str(), yOutputCode.length(), 1, yyout) != 1 )
01137           {
01138             throw TFatalException ("could not write output file");
01139           }
01140 
01141           //
01142           //  Write postfix output code.
01143           //
01144           if ( !yPostfixOutputCode.empty() )
01145           {
01146             if ( fwrite (yPostfixOutputCode.c_str(), yPostfixOutputCode.length(), 1, yyout) != 1 )
01147             {
01148               throw TFatalException ("could not write output file");
01149             }
01150           }
01151         }
01152 
01153         //
01154         //  Finally it closes input and output files.
01155         //
01156         closeFiles();
01157       }
01158       if ( !gCfgSyntaxCheckOnly && !gCfgMainFile )
01159       {
01160         //
01161         //  Creates complementary files (if any).
01162         //
01163         createComplementaryFiles();
01164       }
01165     }
01166   }
01167   return iExitCode;
01168 
01169 }  // start()
01170 
01171 
01172 //
01173 //  S E L E C T O R S
01174 //
01175 
01176 void TApplication::createComplementaryFiles (void) const
01177 {
01178 
01179   using mpcl::system::tSystem;
01180   using mpcl::text::codegen::TVariableString;
01181   using std::basic_ofstream;
01182   
01183   std::basic_ofstream<char>                          tOutputOfstream;
01184   TStringToVariableMap::const_iterator               ktVariableIter;
01185   TStringToVariableMap::const_iterator               ktVariableEnd;
01186   TTargetToRuntimeParametersMapMap::const_iterator   ktTargetIter;
01187   TTargetToRuntimeParametersMapMap::const_iterator   ktTargetEnd;
01188   TString                                            yTargetDirectory;
01189 
01190   ktTargetIter     = tTargetToRuntimeParametersMapMap.begin();
01191   ktTargetEnd      = tTargetToRuntimeParametersMapMap.end();
01192   yTargetDirectory = yCfgComplementaryFileDirectory + tSystem.getDirectorySeparator();
01193   for (; ( ktTargetIter != ktTargetEnd ) ;++ktTargetIter)
01194   {
01195     ktVariableIter = ktTargetIter->second.begin();
01196     ktVariableEnd  = ktTargetIter->second.end();
01197     for (; ( ktVariableIter != ktVariableEnd ) ;++ktVariableIter)
01198     {
01199       if ( ktVariableIter->second.type() == TVariableString::eFile )
01200       {
01201         tOutputOfstream.open ((yTargetDirectory + ktVariableIter->first).c_str());
01202         if ( !tOutputOfstream.good() )
01203         {
01204           throw TFatalException ("could not write complementary file");
01205         }
01206         else
01207         {
01208           tOutputOfstream << ktVariableIter->second;
01209           tOutputOfstream.close();
01210         }
01211       }
01212     }
01213   }
01214 
01215 }  // createComplementaryFiles()
01216 
01217 
01218 mpcl::text::TString TApplication::
01219 debugDescription (void) const
01220 {
01221 
01222   return mpcl::text::Format ( "%s(%d): parsed terminal '%s' as [%s]\n" ,
01223                               yCurrentInputFileName.c_str()            ,
01224                               yylineno                                 ,
01225                               yLastToken.c_str()                       ,
01226                               yytext                                   );
01227 
01228 }  // debugDescription()
01229 
01230 
01231 mpcl::text::TString TApplication::
01232 getClauseCode (const char* pkcINSTRUCTION_NAME, const char* pkcCLAUSE_NAME)
01233 {
01234 
01235   using mpcl::text::codegen::TClauseBodyString;
01236   using mpcl::text::codegen::TInstructionBody;
01237   using mpcl::util::collection::TMap;
01238   using std::cerr;
01239   using std::endl;
01240 
01241   typedef
01242     TMap<TString, const TClauseBodyString*>
01243     TStringToClauseBodyString;
01244   
01245   TStringToClauseBodyString::const_iterator   I;
01246   bool                                        gParameterCheck;
01247   TStringToClauseBodyString::const_iterator   ktEnd;
01248   TString*                                    pyTargetParameterValue;
01249   TStringToClauseBodyString                   tParameterToCodeMap;
01250   TString                                     yTargetParameter;
01251   TString                                     yCode;
01252   TInstructionBody&                           rtInstructionBody ((*tTargetToCodeGeneratorMap [yCurrentTarget]) [pkcINSTRUCTION_NAME]);
01253 
01254   if ( uiCfgDebug > 0 )
01255   {
01256     cerr << programFileName() << ": writing code for <instruction, clause> pair: "
01257          << pkcINSTRUCTION_NAME << ", " << pkcCLAUSE_NAME << endl;
01258     if ( uiCfgDebug > 1 )
01259     {
01260       cerr << programFileName()
01261            << ": code:\n"
01262            << rtInstructionBody.clauseBody (pkcCLAUSE_NAME).instantiate()
01263            << endl;
01264     }
01265   }
01266 
01267   gParameterCheck = rtInstructionBody.clauseTag (pkcCLAUSE_NAME).mustCheckParameters();
01268   yCode           = rtInstructionBody.clauseBody (pkcCLAUSE_NAME).instantiate (tCodeParametersMap, gParameterCheck);
01269 
01270   //
01271   //  Update targets for the other targeted clauses.
01272   //
01273   tParameterToCodeMap = rtInstructionBody.targetedVariablesForClause (pkcCLAUSE_NAME);
01274   I                   = tParameterToCodeMap.begin();
01275   ktEnd               = tParameterToCodeMap.end();
01276   for (; ( I != ktEnd ) ;++I)
01277   {
01278     //
01279     //  First obtain the parameter name.
01280     //
01281     yTargetParameter = I->first;
01282 
01283     //
01284     //  Then build an auxiliary clause body with the
01285     //  parameter name. Next instantiate it (substitute)
01286     //  with runtime-code-parameters (if any).
01287     //
01288     yTargetParameter = TClauseBodyString (yTargetParameter).instantiate (*ptRuntimeParametersMap, false);
01289 
01290     //
01291     //  Updates the value of target parameter value on
01292     //  runtime-code-parameters-map and on code-parameters-map,
01293     //  with the instantiation of the former clause.
01294     //
01295     pyTargetParameterValue  = &((*ptRuntimeParametersMap) [yTargetParameter]);
01296     *pyTargetParameterValue = (I->second)->instantiate (tCodeParametersMap, false);
01297     tCodeParametersMap [yTargetParameter] = *pyTargetParameterValue;
01298   }
01299   return yCode;
01300 
01301 }  // getClauseCode()
01302 
01303 
01304 mpcl::text::TString TApplication::
01305 getLineDirective (unsigned int uiLINE_NUMBER) const
01306 {
01307 
01308   return mpcl::text::Format ("#line %u \"%s\"\n", uiLINE_NUMBER, yCurrentInputFileName.c_str());
01309 
01310 }  // getLineDirective()
01311 
01312 
01313 void TApplication::handleCompilerError (const char* pkcMESSAGE)
01314 {
01315 
01316   using mpcl::text::Format;
01317   using std::cerr;
01318 
01319   TString   yMessage;
01320 
01321   setCompilationFailed();
01322   yMessage = Format ("near '%s' ('%s'); %s", yLastToken.c_str(), yytext, pkcMESSAGE);
01323   cerr << TErrorException (yMessage.c_str(), yCurrentInputFileName.c_str(), yylineno);
01324 
01325 }  // handleCompilerError()
01326 
01327 
01328 bool TApplication::isReusingTarget (void) const
01329 {
01330 
01331   return gReusingTarget;
01332 
01333 }  // isReusingTarget()
01334 
01335 
01336 void TApplication::printParameters (void) const
01337 {
01338 
01339   using std::cout;
01340   using std::endl;
01341 
01342   cout << "cdml-path:                    " << yCfgCdmlPath                   << endl;
01343   cout << "complementary-files:          " << gCfgComplementaryFiles         << endl;
01344   cout << "complementary-file-directory: " << yCfgComplementaryFileDirectory << endl;
01345   cout << "debug:                        " << uiCfgDebug                     << endl;
01346   cout << "help:                         " << gCfgHelp                       << endl;
01347   cout << "language:                     " << yCfgLanguage                   << endl;
01348   cout << "line-directives:              " << gCfgLineDirectives             << endl;
01349   cout << "output-cdml:                  " << gCfgOutputCdml                 << endl;
01350   cout << "output-cdml-skel:             " << gCfgOutputCdmlSkel             << endl;
01351   cout << "parameters:                   " << gCfgParameters                 << endl;
01352   cout << "syntax-check-only:            " << gCfgSyntaxCheckOnly            << endl;
01353   cout << "target:                       " << yCfgTarget                     << endl;
01354   cout << "version:                      " << gCfgVersion                    << endl;
01355 
01356 }  // printParameters()
01357 
01358 
01359 void TApplication::
01360 printUsage (void) const
01361 {
01362 
01363   using mpcl::text::Format;
01364   
01365   TString   yUsageInfo;
01366   
01367   yUsageInfo = Format ( "%s Universal Embedded SQL Compiler Version %s\n"
01368                         "Copyright (c) Rafael Jesus Alcantara Perez, 1996-2003.\n"
01369                         "Usage:  %s [OPTION]... [FILE]...\n\n"
01370                         "Overall Options:\n"
01371                         "  -%s, --%s=CDML_PATH (%s)\n"
01372                         "  -%s, --%s=DIRECTORY (%s)\n"
01373                         "  -%s, --%s\n"
01374                         "  -%s, --%s={0, 1, 2} (0)\n"
01375                         "  -%s, --%s={c++, java} (c++)\n"
01376                         "  -%s, --%s\n"
01377                         "  -%s, --%s\n"
01378                         "  -%s, --%s=TARGET_PLATFORM\n\n"
01379                         "Syntax checking and SQL-92 Conformance Level selection:\n"
01380                         "  -%s, --%s (default)\n"
01381                         "  -%s, --%s\n"
01382                         "  -%s, --%s\n"
01383                         "  -%s, --%s\n"
01384                         "  -%s, --%s\n\n"
01385                         "Informative output:\n"
01386                         "  -%s, --%s\n"
01387                         "  -%s, --%s (need target)\n"
01388                         "  -%s, --%s (need target)\n"
01389                         "  -%s, --%s\n"
01390                         "  -%s, --%s\n\n"                                                    ,
01391                         name().c_str()                                                       ,
01392                         release().c_str()                                                    ,
01393                         programFileName().c_str()                                            ,
01394                         tConfigProcessor ["cdml-path"].shortcut().c_str()                    ,
01395                         tConfigProcessor ["cdml-path"].name().c_str()                        ,
01396                         tConfigProcessor ["cdml-path"].getValue().c_str()                    ,
01397                         tConfigProcessor ["complementary-file-directory"].shortcut().c_str() ,
01398                         tConfigProcessor ["complementary-file-directory"].name().c_str()     ,
01399                         tConfigProcessor ["complementary-file-directory"].getValue().c_str() ,
01400                         tConfigProcessor ["complementary-files"].shortcut().c_str()          ,
01401                         tConfigProcessor ["complementary-files"].name().c_str()              ,
01402                         tConfigProcessor ["debug"].shortcut().c_str()                        ,
01403                         tConfigProcessor ["debug"].name().c_str()                            ,
01404                         tConfigProcessor ["language"].shortcut().c_str()                     ,
01405                         tConfigProcessor ["language"].name().c_str()                         ,
01406                         tConfigProcessor ["line-directives"].shortcut().c_str()              ,
01407                         tConfigProcessor ["line-directives"].name().c_str()                  ,
01408                         tConfigProcessor ["main-file"].shortcut().c_str()                    ,
01409                         tConfigProcessor ["main-file"].name().c_str()                        ,
01410                         tConfigProcessor ["target"].shortcut().c_str()                       ,
01411                         tConfigProcessor ["target"].name().c_str()                           ,
01412                         tConfigProcessor ["full-sql"].shortcut().c_str()                     ,
01413                         tConfigProcessor ["full-sql"].name().c_str()                         ,
01414                         tConfigProcessor ["intermediate-sql"].shortcut().c_str()             ,
01415                         tConfigProcessor ["intermediate-sql"].name().c_str()                 ,
01416                         tConfigProcessor ["entry-sql"].shortcut().c_str()                    ,
01417                         tConfigProcessor ["entry-sql"].name().c_str()                        ,
01418                         tConfigProcessor ["relaxed-syntax"].shortcut().c_str()               ,
01419                         tConfigProcessor ["relaxed-syntax"].name().c_str()                   ,
01420                         tConfigProcessor ["syntax-check-only"].shortcut().c_str()            ,
01421                         tConfigProcessor ["syntax-check-only"].name().c_str()                ,
01422                         tConfigProcessor ["help"].shortcut().c_str()                         ,
01423                         tConfigProcessor ["help"].name().c_str()                             ,
01424                         tConfigProcessor ["output-cdml"].shortcut().c_str()                  ,
01425                         tConfigProcessor ["output-cdml"].name().c_str()                      ,
01426                         tConfigProcessor ["output-cdml-skel"].shortcut().c_str()             ,
01427                         tConfigProcessor ["output-cdml-skel"].name().c_str()                 ,
01428                         tConfigProcessor ["parameters"].shortcut().c_str()                   ,
01429                         tConfigProcessor ["parameters"].name().c_str()                       ,
01430                         tConfigProcessor ["version"].shortcut().c_str()                      ,
01431                         tConfigProcessor ["version"].name().c_str()                          );
01432   std::cout << yUsageInfo;
01433   
01434 }  // printUsage()
01435 
01436 
01437 void TApplication::require (long int liREQUERIMENT_IDENTIFIER...) const
01438 {
01439 
01440   va_list   tVa_list;
01441 
01442   va_start (tVa_list, liREQUERIMENT_IDENTIFIER);
01443   tInvariantVerifier.requireList (liREQUERIMENT_IDENTIFIER, tVa_list);
01444   va_end (tVa_list);
01445 
01446 }  // require()

Generated on Mon Oct 13 02:40:10 2003 for UESQLC by doxygen1.2.18