mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-25 05:23:02 +01:00
57f6bc46d5
-Use C++ struct declaration style.
446 lines
9.0 KiB
C++
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
|
|
|
|
}
|
|
|