8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 05:23:02 +01:00
firebird-mirror/src/gpre/pat.cpp

446 lines
9.0 KiB
C++

//____________________________________________________________
//
// PROGRAM: Language Preprocessor
// MODULE: pat.cpp
// DESCRIPTION: Code generator pattern generator
//
// 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: pat.cpp,v 1.24 2004-05-24 17:13:37 brodsom Exp $
//
#include "firebird.h"
#include <stdio.h>
#include <string.h>
#include "../gpre/gpre.h"
#include "../gpre/pat.h"
#include "../gpre/gpre_proto.h"
#include "../gpre/pat_proto.h"
#include "../gpre/lang_proto.h"
typedef enum {
NL,
RH, RL, RT, RI, RS, // Request handle, level, transaction, ident, length
DH, DF, // Database handle, filename
TH, // Transaction handle
BH, BI, // Blob handle, blob_ident
FH, // Form handle
V1, V2, // Status vectors
I1, I2, // Identifier numbers
RF, RE, // OS- and language-dependent REF and REF-end character
VF, VE, // OS- and language-dependent VAL and VAL-end character
S1, S2, S3, S4, S5, S6, S7,
// Arbitrary strings
N1, N2, N3, N4, // Arbitrary number (SSHORT)
L1, L2, // Arbitrary number (SLONG)
PN, PL, PI, // Port number, port length, port ident
QN, QL, QI, // Second port number, port length, port ident
IF, EL, EN, // If, else, end
FR // Field reference
} PAT_T;
static const struct ops {
PAT_T ops_type;
TEXT ops_string[3];
} operators[] =
{
{ RH, "RH" },
{ RL, "RL" },
{ RT, "RT" },
{ RI, "RI" },
{ RS, "RS" },
{ DH, "DH" },
{ DF, "DF" },
{ TH, "TH" },
{ BH, "BH" },
{ BI, "BI" },
{ FH, "FH" },
{ V1, "V1" },
{ V2, "V2" },
{ I1, "I1" },
{ I2, "I2" },
{ S1, "S1" },
{ S2, "S2" },
{ S3, "S3" },
{ S4, "S4" },
{ S5, "S5" },
{ S6, "S6" },
{ S7, "S7" },
{ N1, "N1" },
{ N2, "N2" },
{ N3, "N3" },
{ N4, "N4" },
{ L1, "L1" },
{ L2, "L2" },
{ PN, "PN" },
{ PL, "PL" },
{ PI, "PI" },
{ QN, "QN" },
{ QL, "QL" },
{ QI, "QI" },
{ IF, "IF" },
{ EL, "EL" },
{ EN, "EN" },
{ RF, "RF" },
{ RE, "RE" },
{ VF, "VF" },
{ VE, "VE" },
{ FR, "FR" },
{ NL, "" }
};
//____________________________________________________________
//
// Expand a pattern.
//
void PATTERN_expand( USHORT column, const TEXT* pattern, PAT* args)
{
TEXT buffer[512], temp1[16], temp2[16];
SSHORT value; /* value needs to be signed since some of the
values printed out are signed. */
SLONG long_value;
TEXT* q;
// CVC: kudos to the programmer that had chosen variables with the same
// names that structs in gpre.h and with type char* if not enough.
// Renamed ref to lang_ref and val to lang_val.
const TEXT* lang_ref = "";
const TEXT* refend = "";
const TEXT* lang_val = "";
const TEXT* valend = "";
if ((gpreGlob.sw_language == lang_c) || (isLangCpp(gpreGlob.sw_language))) {
lang_ref = "&";
refend = "";
}
else if (gpreGlob.sw_language == lang_pascal) {
lang_ref = "%%REF ";
refend = "";
}
else if (gpreGlob.sw_language == lang_cobol) {
lang_ref = "BY REFERENCE ";
refend = "";
lang_val = "BY VALUE ";
valend = "";
}
else if (gpreGlob.sw_language == lang_fortran) {
#ifdef VMS
lang_ref = "%REF(";
refend = ")";
lang_val = "%VAL(";
valend = ")";
#endif
#if (defined AIX || defined AIX_PPC)
lang_ref = "%REF(";
refend = ")";
lang_val = "%VAL(";
valend = ")";
#endif
}
TEXT* p = buffer;
*p++ = '\n';
bool sw_gen = true;
for (USHORT n = column; n; --n)
*p++ = ' ';
TEXT c;
while (c = *pattern++) {
if (c != '%') {
if (sw_gen) {
*p++ = c;
if ((c == '\n') && (*pattern))
for (USHORT n = column; n; --n)
*p++ = ' ';
}
continue;
}
bool sw_ident = false;
const TEXT* string = NULL;
const ref* reference = NULL;
bool handle_flag = false, long_flag = false;
const ops* oper_iter;
for (oper_iter = operators; oper_iter->ops_type != NL; oper_iter++)
if (oper_iter->ops_string[0] == pattern[0] &&
oper_iter->ops_string[1] == pattern[1])
{
break;
}
pattern += 2;
switch (oper_iter->ops_type) {
case IF:
sw_gen = args->pat_condition;
continue;
case EL:
sw_gen = !sw_gen;
continue;
case EN:
sw_gen = true;
continue;
case RH:
handle_flag = true;
string = args->pat_request->req_handle;
break;
case RL:
string = args->pat_request->req_request_level;
break;
case RS:
value = args->pat_request->req_length;
break;
case RT:
handle_flag = true;
string = args->pat_request->req_trans;
break;
case RI:
value = args->pat_request->req_ident;
sw_ident = true;
break;
case DH:
handle_flag = true;
string = args->pat_database->dbb_name->sym_string;
break;
case DF:
string = args->pat_database->dbb_filename;
break;
case PN:
value = args->pat_port->por_msg_number;
break;
case PL:
value = args->pat_port->por_length;
break;
case PI:
value = args->pat_port->por_ident;
sw_ident = true;
break;
case QN:
value = args->pat_port2->por_msg_number;
break;
case QL:
value = args->pat_port2->por_length;
break;
case QI:
value = args->pat_port2->por_ident;
sw_ident = true;
break;
case BH:
value = args->pat_blob->blb_ident;
sw_ident = true;
break;
case I1:
value = args->pat_ident1;
sw_ident = true;
break;
case I2:
value = args->pat_ident2;
sw_ident = true;
break;
case S1:
string = args->pat_string1;
break;
case S2:
string = args->pat_string2;
break;
case S3:
string = args->pat_string3;
break;
case S4:
string = args->pat_string4;
break;
case S5:
string = args->pat_string5;
break;
case S6:
string = args->pat_string6;
break;
case S7:
string = args->pat_string7;
break;
case V1:
string = args->pat_vector1;
break;
case V2:
string = args->pat_vector2;
break;
case N1:
value = args->pat_value1;
break;
case N2:
value = args->pat_value2;
break;
case N3:
value = args->pat_value3;
break;
case N4:
value = args->pat_value4;
break;
case L1:
long_value = args->pat_long1;
long_flag = true;
break;
case L2:
long_value = args->pat_long2;
long_flag = true;
break;
case RF:
string = lang_ref;
break;
case RE:
string = refend;
break;
case VF:
string = lang_val;
break;
case VE:
string = valend;
break;
case FR:
reference = args->pat_reference;
break;
default:
sprintf(buffer, "Unknown substitution \"%c%c\"", pattern[-2],
pattern[-1]);
CPR_error(buffer);
continue;
}
if (!sw_gen)
continue;
if (string) {
if (handle_flag && (gpreGlob.sw_language == lang_ada))
for (q = gpreGlob.ada_package; *q;)
*p++ = *q++;
while (*string)
*p++ = *string++;
continue;
}
if (sw_ident)
sprintf(p, gpreGlob.ident_pattern, value);
else if (reference) {
if (!reference->ref_port)
sprintf(p, gpreGlob.ident_pattern, reference->ref_ident);
else {
sprintf(temp1, gpreGlob.ident_pattern, reference->ref_port->por_ident);
sprintf(temp2, gpreGlob.ident_pattern, reference->ref_ident);
switch (gpreGlob.sw_language) {
case lang_fortran:
case lang_cobol:
strcpy(p, temp2);
break;
default:
sprintf(p, "%s.%s", temp1, temp2);
}
}
}
else if (long_flag) {
sprintf(p, "%"SLONGFORMAT, long_value);
}
else {
sprintf(p, "%d", value);
}
while (*p)
p++;
}
*p = 0;
#if (defined GPRE_ADA || defined GPRE_COBOL || defined GPRE_FORTRAN) && !defined(BOOT_BUILD)
switch (gpreGlob.sw_language) {
#ifdef GPRE_ADA
/* Ada lines can be up to 120 characters long. ADA_print_buffer
handles this problem and ensures that GPRE output is <=120 characters.
*/
case lang_ada:
ADA_print_buffer(buffer, 0);
break;
#endif
#ifdef GPRE_COBOL
/* COBOL lines can be up to 72 characters long. COB_print_buffer
handles this problem and ensures that GPRE output is <= 72 characters.
*/
case lang_cobol:
COB_print_buffer(buffer, true);
break;
#endif
#ifdef GPRE_FORTRAN
/* In FORTRAN, characters beyond column 72 are ignored. FTN_print_buffer
handles this problem and ensures that GPRE output does not exceed this
limit.
*/
case lang_fortran:
FTN_print_buffer(buffer);
break;
#endif
default:
fprintf(gpreGlob.out_file, buffer);
break;
}
#else
fprintf(gpreGlob.out_file, buffer);
#endif
}