8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 04:43:03 +01:00
firebird-mirror/src/gpre/gpre.cpp
2004-10-30 05:30:08 +00:00

2905 lines
70 KiB
C++

//____________________________________________________________
//
// PROGRAM: Preprocessor
// MODULE: gpre.cpp
// DESCRIPTION: Main line routine
//
// The contents of this file are subject to the Interbase Public
// License Version 1.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy
// of the License at http://www.Inprise.com/IPL.html
//
// Software distributed under the License is distributed on an
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
// or implied. See the License for the specific language governing
// rights and limitations under the License.
//
// The Original Code was created by Inprise Corporation
// and its predecessors. Portions created by Inprise Corporation are
// Copyright (C) Inprise Corporation.
//
// All Rights Reserved.
// Contributor(s): ______________________________________.
// $Id: gpre.cpp,v 1.65 2004-10-30 05:30:08 robocop Exp $
// Revision 1.2 2000/11/16 15:54:29 fsg
// Added new switch -verbose to gpre that will dump
// parsed lines to stderr
//
// Fixed gpre bug in handling row names in WHERE clauses
// that are reserved words now (DATE etc)
// (this caused gpre to dump core when parsing tan.e)
//
// Fixed gpre bug in handling lower case table aliases
// in WHERE clauses for sql dialect 2 and 3.
// (cause a core dump in a test case from C.R. Zamana)
//
// TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings
//
// FSG (Frank Schlottmann-Gödde) 8.Mar.2002 - tiny cobol support
// fixed Bug No. 526204
//
// 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
//
//____________________________________________________________
//
//
#include "firebird.h"
#include <stdlib.h>
#include <string.h>
#include "../gpre/gpre.h"
#include "../jrd/license.h"
#include "../jrd/intl.h"
#include "../gpre/cmp_proto.h"
#include "../gpre/hsh_proto.h"
#include "../gpre/gpre_proto.h"
#include "../gpre/lang_proto.h"
#include "../gpre/gpre_meta.h"
#include "../gpre/msc_proto.h"
#include "../gpre/par_proto.h"
#include "../jrd/gds_proto.h"
#include "../gpre/gpreswi.h"
#include "../common/utils_proto.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef VMS
#include <descrip.h>
extern "C" {
int lib$get_foreign();
} // extern "C"
#endif
// Globals
GpreGlobals gpreGlob;
#ifdef SMALL_FILE_NAMES
const char* const SCRATCH = "fb_q";
#else
const char* const SCRATCH = "fb_query_";
#endif
const char* const FOPEN_READ_TYPE = "r";
const char* const FOPEN_WRITE_TYPE = "w";
static bool all_digits(const char*);
static bool arg_is_string(SLONG, TEXT**, const TEXT*);
static SSHORT compare_ASCII7z(const char*, const char*);
static SLONG compile_module(SLONG, const TEXT*);
static bool file_rename(TEXT*, const TEXT*, const TEXT*);
#ifdef GPRE_FORTRAN
static void finish_based(act*);
#endif
static int get_char(FILE*);
static bool get_switches(int, TEXT**, const in_sw_tab_t*, SW_TAB,
TEXT**);
static TOK get_token();
static int nextchar();
static SLONG pass1(const TEXT*);
static void pass2(SLONG);
static void print_switches();
static void remember_label(const TEXT*);
//static FILE* reposition_file(FILE *, SLONG);
static void return_char(SSHORT);
static SSHORT skip_white();
// Program wide globals
static FILE* input_file;
static FILE* trace_file;
static const TEXT* file_name;
static TEXT* out_file_name;
static SLONG position;
static SLONG last_position;
static SLONG line_position;
static SLONG first_position;
static SLONG prior_line_position;
static act* global_last_action;
static act* global_first_action;
static UCHAR classes[256];
static TEXT input_buffer[512], *input_char;
static DBB sw_databases;
// Added sw_verbose
// FSG 14.Nov.2000
static bool sw_verbose;
static bool sw_standard_out;
static USHORT sw_first;
static bool sw_lines;
static bool sw_trace;
static bool sw_alsys;
static int line_global;
static int warnings_global;
static int fatals_global;
//static jmp_buf fatal_env;
static const TEXT *comment_start, *comment_stop;
typedef void (*pfn_gen_routine) (const act*, int);
static pfn_gen_routine gen_routine;
static TEXT trace_file_name[128];
static SLONG traced_position = 0;
//___________________________________________________________________
// Test if input language is cpp based.
//
bool isLangCpp(LANG_T lang)
{
if (lang == lang_cxx || lang == lang_internal) {
return true;
}
return false;
}
/*
* Type and table definition for the extension tables. Tells GPRE
* the default extensions for DML and host languages.
*/
struct ext_table_t
{
lang_t ext_language;
gpre_cmd_switch ext_in_sw;
const TEXT* in;
const TEXT* out;
};
static const ext_table_t dml_ext_table[] =
{
{ lang_c, IN_SW_GPRE_C, ".e", ".c" },
#ifndef VMS
#ifndef WIN_NT
{ lang_scxx, IN_SW_GPRE_SCXX, ".E", ".C" },
#endif
#endif
{ lang_cxx, IN_SW_GPRE_CXX, ".exx", ".cxx" },
{ lang_cpp, IN_SW_GPRE_CXX, ".epp", ".cpp" },
{ lang_internal, IN_SW_GPRE_G, ".e", ".c" },
{ lang_internal_cxx, IN_SW_GPRE_0, ".epp", ".cpp" },
{ lang_pascal, IN_SW_GPRE_P, ".epas", ".pas" },
#ifdef GPRE_FORTRAN
#ifdef VMS
{ lang_fortran, IN_SW_GPRE_F, ".efor", ".for" },
#else
{ lang_fortran, IN_SW_GPRE_F, ".ef", ".f" },
#endif
#endif // GPRE_FORTRAN
#ifdef GPRE_COBOL
#ifdef VMS
{ lang_cobol, IN_SW_GPRE_COB, ".ecob", ".cob" },
#else
{ lang_cobol, IN_SW_GPRE_COB, ".ecbl", ".cbl" },
#endif
#endif // GPRE_COBOL
#ifdef GPRE_ADA
#ifdef VMS
{ lang_ada, IN_SW_GPRE_ADA, ".eada", ".ada" },
#elif defined(hpux)
{ lang_ada, IN_SW_GPRE_ADA, ".eada", ".ada" },
#else
{ lang_ada, IN_SW_GPRE_ADA, ".ea", ".a" },
#endif
#ifdef ALSYS_ADA
{ lang_ada, IN_SW_GPRE_ALSYS, ".eada", ".ada" },
#endif
#endif // GPRE_ADA
#if (defined( WIN_NT))
{ lang_cplusplus, IN_SW_GPRE_CPLUSPLUS, ".epp", ".cpp" },
#else
{ lang_cplusplus, IN_SW_GPRE_CPLUSPLUS, ".exx", ".cxx" },
#endif
{ lang_undef, IN_SW_GPRE_0, NULL, NULL }
};
enum char_types {
CHR_LETTER = 1,
CHR_DIGIT = 2,
CHR_IDENT = 4,
CHR_QUOTE = 8,
CHR_WHITE = 16,
CHR_INTRODUCER = 32,
CHR_DBLQUOTE = 64
};
// macro compares chars; case sensitive for some platforms
#ifdef EITHER_CASE
#define SAME(p,q) UPPER7 (*p) == UPPER7 (*q)
#else
#define SAME(p,q) *p == *q
#endif
//____________________________________________________________
//
// Main line routine for C preprocessor. Initializes
// system, performs pass 1 and pass 2. Interprets
// command line.
//
int main(int argc, char* argv[])
{
gpre_sym* symbol;
int i;
TEXT* p;
TEXT spare_file_name[256];
TEXT spare_out_file_name[256];
bool renamed;
bool explicitt;
const ext_table_t* ext_tab;
sw_tab_t sw_table[IN_SW_GPRE_COUNT];
#ifdef VMS
FILE *temp;
TEXT temp_name[256];
SSHORT c;
#endif
gpreGlob.module_lc_ctype = NULL;
gpreGlob.errors_global = 0;
warnings_global = 0;
fatals_global = 0;
gpreGlob.ADA_create_database = 1;
bool use_lang_internal_gxx_output;
use_lang_internal_gxx_output = false;
strcpy(gpreGlob.ada_package, "");
gpreGlob.ada_flags = 0;
input_char = input_buffer;
#ifdef VMS
argc = VMS_parse(&argv, argc);
#endif
// Initialize character class table
for (i = 0; i <= 127; ++i) {
classes[i] = 0;
}
for (i = 128; i <= 255; ++i) {
classes[i] = CHR_LETTER | CHR_IDENT;
}
for (i = 'a'; i <= 'z'; ++i) {
classes[i] = CHR_LETTER | CHR_IDENT;
}
for (i = 'A'; i <= 'Z'; ++i) {
classes[i] = CHR_LETTER | CHR_IDENT;
}
for (i = '0'; i <= '9'; ++i) {
classes[i] = CHR_DIGIT | CHR_IDENT;
}
classes[static_cast<UCHAR>('_')] = CHR_LETTER | CHR_IDENT | CHR_INTRODUCER;
classes[static_cast<UCHAR>('$')] = CHR_IDENT;
classes[static_cast<UCHAR>(' ')] = CHR_WHITE;
classes[static_cast<UCHAR>('\t')] = CHR_WHITE;
classes[static_cast<UCHAR>('\n')] = CHR_WHITE;
classes[static_cast<UCHAR>('\r')] = CHR_WHITE;
classes[static_cast<UCHAR>('\'')] = CHR_QUOTE;
classes[static_cast<UCHAR>('\"')] = CHR_DBLQUOTE;
classes[static_cast<UCHAR>('#')] = CHR_IDENT;
// zorch 0 through 7 in the fortran label vector
gpreGlob.fortran_labels[0] = 255;
// set switches and so on to default (C) values
DBB db = NULL;
gpreGlob.sw_language = lang_undef;
sw_lines = true;
gpreGlob.sw_auto = true;
gpreGlob.sw_cstring = true;
sw_alsys = false;
gpreGlob.sw_external = false;
sw_standard_out = false;
gpreGlob.sw_ansi = false;
gpreGlob.sw_version = false;
gpreGlob.sw_d_float = false;
gpreGlob.sw_sql_dialect = SQL_DIALECT_V5;
gpreGlob.dialect_specified = false;
gen_routine = C_CXX_action;
comment_start = "/*";
comment_stop = "*/";
gpreGlob.ident_pattern = "gds__%d";
gpreGlob.transaction_name = "gds__trans";
gpreGlob.database_name = "gds__database";
gpreGlob.utility_name = "gds__utility";
gpreGlob.count_name = "gds__count";
gpreGlob.slack_name = "gds__slack";
gpreGlob.global_db_count = 0;
gpreGlob.default_user = NULL;
gpreGlob.default_password = NULL;
gpreGlob.default_lc_ctype = NULL;
gpreGlob.text_subtypes = NULL;
gpreGlob.override_case = false;
gpreGlob.sw_know_interp = FALSE;
gpreGlob.sw_interp = 0;
// FSG 14.Nov.2000
sw_verbose = false;
gpreGlob.sw_sql_dialect = gpreGlob.compiletime_db_dialect = SQL_DIALECT_V5;
//
// Call a subroutine to process the input line
//
TEXT* filename_array[4] = { 0, 0, 0, 0 };
if (!get_switches(argc, argv, gpre_in_sw_table, sw_table, filename_array)) {
CPR_exit(FINI_ERROR);
}
file_name = filename_array[0];
out_file_name = filename_array[1];
const TEXT* db_filename = filename_array[2];
//TEXT* db_base_directory = filename_array[3];
if (!file_name) {
fprintf(stderr, "gpre: no source file named.\n");
CPR_exit(FINI_ERROR);
}
//
// Try to open the input file.
// If the language wasn't supplied, maybe the kind user included a language
// specific extension, and the file name fixer will find it. The file name
// fixer returns FALSE if it can't add an extension, which means there's already
// one of the right type there.
//
if (gpreGlob.sw_language == lang_undef)
for (ext_tab = dml_ext_table; gpreGlob.sw_language = ext_tab->ext_language;
ext_tab++)
{
strcpy(spare_file_name, file_name);
if (!(file_rename(spare_file_name, ext_tab->in, NULL)))
break;
}
//
// Sigh. No such luck. Maybe there's a file lying around with a plausible
// extension and we can use that.
//
if (gpreGlob.sw_language == lang_undef)
for (ext_tab = dml_ext_table; gpreGlob.sw_language = ext_tab->ext_language;
ext_tab++)
{
strcpy(spare_file_name, file_name);
if (file_rename(spare_file_name, ext_tab->in, NULL) &&
(input_file = fopen(spare_file_name, FOPEN_READ_TYPE)))
{
file_name = spare_file_name;
break;
}
}
//
// Well, if he won't tell me what language it is, or even give me a hint, I'm
// not going to spend all day figuring out what he wants done.
//
if (gpreGlob.sw_language == lang_undef) {
fprintf(stderr,
"gpre: can't find %s with any known extension. Giving up.\n",
file_name);
CPR_exit(FINI_ERROR);
}
//
// Having got here, we know the language, and might even have the file open.
// Better check before reopening it on ourselves. Try the file with the
// extension first (even if we have to add the extension). If we add an
// extension, and find a file with that extension, we make the file name
// point to the expanded file name string in a private buffer.
//
if (!input_file) {
strcpy(spare_file_name, file_name);
for (ext_tab = dml_ext_table;
ext_tab->ext_language != gpreGlob.sw_language;
ext_tab++)
{
; // empty loop body
}
renamed = file_rename(spare_file_name, ext_tab->in, NULL);
if (renamed &&
(input_file = fopen(spare_file_name, FOPEN_READ_TYPE)))
{
file_name = spare_file_name;
}
else if (!(input_file = fopen(file_name, FOPEN_READ_TYPE))) {
if (renamed) {
fprintf(stderr, "gpre: can't open %s or %s\n",
file_name, spare_file_name);
}
else {
fprintf(stderr, "gpre: can't open %s\n", file_name);
}
CPR_exit(FINI_ERROR);
}
}
//
// Now, apply the switches and defaults we've so painfully acquired;
// adding in the language switch in case we inferred it rather than parsing it.
//
const ext_table_t* src_ext_tab = dml_ext_table;
while (src_ext_tab->ext_language != gpreGlob.sw_language) {
++src_ext_tab;
}
sw_table[0].sw_in_sw = src_ext_tab->ext_in_sw;
for (SW_TAB sw_tab = sw_table; sw_tab->sw_in_sw; sw_tab++)
{
switch (sw_tab->sw_in_sw)
{
case IN_SW_GPRE_C:
gpreGlob.sw_language = lang_c;
gpreGlob.ident_pattern = "isc_%d";
gpreGlob.utility_name = "isc_utility";
gpreGlob.count_name = "isc_count";
gpreGlob.slack_name = "isc_slack";
break;
case IN_SW_GPRE_SCXX:
case IN_SW_GPRE_CXX:
case IN_SW_GPRE_CPLUSPLUS:
gpreGlob.sw_language = lang_cxx;
gpreGlob.ident_pattern = "isc_%d";
gpreGlob.utility_name = "isc_utility";
gpreGlob.count_name = "isc_count";
gpreGlob.slack_name = "isc_slack";
gpreGlob.transaction_name = "gds_trans";
gpreGlob.database_name = "gds_database";
break;
case IN_SW_GPRE_D:
// allocate database block and link to db chain
db = (DBB) MSC_alloc_permanent(DBB_LEN);
db->dbb_next = gpreGlob.isc_databases;
// put this one in line to be next
gpreGlob.isc_databases = db;
// allocate symbol block
symbol = (gpre_sym*) MSC_alloc_permanent(SYM_LEN);
// make it a database, specifically this one
symbol->sym_type = SYM_database;
symbol->sym_object = (gpre_ctx*) db;
symbol->sym_string = gpreGlob.database_name;
// database block points to the symbol block
db->dbb_name = symbol;
// give it the file name and try to open it
db->dbb_filename = db_filename;
if (!MET_database(db, true))
CPR_exit(FINI_ERROR);
if (gpreGlob.sw_external)
db->dbb_scope = DBB_EXTERN;
#ifdef FTN_BLK_DATA
else {
gpreGlob.global_db_count = 1;
strcpy(gpreGlob.global_db_list[0].dbb_name, db->dbb_name->sym_string);
}
#endif
break;
case IN_SW_GPRE_E:
gpreGlob.sw_case = true;
break;
#ifndef BOOT_BUILD
#ifdef GPRE_ADA
case IN_SW_GPRE_ADA:
#ifdef VMS
gpreGlob.ada_null_address = "system.address_zero";
#else
gpreGlob.ada_null_address = "0";
#endif
gpreGlob.sw_case = true;
gpreGlob.sw_language = lang_ada;
sw_lines = false;
gpreGlob.sw_cstring = false;
gen_routine = ADA_action;
gpreGlob.utility_name = "isc_utility";
gpreGlob.count_name = "isc_count";
gpreGlob.slack_name = "isc_slack";
gpreGlob.transaction_name = "gds_trans";
gpreGlob.database_name = "isc_database";
gpreGlob.ident_pattern = "isc_%d";
comment_start = "--";
if (db)
db->dbb_name->sym_string = "isc_database";
comment_stop = "--";
break;
case IN_SW_GPRE_ALSYS:
sw_alsys = true;
gpreGlob.sw_case = true;
gpreGlob.sw_language = lang_ada;
sw_lines = false;
gpreGlob.sw_cstring = false;
gen_routine = ADA_action;
gpreGlob.utility_name = "isc_utility";
gpreGlob.count_name = "isc_count";
gpreGlob.slack_name = "isc_slack";
gpreGlob.transaction_name = "gds_trans";
gpreGlob.database_name = "isc_database";
gpreGlob.ident_pattern = "isc_%d";
comment_start = "--";
if (db)
db->dbb_name->sym_string = "isc_database";
comment_stop = "--";
break;
#endif // GPRE_ADA
#ifdef GPRE_FORTRAN
case IN_SW_GPRE_F:
gpreGlob.sw_case = true;
gpreGlob.sw_language = lang_fortran;
sw_lines = false;
gpreGlob.sw_cstring = false;
gen_routine = FTN_action;
#ifdef sun
comment_start = "* ";
#else
comment_start = "C ";
#endif
comment_stop = " ";
// Change the patterns for v4.0
gpreGlob.ident_pattern = "isc_%d";
gpreGlob.utility_name = "isc_utility";
gpreGlob.count_name = "isc_count";
gpreGlob.slack_name = "isc_slack";
break;
#endif // GPRE_FORTRAN
#ifdef GPRE_COBOL
case IN_SW_GPRE_ANSI:
gpreGlob.sw_ansi = true;
break;
case IN_SW_GPRE_COB:
gpreGlob.sw_case = true;
gpreGlob.sw_language = lang_cobol;
comment_stop = " ";
sw_lines = false;
gpreGlob.sw_cstring = false;
gen_routine = COB_action;
break;
#endif // GPRE_COBOL
#ifdef GPRE_PASCAL
case IN_SW_GPRE_P:
gpreGlob.sw_case = true;
gpreGlob.sw_language = lang_pascal;
sw_lines = false;
gpreGlob.sw_cstring = false;
gen_routine = PAS_action;
comment_start = "(*";
comment_stop = "*)";
break;
#endif // GPRE_PASCAL
#endif // !BOOT_BUILD
case IN_SW_GPRE_D_FLOAT:
gpreGlob.sw_d_float = true;
break;
case IN_SW_GPRE_G:
gpreGlob.sw_language = lang_internal;
gen_routine = INT_CXX_action;
gpreGlob.sw_cstring = false;
gpreGlob.transaction_name = "dbb->dbb_sys_trans";
gpreGlob.sw_know_interp = TRUE;
gpreGlob.sw_interp = ttype_metadata;
break;
case IN_SW_GPRE_GXX:
/* When we get executed here the IN_SW_GPRE_G case
* has already been executed. So we just set the
* gen_routine to point to the C++ action, and be
* done with it.
*/
gen_routine = INT_CXX_action;
use_lang_internal_gxx_output = true;
break;
case IN_SW_GPRE_LANG_INTERNAL:
/* We need to reset all the variables (except gpreGlob.sw_language) to the
* default values because the IN_SW_GPRE_G case was already
* executed in the for the very first switch.
**/
gpreGlob.sw_language = lang_internal;
gen_routine = C_CXX_action;
gpreGlob.sw_cstring = true;
gpreGlob.transaction_name = "gds_trans";
gpreGlob.sw_know_interp = FALSE;
gpreGlob.sw_interp = 0;
gpreGlob.ident_pattern = "isc_%d";
gpreGlob.utility_name = "isc_utility";
gpreGlob.count_name = "isc_count";
gpreGlob.slack_name = "isc_slack";
gpreGlob.database_name = "gds_database";
break;
case IN_SW_GPRE_I:
gpreGlob.sw_ids = true;
break;
case IN_SW_GPRE_M:
gpreGlob.sw_auto = false;
break;
case IN_SW_GPRE_N:
sw_lines = false;
break;
case IN_SW_GPRE_O:
sw_standard_out = true;
gpreGlob.out_file = stdout;
break;
case IN_SW_GPRE_R:
gpreGlob.sw_raw = true;
break;
case IN_SW_GPRE_S:
gpreGlob.sw_cstring = false;
break;
case IN_SW_GPRE_T:
sw_trace = true;
break;
// FSG 14.Nov.2000
case IN_SW_GPRE_VERBOSE:
sw_verbose = true;
break;
default:
break;
}
} // for (...)
if ((gpreGlob.sw_auto) && (gpreGlob.default_user || gpreGlob.default_password
|| gpreGlob.default_lc_ctype))
{
CPR_warn("gpre: -user, -password and -charset switches require -manual");
}
//
// If one of the C++ variants was used/discovered, convert to C++ for
// further internal use.
//
if (gpreGlob.sw_language == lang_cpp || gpreGlob.sw_language == lang_cplusplus)
gpreGlob.sw_language = lang_cxx;
#ifdef ALSYS_ADA
if (sw_alsys) {
for (src_ext_tab = dml_ext_table;; src_ext_tab++)
if (src_ext_tab->ext_in_sw == IN_SW_GPRE_ALSYS)
break;
}
#endif
#ifdef VMS
//
// If we're on VMS, we may have an RMS sequential file rather than
// a stream file, and keeping track of our place will be harder.
// So... for VMS, copy the input to a stream file.
//
// If this is Alpha OpenVMS, then we also have to do some more
// work, since RMS is a little different...
//
#ifndef __ALPHA
temp = (FILE *) gds__temp_file(TRUE, "temp", 0);
strcpy(temp_name, "temporary file");
#else
temp = (FILE *) gds__temp_file(TRUE, "temp", temp_name);
#endif
if (temp != (FILE *) - 1) {
while ((c = get_char(input_file)) != EOF)
putc(c, temp);
fclose(input_file);
#ifdef __ALPHA
fclose(temp);
temp = fopen(temp_name, FOPEN_READ_TYPE);
#endif
}
else {
fprintf(stderr, "gpre: can't open %s\n", temp_name);
CPR_exit(FINI_ERROR);
}
input_file = temp;
#endif
#if defined(GPRE_COBOL) && !defined(BOOT_BUILD)
// if cobol is defined we need both sw_cobol and sw_ansi to
// determine how the string substitution table is set up
//
if (gpreGlob.sw_language == lang_cobol)
if (gpreGlob.sw_ansi) {
if (db)
db->dbb_name->sym_string = "isc-database";
comment_start = " * ";
gpreGlob.ident_pattern = "isc-%d";
gpreGlob.transaction_name = "isc-trans";
gpreGlob.database_name = "isc-database";
gpreGlob.utility_name = "isc-utility";
gpreGlob.count_name = "isc-count";
gpreGlob.slack_name = "isc-slack";
}
else { // just to be sure :-)
comment_start = "* ";
gpreGlob.transaction_name = "ISC_TRANS";
}
COB_name_init(gpreGlob.sw_ansi);
#endif
//
// See if user has specified an interpretation on the command line,
// as might be used for SQL access.
//
if (gpreGlob.default_lc_ctype) {
if (all_digits(gpreGlob.default_lc_ctype)) {
/* Numeric name? if so assume user has hard-coded a subtype number */
gpreGlob.sw_interp = atoi(gpreGlob.default_lc_ctype);
gpreGlob.sw_know_interp = TRUE;
}
else if (compare_ASCII7z(gpreGlob.default_lc_ctype, "DYNAMIC") == 0) {
// Dynamic means use the interpretation declared at runtime
gpreGlob.sw_interp = ttype_dynamic;
gpreGlob.sw_know_interp = TRUE;
}
else if (gpreGlob.isc_databases) {
// Name resolution done by MET_load_hash_table
gpreGlob.isc_databases->dbb_c_lc_ctype = gpreGlob.default_lc_ctype;
}
}
//
// Finally, open the output file, if we're not using standard out.
// If only one file name was given, make sure it has the preprocessor
// extension, then back up to that extension, zorch it, and add
// the language extension. Then you've got an output name. Take it
// and add the correct extension. If got an explicit output file
// name, use it as is unless it doesn't have an extension in which
// case use the default language extension. Finally, open the file.
// What could be easier?
//
if (!sw_standard_out) {
const ext_table_t* out_src_ext_tab = src_ext_tab;
if (use_lang_internal_gxx_output) {
out_src_ext_tab = dml_ext_table;
while (out_src_ext_tab->ext_language != lang_internal_cxx) {
++out_src_ext_tab;
}
}
renamed = explicitt = true;
if (!out_file_name) {
out_file_name = spare_out_file_name;
strcpy(spare_out_file_name, file_name);
if (renamed = file_rename(spare_out_file_name, out_src_ext_tab->in,
out_src_ext_tab->out))
{
explicitt = false;
}
}
if (renamed) {
for (p = out_file_name; *p; p++);
#ifdef VMS
while (p != out_file_name && *p != '.' && *p != ']')
#else
while (p != out_file_name && *p != '.' && *p != '/')
#endif
p--;
if (!explicitt)
*p = 0;
if (*p != '.') {
strcpy(spare_out_file_name, out_file_name);
out_file_name = spare_out_file_name;
file_rename(out_file_name, out_src_ext_tab->out, NULL);
}
}
if (!(strcmp(out_file_name, file_name))) {
fprintf(stderr,
"gpre: output file %s would duplicate input\n",
out_file_name);
CPR_exit(FINI_ERROR);
}
if ((gpreGlob.out_file = fopen(out_file_name, FOPEN_WRITE_TYPE)) == NULL) {
fprintf(stderr, "gpre: can't open output file %s\n",
out_file_name);
CPR_exit(FINI_ERROR);
}
}
// Compile modules until end of file
sw_databases = gpreGlob.isc_databases;
try {
SLONG end_position = 0;
while (end_position = compile_module(end_position,filename_array[3]));
// empty loop body
} // try
catch (const std::exception&) {} // fall through to the cleanup code
#ifdef FTN_BLK_DATA
if (gpreGlob.sw_language == lang_fortran)
FTN_fini();
#endif
MET_fini(0);
fclose(input_file);
#ifdef VMS
#ifdef __ALPHA
delete(temp_name);
#endif
#endif
if (!sw_standard_out) {
fclose(gpreGlob.out_file);
if (gpreGlob.errors_global)
unlink(out_file_name);
}
if (gpreGlob.errors_global || warnings_global) {
if (!gpreGlob.errors_global)
fprintf(stderr, "No errors, ");
else if (gpreGlob.errors_global == 1)
fprintf(stderr, "1 error, ");
else
fprintf(stderr, "%3d errors, ", gpreGlob.errors_global);
if (!warnings_global)
fprintf(stderr, "no warnings\n");
else if (warnings_global == 1)
fprintf(stderr, "1 warning\n");
else
fprintf(stderr, "%3d warnings\n", warnings_global);
}
CPR_exit((gpreGlob.errors_global) ? FINI_ERROR : FINI_OK);
return 0;
}
//____________________________________________________________
//
// Abort this silly program.
//
void CPR_abort()
{
++fatals_global;
//throw std::exception();
throw gpre_exception("Program terminated.");
}
#ifdef DEV_BUILD
//____________________________________________________________
//
// Report an assertion failure and abort this silly program.
//
void CPR_assert(const TEXT* file, int line)
{
TEXT buffer[MAXPATHLEN << 1];
fb_utils::snprintf(buffer, sizeof(buffer),
"GPRE assertion failure file '%s' line '%d'", file, line);
CPR_bugcheck(buffer);
}
#endif
//____________________________________________________________
//
// Issue an error message.
//
void CPR_bugcheck(const TEXT* string)
{
fprintf(stderr, "*** INTERNAL BUGCHECK: %s ***\n", string);
MET_fini(0);
CPR_abort();
}
//____________________________________________________________
//
// Mark end of a text description.
//
void CPR_end_text(gpre_txt* text)
{
text->txt_length = (USHORT) (gpreGlob.token_global.tok_position - text->txt_position - 1);
}
//____________________________________________________________
//
// Issue an error message.
//
int CPR_error(const TEXT* string)
{
fprintf(stderr, "(E) %s:%d: %s\n", file_name, line_global + 1, string);
gpreGlob.errors_global++;
return 0;
}
//____________________________________________________________
//
// Exit with status.
//
void CPR_exit( int stat)
{
#ifdef LINUX
if (trace_file_name[0])
{
if (trace_file)
fclose(trace_file);
unlink(trace_file_name);
}
#else
if (trace_file)
fclose(trace_file);
if (trace_file_name[0])
unlink(trace_file_name);
#endif
exit(stat);
}
//____________________________________________________________
//
// Issue an warning message.
//
void CPR_warn(const TEXT* string)
{
fprintf(stderr, "(W) %s:%d: %s\n", file_name, line_global + 1, string);
warnings_global++;
}
//____________________________________________________________
//
// Fortran, being a line oriented language, sometimes needs
// to know when it is at end of line to avoid parsing into the
// next statement. CPR_eol_token normally gets the next token,
// but if the language is FORTRAN and there isn't anything else
// on the line, it fakes a dummy token to indicate end of line.
//
TOK CPR_eol_token()
{
if (gpreGlob.sw_language != lang_fortran)
return CPR_token();
// Save the information from the previous token
gpreGlob.prior_token = gpreGlob.token_global;
gpreGlob.prior_token.tok_position = last_position;
last_position =
gpreGlob.token_global.tok_position + gpreGlob.token_global.tok_length
+ gpreGlob.token_global.tok_white_space - 1;
TEXT* p = gpreGlob.token_global.tok_string;
SSHORT num_chars = 0;
// skip spaces
SSHORT c;
for (c = nextchar(); c == ' '; c = nextchar()) {
num_chars++;
*p++ = (TEXT) c;
}
// in-line comments are equivalent to end of line
if (c == '!')
while (c != '\n' && c != EOF) {
c = nextchar();
num_chars++;
}
// in-line SQL comments are equivalent to end of line
if (gpreGlob.sw_sql && (c == '-')) {
const SSHORT peek = nextchar();
if (peek != '-')
return_char(peek);
else {
while (c != '\n' && c != EOF) {
c = nextchar();
num_chars++;
}
last_position = position - 1;
}
}
if (c == EOF) {
gpreGlob.token_global.tok_symbol = NULL;
gpreGlob.token_global.tok_keyword = KW_none;
return NULL;
}
// Not EOL so back up to the begining and try again
if (c != '\n') {
return_char(c);
while (--num_chars > 0)
return_char(*--p);
return CPR_token();
}
// if we've got EOL, treat it like a semi-colon
// NOTE: the fact that the length of this token is set to 0, is used as an
// indicator elsewhere that it was a faked token
gpreGlob.token_global.tok_string[0] = ';';
gpreGlob.token_global.tok_string[1] = 0;
gpreGlob.token_global.tok_type = tok_punct;
gpreGlob.token_global.tok_length = 0;
gpreGlob.token_global.tok_white_space = 0;
gpreGlob.token_global.tok_position = position;
gpreGlob.token_global.tok_symbol = HSH_lookup(gpreGlob.token_global.tok_string);
gpreGlob.token_global.tok_keyword = (KWWORDS) gpreGlob.token_global.tok_symbol->sym_keyword;
if (sw_trace)
puts(gpreGlob.token_global.tok_string);
return &gpreGlob.token_global;
}
//____________________________________________________________
//
// Write text from the scratch trace file into a buffer.
//
void CPR_get_text( TEXT* buffer, const gpre_txt* text)
{
SLONG start = text->txt_position;
int length = text->txt_length;
// On PC-like platforms, '\n' will be 2 bytes. The txt_position
// will be incorrect for fseek. The position is not adjusted
// just for PC-like platforms because, we use fseek () and
// getc to position ourselves at the token position.
// We should keep both character position and byte position
// and use them appropriately. for now use getc ()
//
#if (defined WIN_NT)
if (fseek(trace_file, 0L, 0))
#else
if (fseek(trace_file, start, 0))
#endif
{
fseek(trace_file, 0L, 2);
CPR_error("fseek failed for trace file");
}
#if (defined WIN_NT)
// move forward to actual position
while (start--)
getc(trace_file);
#endif
TEXT* p = buffer;
while (length--)
*p++ = getc(trace_file);
fseek(trace_file, (SLONG) 0, 2);
}
//____________________________________________________________
//
// A BASIC-specific function which resides here since it reads from
// the input file. Look for a '\n' with no continuation character (&).
// Eat tokens until previous condition is satisfied.
// This function is used to "eat" a BASIC external function definition.
//
void CPR_raw_read()
{
SCHAR token_string[MAXSYMLEN];
bool continue_char = false;
SCHAR* p = token_string;
SSHORT c;
while (c = get_char(input_file))
{
position++;
if ((classes[c] == CHR_WHITE) && sw_trace && token_string) {
*p = 0;
puts(token_string);
token_string[0] = 0;
p = token_string;
}
else
*p++ = (SCHAR) c;
if (c == '\n') { // Changed assignment to comparison. Probable archaic bug
line_global++;
line_position = 0;
if (!continue_char)
return;
continue_char = false;
}
else {
line_position++;
if (classes[c] != CHR_WHITE)
continue_char = (gpreGlob.token_global.tok_keyword == KW_AMPERSAND);
}
}
}
//____________________________________________________________
//
// Generate a syntax error.
//
void CPR_s_error(const TEXT* string)
{
TEXT s[512];
fb_utils::snprintf(s, sizeof(s),
"expected %s, encountered \"%s\"", string, gpreGlob.token_global.tok_string);
CPR_error(s);
PAR_unwind();
}
//____________________________________________________________
//
// Make the current position to save description text.
//
gpre_txt* CPR_start_text()
{
gpre_txt* text = (gpre_txt*) MSC_alloc(TXT_LEN);
text->txt_position = gpreGlob.token_global.tok_position - 1;
return text;
}
//____________________________________________________________
//
// Parse and return the next token.
// If the token is a charset introducer, gobble it, grab the
// next token, and flag that token as being in a non-default
// character set.
//
TOK CPR_token()
{
TOK token = get_token();
if (!token)
return NULL;
if (token->tok_type == tok_introducer) {
gpre_sym* symbol = MSC_find_symbol(HSH_lookup(token->tok_string + 1), SYM_charset);
if (!symbol) {
TEXT err_buffer[100];
sprintf(err_buffer, "Character set not recognized: '%.50s'",
token->tok_string);
CPR_error(err_buffer);
}
token = get_token();
switch (gpreGlob.sw_sql_dialect) {
case SQL_DIALECT_V5:
if (!(isQuoted(token->tok_type)))
CPR_error("Can only tag quoted strings with character set");
else
token->tok_charset = symbol;
break;
default:
if (token->tok_type != tok_sglquoted)
CPR_error("Can only tag quoted strings with character set");
else
token->tok_charset = symbol;
break;
}
}
// use -charset switch if there is one for quoted strings
// only after a database declaration is loaded and MET_load_hash_table run.
else if (gpreGlob.default_lc_ctype && gpreGlob.text_subtypes) {
switch (gpreGlob.sw_sql_dialect) {
case SQL_DIALECT_V5:
if (isQuoted(token->tok_type)) {
token->tok_charset = MSC_find_symbol(HSH_lookup(gpreGlob.default_lc_ctype),
SYM_charset);
}
break;
default:
if (token->tok_type == tok_sglquoted) {
token->tok_charset = MSC_find_symbol(HSH_lookup(gpreGlob.default_lc_ctype),
SYM_charset);
}
break;
}
}
return token;
}
//____________________________________________________________
//
// Return true if the string consists entirely of digits.
//
static bool all_digits(const char* str1)
{
for (; *str1; str1++)
if (!(classes[static_cast<UCHAR>(*str1)] & CHR_DIGIT))
return false;
return true;
}
//____________________________________________________________
//
// Check the command line argument which follows
// a switch which requires a string argument.
// If there is a problem, explain and return.
//
static bool arg_is_string(SLONG argc,
TEXT** argvstring,
const TEXT* errstring)
{
const TEXT* str = *++argvstring;
if (!argc || *str == '-') {
fprintf(stderr, "%s", errstring);
print_switches();
return false;
}
return true;
}
//____________________________________________________________
//
// Compare two ASCII 7-bit strings, case insensitive.
// Strings are null-byte terminated.
// Return 0 if strings are equal,
// (negative) if str1 < str2
// (positive) if str1 > str2
//
static SSHORT compare_ASCII7z(const char* str1, const char* str2)
{
for (; *str1; str1++, str2++)
if (UPPER7(*str1) != UPPER7(*str2))
return (UPPER7(*str1) - UPPER7(*str2));
return 0;
}
//____________________________________________________________
//
// Switches have been processed and files have been opened.
// Process a module and generate output.
//
static SLONG compile_module( SLONG start_position, const TEXT* base_directory)
{
// Reset miscellaneous pointers
gpreGlob.isc_databases = sw_databases;
gpreGlob.requests = NULL;
gpreGlob.events = NULL;
global_last_action = global_first_action = gpreGlob.global_functions = NULL;
// Position the input file and initialize various modules
fseek(input_file, start_position, 0);
input_char = input_buffer;
#if !(defined WIN_NT)
trace_file = (FILE *) gds__temp_file(TRUE, SCRATCH, 0);
#else
// PC-like platforms can't delete a file that is open. Therefore
// we will save the name of the temp file for later deletion.
trace_file = (FILE *) gds__temp_file(TRUE, SCRATCH, trace_file_name);
#endif
if (trace_file == (FILE *) - 1) {
trace_file = NULL;
CPR_error("Couldn't open scratch file");
return 0;
}
position = start_position;
MSC_init();
HSH_init();
PAR_init();
CMP_init();
// Take a first pass at the module
SLONG end_position = pass1(base_directory);
// finish up any based_ons that got deferred
#ifdef GPRE_FORTRAN
if (gpreGlob.sw_language == lang_fortran)
finish_based(global_first_action);
#endif
MET_fini(NULL);
PAR_fini();
if (gpreGlob.errors_global)
return end_position;
for (gpre_req* request = gpreGlob.requests; request; request = request->req_next)
{
CMP_compile_request(request);
}
fseek(input_file, start_position, 0);
input_char = input_buffer;
if (!gpreGlob.errors_global)
pass2(start_position);
return end_position;
}
//____________________________________________________________
//
// Add the appropriate extension to a file
// name, if there's not one already. If
// the "appropriate" one is there and a
// new extension is given, use it.
//
static bool file_rename(TEXT* file_nameL,
const TEXT* extension,
const TEXT* new_extension)
{
TEXT *p;
// go to the end of the file name
for (p = file_nameL; *p; p++);
TEXT* terminator = p;
// back up to the last extension (if any)
#if defined(VMS)
while ((p != file_nameL) && (*p != '.') && (*p != ']'))
#elif defined(WIN_NT)
while ((p != file_nameL) && (*p != '.') && (*p != '/') && (*p != '\\'))
#else
while ((p != file_nameL) && (*p != '.') && (*p != '/'))
#endif
--p;
//
// There's a match and the file spec has no extension,
// so add extension.
//
if (*p != '.') {
while (*terminator++ = *extension++);
return true;
}
//
// There's a match and an extension. If the extension in
// the table matches the one on the file, we don't want
// to add a duplicate. Otherwise add it.
//
TEXT* ext = p;
for (const TEXT* q = extension; SAME(p, q); p++, q++)
if (!*p) {
if (new_extension)
while (*ext++ = *new_extension++);
return false;
}
#ifndef VMS
// Didn't match extension, so add the extension
while (*terminator++ = *extension++);
#endif
return true;
}
#ifdef GPRE_FORTRAN
//____________________________________________________________
//
// Scan through the based_on actions
// looking for ones that were deferred
// because we didn't have a database yet.
//
// Look at each action in turn, and if it's
// a based_on with a field name rather than a
// field block pointer, complete the name parse.
// If there's a database name, find the database,
// then the relation within the database, then
// the field. Otherwise, look through all databases
// for the relation.
//
static void finish_based( act* action)
{
gpre_rel* relation;
gpre_fld* field;
TEXT s[MAXPATHLEN << 1];
for (; action; action = action->act_rest) {
if (action->act_type != ACT_basedon)
continue;
/* If there are no databases either on the command line or in
this subroutine or main program, can't do a BASED_ON. */
if (!gpreGlob.isc_databases) {
CPR_error
("No database defined. Needed for a BASED_ON operation");
continue;
}
bas* based_on = (bas*) action->act_object;
if (!based_on->bas_fld_name)
continue;
DBB db = NULL;
if (based_on->bas_db_name) {
gpre_sym* symbol = HSH_lookup(based_on->bas_db_name->str_string);
for (; symbol; symbol = symbol->sym_homonym)
if (symbol->sym_type == SYM_database)
break;
if (symbol) {
db = (DBB) symbol->sym_object;
relation =
MET_get_relation(db, based_on->bas_rel_name->str_string, "");
if (!relation) {
fb_utils::snprintf(s, sizeof(s),
"relation %s is not defined in database %s",
based_on->bas_rel_name->str_string,
based_on->bas_db_name->str_string);
CPR_error(s);
continue;
}
field = MET_field(relation, based_on->bas_fld_name->str_string);
}
else {
if (based_on->bas_flags & BAS_ambiguous) {
/* The reference could have been DB.RELATION.FIELD or
RELATION.FIELD.SEGMENT. It's not the former. Try
the latter. */
based_on->bas_fld_name = based_on->bas_rel_name;
based_on->bas_rel_name = based_on->bas_db_name;
based_on->bas_db_name = NULL;
based_on->bas_flags |= BAS_segment;
}
else {
fb_utils::snprintf(s, sizeof(s), "database %s is not defined",
based_on->bas_db_name->str_string);
CPR_error(s);
continue;
}
}
}
if (!db) {
field = NULL;
for (db = gpreGlob.isc_databases; db; db = db->dbb_next)
if (relation =
MET_get_relation(db, based_on->bas_rel_name->str_string, ""))
{
if (field) {
/* The field reference is ambiguous. It exists in more
than one database. */
fb_utils::snprintf(s, sizeof(s),
"field %s in relation %s ambiguous",
based_on->bas_fld_name->str_string,
based_on->bas_rel_name->str_string);
CPR_error(s);
break;
}
field =
MET_field(relation, based_on->bas_fld_name->str_string);
}
if (db)
continue;
if (!relation && !field) {
sprintf(s, "relation %s is not defined",
based_on->bas_rel_name->str_string);
CPR_error(s);
continue;
}
}
if (!field) {
sprintf(s, "field %s is not defined in relation %s",
based_on->bas_fld_name->str_string,
based_on->bas_rel_name->str_string);
CPR_error(s);
continue;
}
if ((based_on->bas_flags & BAS_segment)
&& !(field->fld_flags & FLD_blob))
{
sprintf(s, "field %s is not a blob",
field->fld_symbol->sym_string);
CPR_error(s);
continue;
}
based_on->bas_field = field;
}
}
#endif
//____________________________________________________________
//
// Return a character to the input stream.
//
static int get_char( FILE * file)
{
if (input_char != input_buffer) {
return (int) *--input_char;
}
else
{
const USHORT pc = getc(file);
// Dump this char to stderr, so we can see
// what input line will cause this ugly
// core dump.
// FSG 14.Nov.2000
if (sw_verbose) {
fprintf(stderr, "%c", pc);
}
return pc;
}
}
//____________________________________________________________
//
//
// Parse the input line arguments, saving
// interesting switches in a switch table.
// The first entry in the switch table is
// reserved for the language, and is set
// later, even if specified here.
//
static bool get_switches(int argc,
TEXT** argv,
const in_sw_tab_t* in_sw_table,
SW_TAB sw_table,
TEXT** file_array)
{
USHORT in_sw = 0; // silence uninitialized warning
//
// Read all the switches and arguments, acting only on those
// that apply immediately, since we may find out more when
// we try to open the file.
//
SW_TAB sw_table_iterator = sw_table;
for (--argc; argc; argc--)
{
TEXT* string = *++argv;
if (*string != '?')
{
if (*string != '-')
{
if (!file_array[1])
{
if (!file_array[0]) {
file_array[0] = string;
}
else {
file_array[1] = string;
}
continue;
}
else
{
// both input and output files have been defined, hence
// there is an unknown switch
in_sw = IN_SW_GPRE_0;
}
}
else
{
// iterate through the switch table, looking for matches
sw_table_iterator++;
sw_table_iterator->sw_in_sw = IN_SW_GPRE_0;
const TEXT* q;
for (const in_sw_tab_t* in_sw_table_iterator = in_sw_table;
q = in_sw_table_iterator->in_sw_name;
in_sw_table_iterator++)
{
const TEXT* p = string + 1;
// handle orphaned hyphen case
if (!*p--)
break;
// compare switch to switch name in table
while (*p) {
if (!*++p) {
sw_table_iterator->sw_in_sw = (gpre_cmd_switch)in_sw_table_iterator->in_sw;
}
if (UPPER7(*p) != *q++) {
break;
}
}
// end of input means we got a match. stop looking
if (!*p)
break;
}
in_sw = sw_table_iterator->sw_in_sw;
}
}
/*
* Check here for switches that affect file look ups
* and -D so we don't lose their arguments.
* Give up here if we find a bad switch.
*/
if (*string == '?') {
in_sw = IN_SW_GPRE_0;
}
switch (in_sw) {
case IN_SW_GPRE_C:
gpreGlob.sw_language = lang_c;
sw_table_iterator--;
break;
case IN_SW_GPRE_CXX:
gpreGlob.sw_language = lang_cxx;
sw_table_iterator--;
break;
case IN_SW_GPRE_CPLUSPLUS:
gpreGlob.sw_language = lang_cplusplus;
sw_table_iterator--;
break;
case IN_SW_GPRE_GXX:
/* If we decrement sw_tab the switch is removed
* from the table and not processed in the main
* switch statement. Since IN_SW_GPRE_G will always
* be processed for lang_internal, we leave our
* switch in so we can clean up the mess left behind
* by IN_SW_GPRE_G
*/
gpreGlob.sw_language = lang_internal;
break;
case IN_SW_GPRE_G:
gpreGlob.sw_language = lang_internal;
sw_table_iterator--;
break;
#ifdef GPRE_FORTRAN
case IN_SW_GPRE_F:
gpreGlob.sw_language = lang_fortran;
sw_table_iterator--;
break;
#endif
#ifdef GPRE_PASCAL
case IN_SW_GPRE_P:
gpreGlob.sw_language = lang_pascal;
sw_table_iterator--;
break;
#endif
case IN_SW_GPRE_X:
gpreGlob.sw_external = true;
sw_table_iterator--;
break;
#ifdef GPRE_COBOL
case IN_SW_GPRE_COB:
gpreGlob.sw_language = lang_cobol;
sw_table_iterator--;
break;
#endif
case IN_SW_GPRE_LANG_INTERNAL :
gpreGlob.sw_language = lang_internal;
/*sw_tab--;*/
break;
case IN_SW_GPRE_D:
if (!arg_is_string
(--argc, argv,
"Command line syntax: -d requires database name:\n "))
{
return false;
}
file_array[2] = *++argv;
string = *argv;
if (*string == '=')
if (!arg_is_string
(--argc, argv,
"Command line syntax: -d requires database name:\n "))
{
return false;
}
else
file_array[2] = *++argv;
break;
case IN_SW_GPRE_BASE:
if (!arg_is_string
(--argc, argv,
"Command line syntax: -b requires database base directory:\n "))
{
return false;
}
file_array[3] = *++argv;
string = *argv;
if (*string == '=')
if (!arg_is_string
(--argc, argv,
"Command line syntax: -b requires database base directory:\n "))
{
return false;
}
else
file_array[3] = *++argv;
break;
case IN_SW_GPRE_HANDLES:
if (!arg_is_string(
--argc,
argv,
"Command line syntax: -h requires handle package name\n"))
{
return false;
}
strcpy(gpreGlob.ada_package, *++argv);
strcat(gpreGlob.ada_package, ".");
break;
case IN_SW_GPRE_SQLDA:
if (!arg_is_string(
--argc,
argv,
"Command line syntax: -sqlda requires NEW\n "))
{
return false;
}
if (**argv != 'n' || **argv != 'N') {
fprintf(stderr,
"-sqlda : Deprecated Feature: you must use XSQLDA\n ");
print_switches();
return false;
}
break;
case IN_SW_GPRE_SQLDIALECT:
{
int inp;
if (!arg_is_string(
--argc,
argv,
"Command line syntax: -SQL_DIALECT requires value 1, 2 or 3 \n "))
{
return false;
}
++argv;
inp = atoi(*argv);
if (inp < 1 || inp > 3) {
fprintf(stderr,
"Command line syntax: -SQL_DIALECT requires value 1, 2 or 3 \n ");
print_switches();
return false;
}
else {
gpreGlob.sw_sql_dialect = inp;
}
gpreGlob.dialect_specified = true;
break;
}
case IN_SW_GPRE_Z:
if (!gpreGlob.sw_version) {
printf("gpre version %s\n", GDS_VERSION);
}
gpreGlob.sw_version = true;
break;
case IN_SW_GPRE_0:
if (*string != '?') {
fprintf(stderr, "gpre: unknown switch %s\n", string);
}
print_switches();
return false;
case IN_SW_GPRE_USER:
if (!arg_is_string(
--argc,
argv,
"Command line syntax: -user requires user name string:\n "))
{
return false;
}
gpreGlob.default_user = *++argv;
break;
case IN_SW_GPRE_PASSWORD:
if (!arg_is_string(
--argc,
argv,
"Command line syntax: -password requires password string:\n "))
{
return false;
}
gpreGlob.default_password = *++argv;
break;
case IN_SW_GPRE_INTERP:
if (!arg_is_string(
--argc,
argv,
"Command line syntax: -charset requires character set name:\n "))
{
return false;
}
gpreGlob.default_lc_ctype = (const TEXT*) * ++argv;
break;
}
}
sw_table_iterator++;
sw_table_iterator->sw_in_sw = IN_SW_GPRE_0;
return true;
}
//____________________________________________________________
//
// Parse and return the next token.
//
static TOK get_token()
{
SSHORT next;
USHORT peek;
TEXT *p, *end;
// Save the information from the previous token
gpreGlob.prior_token = gpreGlob.token_global;
gpreGlob.prior_token.tok_position = last_position;
last_position =
gpreGlob.token_global.tok_position + gpreGlob.token_global.tok_length
+ gpreGlob.token_global.tok_white_space - 1;
int start_line = line_global;
SLONG start_position = position;
gpreGlob.token_global.tok_charset = NULL;
SSHORT c = skip_white();
#ifdef GPRE_COBOL
// Skip over cobol line continuation characters
if (gpreGlob.sw_language == lang_cobol && !gpreGlob.sw_ansi)
while (line_position == 1) {
c = skip_white();
start_line = line_global;
}
#endif
// Skip fortran line continuation characters
#ifdef GPRE_FORTRAN
if (gpreGlob.sw_language == lang_fortran) {
while (line_position == 6) {
c = skip_white();
start_line = line_global;
}
if (gpreGlob.sw_sql && line_global != start_line) {
return_char(c);
gpreGlob.token_global.tok_string[0] = ';';
gpreGlob.token_global.tok_string[1] = 0;
gpreGlob.token_global.tok_type = tok_punct;
gpreGlob.token_global.tok_length = 0;
gpreGlob.token_global.tok_white_space = 0;
gpreGlob.token_global.tok_position = start_position + 1;
gpreGlob.token_global.tok_symbol = HSH_lookup(gpreGlob.token_global.tok_string);
gpreGlob.token_global.tok_keyword = (KWWORDS) gpreGlob.token_global.tok_symbol->sym_keyword;
return &gpreGlob.token_global;
}
}
#endif
// Get token rolling
p = gpreGlob.token_global.tok_string;
end = p + sizeof(gpreGlob.token_global.tok_string);
*p++ = (TEXT) c;
if (c == EOF) {
gpreGlob.token_global.tok_symbol = NULL;
gpreGlob.token_global.tok_keyword = KW_none;
return NULL;
}
gpreGlob.token_global.tok_position = position;
gpreGlob.token_global.tok_white_space = 0;
UCHAR char_class = classes[c];
#ifdef GPRE_ADA
if ((gpreGlob.sw_language == lang_ada) && (c == '\'')) {
const SSHORT c1 = nextchar();
const SSHORT c2 = nextchar();
if (c2 != '\'') {
char_class = CHR_LETTER;
}
return_char(c2);
return_char(c1);
}
#endif
bool label = false;
if (gpreGlob.sw_sql && (char_class & CHR_INTRODUCER)) {
while (classes[c = nextchar()] & CHR_IDENT) {
if (p < end) {
*p++ = (TEXT) c;
}
}
return_char(c);
gpreGlob.token_global.tok_type = tok_introducer;
}
else if (char_class & CHR_LETTER) {
while (true) {
while (classes[c = nextchar()] & CHR_IDENT)
*p++ = (TEXT) c;
if (c != '-' || gpreGlob.sw_language != lang_cobol)
break;
if (gpreGlob.sw_language == lang_cobol && gpreGlob.sw_ansi)
*p++ = (TEXT) c;
else
*p++ = '_';
}
return_char(c);
gpreGlob.token_global.tok_type = tok_ident;
}
else if (char_class & CHR_DIGIT) {
#ifdef GPRE_FORTRAN
if (gpreGlob.sw_language == lang_fortran && line_position < 7)
label = true;
#endif
while (classes[c = nextchar()] & CHR_DIGIT)
*p++ = (TEXT) c;
if (label) {
*p = 0;
remember_label(gpreGlob.token_global.tok_string);
}
if (c == '.') {
*p++ = (TEXT) c;
while (classes[c = nextchar()] & CHR_DIGIT)
*p++ = (TEXT) c;
}
if (!label && (c == 'E' || c == 'e')) {
*p++ = (TEXT) c;
c = nextchar();
if (c == '+' || c == '-')
*p++ = (TEXT) c;
else
return_char(c);
while (classes[c = nextchar()] & CHR_DIGIT)
*p++ = (TEXT) c;
}
return_char(c);
gpreGlob.token_global.tok_type = tok_number;
}
else if ((char_class & CHR_QUOTE) || (char_class & CHR_DBLQUOTE)) {
gpreGlob.token_global.tok_type = (char_class & CHR_QUOTE) ? tok_sglquoted : tok_dblquoted;
for (;;) {
next = nextchar();
if (gpreGlob.sw_language == lang_cobol && gpreGlob.sw_ansi && next == '\n') {
if (prior_line_position == 73) {
// should be a split literal
next = skip_white();
if (next != '-' || line_position != 7) {
CPR_error("unterminated quoted string");
break;
}
next = skip_white();
if (next != c) {
CPR_error("unterminated quoted string");
break;
}
next = nextchar();
gpreGlob.token_global.tok_white_space += line_position - 1;
}
else {
CPR_error("unterminated quoted string");
break;
}
}
else if (next == EOF
|| (next == '\n' && (p[-1] != '\\' || gpreGlob.sw_sql)))
{
return_char(*p);
/* Decrement, then increment line counter, for accuracy of
the error message for an unterminated quoted string. */
line_global--;
CPR_error("unterminated quoted string");
line_global++;
break;
}
/* If we can hold the literal do so, else assume it is in part
of program we do not care about */
if (next == '\\' && !gpreGlob.sw_sql &&
((gpreGlob.sw_language == lang_c) || (isLangCpp(gpreGlob.sw_language))))
{
peek = nextchar();
if (peek == '\n') {
gpreGlob.token_global.tok_white_space += 2;
}
else if (p < end) {
*p++ = (TEXT) next;
if (p < end) {
*p++ = (TEXT) peek;
}
}
continue;
}
if (p < end)
*p++ = (TEXT) next;
if (next == c)
/* If 2 quotes in a row, treat 2nd as literal - bug #1530 */
{
peek = nextchar();
if (peek != c) {
return_char(peek);
break;
}
else
gpreGlob.token_global.tok_white_space++;
}
}
}
else if (c == '.') {
if (classes[c = nextchar()] & CHR_DIGIT) {
*p++ = (TEXT) c;
while (classes[c = nextchar()] & CHR_DIGIT)
*p++ = (TEXT) c;
if ((c == 'E' || c == 'e')) {
*p++ = (TEXT) c;
c = nextchar();
if (c == '+' || c == '-')
*p++ = (TEXT) c;
else
return_char(c);
while (classes[c = nextchar()] & CHR_DIGIT)
*p++ = (TEXT) c;
}
return_char(c);
gpreGlob.token_global.tok_type = tok_number;
}
else {
return_char(c);
gpreGlob.token_global.tok_type = tok_punct;
*p++ = nextchar();
*p = 0;
if (!HSH_lookup(gpreGlob.token_global.tok_string))
return_char(*--p);
}
}
else {
gpreGlob.token_global.tok_type = tok_punct;
*p++ = nextchar();
*p = 0;
if (!HSH_lookup(gpreGlob.token_global.tok_string))
return_char(*--p);
}
gpre_sym* symbol;
gpreGlob.token_global.tok_length = p - gpreGlob.token_global.tok_string;
*p++ = 0;
if (isQuoted(gpreGlob.token_global.tok_type)) {
strip_quotes(gpreGlob.token_global);
/** If the dialect is 1 then anything that is quoted is
a string. Don not lookup in the hash table to prevent
parsing confusion.
**/
if (gpreGlob.sw_sql_dialect != SQL_DIALECT_V5)
gpreGlob.token_global.tok_symbol = symbol = HSH_lookup(gpreGlob.token_global.tok_string);
else
gpreGlob.token_global.tok_symbol = symbol = NULL;
if (symbol && symbol->sym_type == SYM_keyword)
gpreGlob.token_global.tok_keyword = (KWWORDS) symbol->sym_keyword;
else
gpreGlob.token_global.tok_keyword = KW_none;
}
else if (gpreGlob.sw_case) {
if (!gpreGlob.override_case) {
gpreGlob.token_global.tok_symbol = symbol = HSH_lookup2(gpreGlob.token_global.tok_string);
if (symbol && symbol->sym_type == SYM_keyword)
gpreGlob.token_global.tok_keyword = (KWWORDS) symbol->sym_keyword;
else
gpreGlob.token_global.tok_keyword = KW_none;
}
else {
gpreGlob.token_global.tok_symbol = symbol = HSH_lookup(gpreGlob.token_global.tok_string);
if (symbol && symbol->sym_type == SYM_keyword)
gpreGlob.token_global.tok_keyword = (KWWORDS) symbol->sym_keyword;
else
gpreGlob.token_global.tok_keyword = KW_none;
gpreGlob.override_case = false;
}
}
else {
gpreGlob.token_global.tok_symbol = symbol = HSH_lookup(gpreGlob.token_global.tok_string);
if (symbol && symbol->sym_type == SYM_keyword)
gpreGlob.token_global.tok_keyword = (KWWORDS) symbol->sym_keyword;
else
gpreGlob.token_global.tok_keyword = KW_none;
}
// ** Take care of GDML context variables. Context variables are inserted
//into the hash table as it is. There is no upper casing of the variable
//name done. Hence in all likelyhood we might have missed it while looking it
//up if -e switch was specified. Hence
//IF symbol is null AND it is not a quoted string AND -e switch was specified
//THEN search again using HSH_lookup2().
//*
if ((gpreGlob.token_global.tok_symbol == NULL) && (!isQuoted(gpreGlob.token_global.tok_type))
&& gpreGlob.sw_case)
{
gpreGlob.token_global.tok_symbol = symbol = HSH_lookup2(gpreGlob.token_global.tok_string);
if (symbol && symbol->sym_type == SYM_keyword)
gpreGlob.token_global.tok_keyword = (KWWORDS) symbol->sym_keyword;
else
gpreGlob.token_global.tok_keyword = KW_none;
}
// for FORTRAN, make note of the first token in a statement
fb_assert(first_position <= MAX_USHORT);
gpreGlob.token_global.tok_first = (USHORT) first_position;
first_position = FALSE;
if (sw_trace)
puts(gpreGlob.token_global.tok_string);
return &gpreGlob.token_global;
}
//____________________________________________________________
//
// Get the next character from the input stream.
// Also, for Fortran, mark the beginning of a statement
//
static int nextchar()
{
position++;
line_position++;
const SSHORT c = get_char(input_file);
if (c == '\n') {
line_global++;
prior_line_position = line_position;
line_position = 0;
}
// For silly fortran, mark the first token in a statement so
// we can decide to start the database field substitution string
// with a continuation indicator if appropriate.
if (line_position == 1) {
first_position = TRUE;
/* If the first character on a Fortran line is a tab, bump up the
position indicator. */
#ifdef GPRE_FORTRAN
if (gpreGlob.sw_language == lang_fortran && c == '\t')
line_position = 7;
#endif
}
// if this is a continuation line, the next token is not
// the start of a statement.
#ifdef GPRE_FORTRAN
if (gpreGlob.sw_language == lang_fortran && line_position == 6 && c != ' '
&& c != '0')
{
first_position = FALSE;
}
#endif
#ifdef GPRE_COBOL
if (gpreGlob.sw_language == lang_cobol &&
(!gpreGlob.sw_ansi && line_position == 1 && c == '-') ||
(gpreGlob.sw_ansi && line_position == 7 && c == '-'))
{
first_position = FALSE;
}
#endif
if (position > traced_position) {
traced_position = position;
fputc(c, trace_file);
}
return c;
}
//____________________________________________________________
//
// Make first pass at input file. This involves
// passing thru tokens looking for keywords. When
// a keyword is found, try to parse an action. If
// the parse is successful (an action block is returned)
// link the new action into the system data structures
// for processing on pass 2.
//
static SLONG pass1(const TEXT* base_directory)
{
// FSG 14.Nov.2000
if (sw_verbose) {
fprintf(stderr,
"*********************** PASS 1 ***************************\n");
}
while (CPR_token())
{
while (gpreGlob.token_global.tok_symbol)
{
const SLONG start = gpreGlob.token_global.tok_position;
act* action = PAR_action(base_directory);
if (action)
{
action->act_position = start;
if (!(action->act_flags & ACT_back_token)) {
action->act_length = last_position - start;
}
else {
action->act_length =
gpreGlob.prior_token.tok_position +
gpreGlob.prior_token.tok_length - 1 - start;
}
if (global_first_action) {
global_last_action->act_rest = action;
}
else {
global_first_action = action;
}
// Allow for more than one action to be generated by a token.
do
{
global_last_action = action;
if (action = action->act_rest)
{
if (action->act_type == ACT_database)
{
/* CREATE DATABASE has two actions the second one
is do generate global decl at the start of the
program file. */
global_last_action->act_rest = NULL;
action->act_rest = global_first_action;
global_first_action = action;
action->act_position = -1;
action->act_length = -1;
break;
}
else
{
action->act_position = global_last_action->act_position;
action->act_length = 0;
}
}
} while (action);
if (global_last_action->act_flags & ACT_break) {
return last_position;
}
if (!gpreGlob.token_global.tok_length &&
((int) gpreGlob.token_global.tok_keyword == (int) KW_SEMI_COLON))
{
break;
}
}
}
}
if (gpreGlob.isc_databases &&
(gpreGlob.isc_databases->dbb_flags & DBB_sqlca) &&
!gpreGlob.isc_databases->dbb_filename)
{
CPR_error("No database specified");
}
return 0;
}
//____________________________________________________________
//
// Make a second pass thru the input file turning actions into
// comments, substituting text for actions, and generating the
// output file.
//
static void pass2( SLONG start_position)
{
SLONG i;
SSHORT c = 0;
// FSG 14.Nov.2000
if (sw_verbose) {
fprintf(stderr,
"*********************** PASS 2 ***************************\n");
}
bool suppress_output = false;
const bool sw_block_comments =
gpreGlob.sw_language == lang_c ||
isLangCpp(gpreGlob.sw_language) ||
gpreGlob.sw_language == lang_pascal;
// Put out a distintive module header
if (!sw_first++)
{
for (i = 0; i < 5; ++i)
{
fprintf(gpreGlob.out_file,
"%s********** Preprocessed module -- do not edit **************%s\n",
comment_start, comment_stop);
}
fprintf(gpreGlob.out_file,
"%s**************** gpre version %s *********************%s\n",
comment_start, GDS_VERSION, comment_stop);
}
#ifdef GPRE_ADA
if ((gpreGlob.sw_language == lang_ada) &&
(gpreGlob.ada_flags & gpreGlob.ADA_create_database))
{
fprintf(gpreGlob.out_file, "with unchecked_conversion;\nwith system;\n");
}
#endif
// Let's prepare for worst case: a lot of small dirs, many "\" to duplicate.
char backlash_fixed_file_name[MAXPATHLEN + MAXPATHLEN];
{ // scope
char* p = backlash_fixed_file_name;
for (const char* q = file_name; *q;)
{
if ((*p++ = *q++) == '\\')
*p++ = '\\';
}
*p = 0;
} // scope
//
//if (sw_lines)
// fprintf (gpreGlob.out_file, "#line 1 \"%s\"\n", backlash_fixed_file_name);
//
SLONG line = 0;
bool line_pending = sw_lines;
SLONG current = 1 + start_position;
SLONG column = 0;
SSHORT comment_start_len = strlen(comment_start);
SSHORT to_skip = 0;
// Dump text until the start of the next action, then process the action.
for (const act* action = global_first_action; action; action = action->act_rest)
{
/* Dump text until the start of the next action. If a line marker
is pending and we see an end of line, dump out the marker. */
for (; current < action->act_position; current++)
{
c = get_char(input_file);
if (c == EOF) {
CPR_error("internal error -- unexpected EOF between actions");
return;
}
if (c == '\n' || !line) {
line++;
if (line_pending) {
if (line == 1)
fprintf(gpreGlob.out_file, "#line %ld \"%s\"\n", line,
backlash_fixed_file_name);
else
fprintf(gpreGlob.out_file, "\n#line %ld \"%s\"", line,
backlash_fixed_file_name);
line_pending = false;
}
if (line == 1 && c == '\n')
line++;
column = -1;
}
putc(c, gpreGlob.out_file);
if (c == '\t') {
column = (column + 8) & ~7;
}
else {
++column;
}
}
// Determine if this action is one which requires line continuation
// handling in certain languages.
const bool continue_flag =
(action->act_type == ACT_variable) ||
(action->act_type == ACT_segment) ||
(action->act_type == ACT_segment_length) ;
// Unless the action is purely a marker, insert a comment initiator
// into the output stream.
const SLONG start = column;
if (!(action->act_flags & ACT_mark)) {
if (gpreGlob.sw_language == lang_fortran) {
fputc('\n', gpreGlob.out_file);
fputs(comment_start, gpreGlob.out_file);
}
else if (gpreGlob.sw_language == lang_cobol)
if (continue_flag)
suppress_output = true;
else {
fputc('\n', gpreGlob.out_file);
fputs(comment_start, gpreGlob.out_file);
to_skip = (column < 7) ? comment_start_len - column : 0;
column = 0;
}
else
fputs(comment_start, gpreGlob.out_file);
}
// Next, dump the text of the action to the output stream.
for (i = 0; i <= action->act_length; ++i, ++current) {
if (c == EOF) {
CPR_error("internal error -- unexpected EOF in action");
return;
}
const SSHORT prior = c;
c = get_char(input_file);
if (!suppress_output) {
// close current comment to avoid nesting comments
if (sw_block_comments && !(action->act_flags & ACT_mark) &&
c == comment_start[0])
{
const SSHORT d = get_char(input_file);
return_char(d);
if (d == comment_start[1])
fputs(comment_stop, gpreGlob.out_file);
}
if (gpreGlob.sw_language != lang_cobol || !gpreGlob.sw_ansi || c == '\n'
|| to_skip-- <= 0)
{
putc(c, gpreGlob.out_file);
}
if (c == '\n') {
line++;
if ((gpreGlob.sw_language == lang_fortran) ||
(gpreGlob.sw_language == lang_ada) ||
(gpreGlob.sw_language == lang_cobol))
{
fputs(comment_start, gpreGlob.out_file);
to_skip =
(column < 7) ? comment_start_len - column : 0;
column = 0;
}
}
// reopen our comment at end of user's comment
if (sw_block_comments && !(action->act_flags & ACT_mark) &&
prior == comment_stop[0] && c == comment_stop[1])
{
fputs(comment_start, gpreGlob.out_file);
}
}
}
// Unless action was purely a marker, insert a comment terminator.
if (!(action->act_flags & ACT_mark) && !suppress_output) {
fputs(comment_stop, gpreGlob.out_file);
if ((gpreGlob.sw_language == lang_fortran) || (gpreGlob.sw_language == lang_cobol))
fputc('\n', gpreGlob.out_file);
}
suppress_output = false;
(*gen_routine) (action, start);
if (action->act_type == ACT_routine &&
!action->act_object &&
((gpreGlob.sw_language == lang_c) || (isLangCpp(gpreGlob.sw_language))))
{
continue;
}
if (action->act_flags & ACT_break)
return;
if (sw_lines)
line_pending = true;
column = 0;
to_skip = 0;
}
// We're out of actions -- dump the remaining text to the output stream.
if (!line && line_pending) {
fprintf(gpreGlob.out_file, "#line 1 \"%s\"\n", backlash_fixed_file_name);
line_pending = false;
}
while ((c = get_char(input_file)) != EOF) {
if (c == '\n' && line_pending) {
fprintf(gpreGlob.out_file, "\n#line %ld \"%s\"", line + 1, backlash_fixed_file_name);
line_pending = false;
}
if (c == EOF) {
CPR_error("internal error -- unexpected EOF in tail");
return;
}
putc(c, gpreGlob.out_file);
}
// Last but not least, generate any remaining functions
for (; gpreGlob.global_functions; gpreGlob.global_functions = gpreGlob.global_functions->act_next)
(*gen_routine) (gpreGlob.global_functions, 0);
}
//____________________________________________________________
//
// Print out the switch table as an
// aid to those who have forgotten or are fishing
//
static void print_switches()
{
const in_sw_tab_t* in_sw_table_iterator;
fprintf(stderr, "\tlegal switches are:\n");
for (in_sw_table_iterator = gpre_in_sw_table;
in_sw_table_iterator->in_sw;
in_sw_table_iterator++)
{
if (in_sw_table_iterator->in_sw_text) {
fprintf(stderr, "%s%s\n", in_sw_table_iterator->in_sw_name,
in_sw_table_iterator->in_sw_text);
}
}
fprintf(stderr, "\n\tand the internal 'illegal' switches are:\n");
for (in_sw_table_iterator = gpre_in_sw_table;
in_sw_table_iterator->in_sw;
in_sw_table_iterator++)
{
if (!in_sw_table_iterator->in_sw_text) {
fprintf(stderr, "%s\n", in_sw_table_iterator->in_sw_name);
}
}
}
//____________________________________________________________
//
// Set a bit in the label vector indicating
// that a label has been used. If the label
// is bigger than the vector, punt.
//
static void remember_label(const TEXT* label_string)
{
SLONG label = atoi(label_string);
if (label < 8192) {
const UCHAR target_byte = label & 7;
label >>= 3;
gpreGlob.fortran_labels[label] |= 1 << target_byte;
}
}
//____________________________________________________________
//
// Return a character to the input stream.
//
static void return_char( SSHORT c)
{
--position;
--line_position;
// note putting back a new line results in incorrect line_position value
if (c == '\n') {
--line_global;
}
*input_char++ = (TEXT) c;
}
//____________________________________________________________
//
// Skip over white space and comments in input stream
//
static SSHORT skip_white()
{
SSHORT c, next;
while (true) {
if ((c = nextchar()) == EOF)
return c;
c = c & 0xff;
// skip Fortran comments
#ifdef GPRE_FORTRAN
if (gpreGlob.sw_language == lang_fortran &&
line_position == 1 && (c == 'C' || c == 'c' || c == '*'))
{
while ((c = nextchar()) != '\n' && c != EOF);
continue;
}
#endif
#ifdef GPRE_COBOL
// skip sequence numbers when ansi COBOL
if (gpreGlob.sw_language == lang_cobol && gpreGlob.sw_ansi) {
while (line_position < 7 && (c = nextchar()) != '\n' && c != EOF);
}
// skip COBOL comments and conditional compilation
if (gpreGlob.sw_language == lang_cobol &&
(!gpreGlob.sw_ansi && line_position == 1 &&
(c == 'C' || c == 'c' || c == '*' || c == '/' || c == '\\') ||
(gpreGlob.sw_ansi && line_position == 7 && c != '\t' && c != ' '
&& c != '-')))
{
while ((c = nextchar()) != '\n' && c != EOF);
continue;
}
#endif
const UCHAR char_class = classes[c];
if (char_class & CHR_WHITE) {
continue;
}
// skip in-line SQL comments
if (gpreGlob.sw_sql && (c == '-')) {
const SSHORT c2 = nextchar();
if (c2 != '-')
return_char(c2);
else {
while ((c = nextchar()) != '\n' && c != EOF);
last_position = position - 1;
continue;
}
}
/* skip C, C++ and PL/I comments */
if (c == '/' &&
(gpreGlob.sw_language == lang_c ||
isLangCpp(gpreGlob.sw_language)))
{
if ((next = nextchar()) != '*') {
if (isLangCpp(gpreGlob.sw_language) && next == '/') {
while ((c = nextchar()) != '\n' && c != EOF);
continue;
}
return_char(next);
return c;
}
c = nextchar();
while ((next = nextchar()) != EOF && !(c == '*' && next == '/'))
c = next;
continue;
}
#if !defined(sun) && defined(GPRE_FORTRAN)
// skip fortran embedded comments on VMS or hpux or sgi
if (c == '!'
&& (gpreGlob.sw_language == lang_fortran))
{
/* If this character is a '!' followed by a '=', this is an
Interbase 'not equal' operator, not a Fortran comment.
Bug #307. mao 6/14/89 */
const SSHORT c3 = nextchar();
if (c3 == '=') {
return_char(c3);
return c;
}
else {
if ((c = c3) != '\n' && c != EOF)
while ((c = nextchar()) != '\n' && c != EOF);
continue;
}
}
#endif
if (c == '-' && (gpreGlob.sw_sql || gpreGlob.sw_language == lang_ada)) {
if ((next = nextchar()) != '-') {
return_char(next);
return c;
}
while ((c = nextchar()) != EOF && c != '\n');
continue;
}
// skip PASCAL comments - both types
if (c == '{' && gpreGlob.sw_language == lang_pascal) {
while ((c = nextchar()) != EOF && c != '}');
continue;
}
if (c == '(' && gpreGlob.sw_language == lang_pascal) {
if ((next = nextchar()) != '*') {
return_char(next);
return c;
}
c = nextchar();
while ((next = nextchar()) != EOF && !(c == '*' && next == ')'))
c = next;
continue;
}
break;
}
return c;
}