8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 01:23:03 +01:00
firebird-mirror/src/dudley/generate.cpp

647 lines
13 KiB
C++

/*
* PROGRAM: JRD Data Definition Utility
* MODULE: generate.c
* DESCRIPTION: Blr 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): ______________________________________.
*/
#include "firebird.h"
#include <string.h>
#include "../jrd/gds.h"
#include "../dudley/ddl.h"
#include "../jrd/acl.h"
#include "../dudley/gener_proto.h"
#include "../jrd/gds_proto.h"
#include "../dudley/trn_proto.h"
static void generate(STR, DUDLEY_NOD);
static void get_set_generator(STR, DUDLEY_NOD);
#define STUFF(c) *blr->str_current++ = c
#define STUFF_WORD(c) {STUFF (c); STUFF (c >> 8);}
#define CHECK_BLR(l) {if ( !(blr->str_current - blr->str_start + l <= \
blr->str_length) && !TRN_get_buffer (blr, l) )\
DDL_err (289, NULL, NULL, NULL, NULL, NULL);}
int GENERATE_acl( SCL class_, UCHAR * buffer)
{
/**************************************
*
* G E N E R A T E _ a c l
*
**************************************
*
* Functional description
* Generate an access control list.
*
**************************************/
UCHAR *p, *q, **id, c;
SCE item;
USHORT i;
#if (defined JPN_SJIS || defined JPN_EUC)
/* This does not need Japanization because Kanji User names are not supported */
#endif
p = buffer;
*p++ = ACL_version;
for (item = class_->scl_entries; item; item = item->sce_next) {
*p++ = ACL_id_list;
for (i = 0, id = item->sce_idents; i < id_max; id++, i++)
if (q = *id) {
*p++ = i;
*p++ = strlen((char*) q);
while (c = *q++)
*p++ = UPPER(c);
}
*p++ = priv_end;
*p++ = ACL_priv_list;
for (i = 0; i < priv_max; i++)
if (item->sce_privileges & (1 << i))
*p++ = i;
*p++ = id_end;
}
*p++ = ACL_end;
return p - buffer;
}
void GENERATE_blr( STR blr, DUDLEY_NOD node)
{
/**************************************
*
* G E N E R A T E _ b l r
*
**************************************
*
* Functional description
* Compile a node tree into a blr string.
*
**************************************/
CHECK_BLR(1);
STUFF(blr_version4);
generate(blr, node);
CHECK_BLR(1);
STUFF(blr_eoc);
}
static void generate( STR blr, DUDLEY_NOD node)
{
/**************************************
*
* g e n e r a t e
*
**************************************
*
* Functional description
* Generate blr.
*
**************************************/
DUDLEY_FLD field;
DUDLEY_REL relation;
SYM symbol;
CON constant;
DUDLEY_NOD sub, *arg, *end;
DUDLEY_CTX context;
SCHAR operatr, *p;
SLONG value;
USHORT l;
arg = node->nod_arg;
end = arg + node->nod_count;
switch (node->nod_type) {
case nod_fid:
CHECK_BLR(4);
STUFF(blr_fid);
STUFF(0);
STUFF_WORD(0);
return;
case nod_field:
CHECK_BLR(4);
if (sub = node->nod_arg[s_fld_subs])
STUFF(blr_index);
STUFF(blr_field);
field = (DUDLEY_FLD) node->nod_arg[s_fld_field];
context = (DUDLEY_CTX) node->nod_arg[s_fld_context];
STUFF(context->ctx_context_id);
symbol = field->fld_name;
STUFF(l = symbol->sym_length);
p = (SCHAR *) symbol->sym_string;
if (l) {
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}
if (sub) {
CHECK_BLR(1);
STUFF(sub->nod_count);
for (arg = sub->nod_arg, end = arg + sub->nod_count; arg < end;
arg++)
generate(blr, *arg);
}
return;
case nod_function:
CHECK_BLR(2);
STUFF(blr_function);
symbol = (SYM) node->nod_arg[1];
STUFF(l = symbol->sym_length);
p = (SCHAR *) symbol->sym_string;
if (l) {
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}
sub = node->nod_arg[0];
CHECK_BLR(1);
STUFF(sub->nod_count);
for (arg = sub->nod_arg, end = arg + sub->nod_count; arg < end; arg++)
generate(blr, *arg);
return;
case nod_context:
context = (DUDLEY_CTX) node->nod_arg[0];
relation = context->ctx_relation;
CHECK_BLR(2);
STUFF(blr_relation);
symbol = relation->rel_name;
STUFF(l = symbol->sym_length);
p = (SCHAR *) symbol->sym_string;
if (l) {
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}
CHECK_BLR(1);
STUFF(context->ctx_context_id);
return;
case nod_gen_id:
CHECK_BLR(2);
STUFF(blr_gen_id);
symbol = (SYM) node->nod_arg[1];
STUFF(l = symbol->sym_length);
p = (SCHAR *) symbol->sym_string;
if (l) {
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}
generate(blr, node->nod_arg[0]);
return;
case nod_set_generator:
get_set_generator(blr, node);
return;
case nod_user_name:
CHECK_BLR(1);
STUFF(blr_user_name);
return;
case nod_null:
CHECK_BLR(1);
STUFF(blr_null);
return;
case nod_literal:
CHECK_BLR(6);
STUFF(blr_literal);
constant = (CON) node->nod_arg[0];
l = constant->con_desc.dsc_length;
switch (constant->con_desc.dsc_dtype) {
case dtype_text:
#if (!(defined JPN_SJIS || defined JPN_EUC))
STUFF(blr_text);
#else
STUFF(blr_text2);
STUFF_WORD(DDL_interp)
#endif
STUFF_WORD(l);
break;
case dtype_short:
CHECK_BLR(2);
STUFF(blr_short);
STUFF(constant->con_desc.dsc_scale);
break;
case dtype_long:
CHECK_BLR(2);
STUFF(blr_long);
STUFF(constant->con_desc.dsc_scale);
break;
case dtype_quad:
CHECK_BLR(2);
STUFF(blr_quad);
STUFF(constant->con_desc.dsc_scale);
break;
case dtype_real:
CHECK_BLR(1);
STUFF(blr_float);
break;
case dtype_double:
CHECK_BLR(1);
STUFF(blr_double);
break;
case dtype_timestamp:
CHECK_BLR(1);
STUFF(blr_timestamp);
break;
case dtype_int64:
case dtype_sql_time:
case dtype_sql_date:
default:
DDL_err(95, NULL, NULL, NULL, NULL, NULL); /* msg 95: GENERATE_blr: dtype not supported */
}
p = (SCHAR *) constant->con_data;
switch (constant->con_desc.dsc_dtype) {
case dtype_short:
value = *(SSHORT *) p;
CHECK_BLR(2);
STUFF_WORD(value);
break;
case dtype_long:
value = *(SLONG *) p;
CHECK_BLR(4);
STUFF_WORD(value);
STUFF_WORD(value >> 16);
break;
case dtype_quad:
case dtype_timestamp:
value = *(SLONG *) p;
CHECK_BLR(8);
STUFF_WORD(value);
STUFF_WORD(value >> 16);
value = *(SLONG *) (p + 4);
STUFF_WORD(value);
STUFF_WORD(value >> 16);
break;
default:
if (l) {
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}
}
return;
case nod_rse:
CHECK_BLR(2);
STUFF(blr_rse);
sub = node->nod_arg[s_rse_contexts];
STUFF(sub->nod_count);
for (l = 0, arg = sub->nod_arg; l < sub->nod_count; l++, arg++)
generate(blr, *arg);
if (sub = node->nod_arg[s_rse_first]) {
CHECK_BLR(1);
STUFF(blr_first);
generate(blr, sub);
}
if (sub = node->nod_arg[s_rse_boolean]) {
CHECK_BLR(1);
STUFF(blr_boolean);
generate(blr, sub);
}
if (sub = node->nod_arg[s_rse_sort]) {
CHECK_BLR(2);
STUFF(blr_sort);
STUFF(sub->nod_count / 2);
for (arg = sub->nod_arg, end = arg + sub->nod_count;
arg < end; arg += 2) {
CHECK_BLR(1);
STUFF((arg[1]) ? blr_descending : blr_ascending);
generate(blr, arg[0]);
}
}
if (sub = node->nod_arg[s_rse_reduced]) {
CHECK_BLR(2);
STUFF(blr_project);
STUFF(sub->nod_count / 2);
for (arg = sub->nod_arg, end = arg + sub->nod_count;
arg < end; arg += 2)
generate(blr, arg[0]);
}
CHECK_BLR(1);
STUFF(blr_end);
return;
case nod_count:
case nod_max:
case nod_min:
case nod_total:
case nod_average:
case nod_from:
switch (node->nod_type) {
case nod_count:
operatr = blr_count;
break;
case nod_max:
operatr = blr_maximum;
break;
case nod_min:
operatr = blr_minimum;
break;
case nod_total:
operatr = blr_total;
break;
case nod_average:
operatr = blr_average;
break;
case nod_from:
operatr = (node->nod_arg[s_stt_default]) ? blr_via : blr_from;
break;
}
CHECK_BLR(1);
STUFF(operatr);
generate(blr, node->nod_arg[s_stt_rse]);
if (sub = node->nod_arg[s_stt_value])
generate(blr, sub);
if (sub = node->nod_arg[s_stt_default])
generate(blr, sub);
return;
case nod_any:
CHECK_BLR(1);
STUFF(blr_any);
generate(blr, node->nod_arg[0]);
return;
case nod_unique:
CHECK_BLR(1);
STUFF(blr_unique);
generate(blr, node->nod_arg[0]);
return;
case nod_if:
CHECK_BLR(1);
STUFF(blr_if);
generate(blr, *arg++);
generate(blr, *arg++);
if (*arg)
generate(blr, *arg);
else {
CHECK_BLR(1);
STUFF(blr_end);
}
return;
case nod_list:
CHECK_BLR(1);
STUFF(blr_begin);
for (; arg < end; arg++)
generate(blr, *arg);
CHECK_BLR(1);
STUFF(blr_end);
return;
case nod_abort:
CHECK_BLR(2);
STUFF(blr_leave);
STUFF((int) node->nod_arg[0]);
return;
case nod_erase:
CHECK_BLR(2);
STUFF(blr_erase);
context = (DUDLEY_CTX) node->nod_arg[0];
STUFF(context->ctx_context_id);
return;
case nod_modify:
CHECK_BLR(3);
STUFF(blr_modify);
context = (DUDLEY_CTX) node->nod_arg[s_mod_old_ctx];
STUFF(context->ctx_context_id);
context = (DUDLEY_CTX) node->nod_arg[s_mod_new_ctx];
STUFF(context->ctx_context_id);
generate(blr, node->nod_arg[s_mod_action]);
return;
case nod_eql:
operatr = blr_eql;
break;
case nod_neq:
operatr = blr_neq;
break;
case nod_gtr:
operatr = blr_gtr;
break;
case nod_geq:
operatr = blr_geq;
break;
case nod_leq:
operatr = blr_leq;
break;
case nod_lss:
operatr = blr_lss;
break;
case nod_between:
operatr = blr_between;
break;
case nod_matches:
operatr = blr_matching;
break;
case nod_containing:
operatr = blr_containing;
break;
case nod_starts:
operatr = blr_starting;
break;
case nod_missing:
operatr = blr_missing;
break;
case nod_and:
operatr = blr_and;
break;
case nod_or:
operatr = blr_or;
break;
case nod_not:
operatr = blr_not;
break;
case nod_add:
operatr = blr_add;
break;
case nod_subtract:
operatr = blr_subtract;
break;
case nod_multiply:
operatr = blr_multiply;
break;
case nod_divide:
operatr = blr_divide;
break;
case nod_negate:
operatr = blr_negate;
break;
case nod_concatenate:
operatr = blr_concatenate;
break;
case nod_for:
operatr = blr_for;
break;
case nod_assignment:
operatr = blr_assignment;
break;
case nod_store:
operatr = blr_store;
break;
case nod_post:
operatr = blr_post;
break;
case nod_uppercase:
operatr = blr_upcase;
break;
case nod_sleuth:
operatr = blr_matching2;
break;
/*case nod_substr: operatr = blr_substring; break; */
default:
DDL_err(96, NULL, NULL, NULL, NULL, NULL); /* msg 96: GENERATE_blr: node not supported */
return;
}
/* If the user has given us something that has the form
field {EQ} NULL
{NE}
transform it into
field [NOT] MISSING */
if ((operatr == blr_eql || operatr == blr_neq) &&
(arg[0]->nod_type == nod_null || arg[1]->nod_type == nod_null)) {
if (operatr == blr_neq) {
CHECK_BLR(1);
STUFF(blr_not);
}
operatr = blr_missing;
if (arg[0]->nod_type == nod_null)
arg++;
end = arg + 1;
}
/* Fall thru on reasonable stuff */
CHECK_BLR(1);
STUFF(operatr);
for (; arg < end; arg++)
generate(blr, *arg);
}
static void get_set_generator( STR blr, DUDLEY_NOD node)
{
/**************************************
*
* g e t _ s e t _ g e n e r a t o r
*
**************************************
*
* Functional description
* produce blr for set_generator. The
* mutable characteristics are the
* generator name and the increment.
* The rest is canned.
**************************************/
SCHAR *p;
SYM symbol;
static SCHAR gen_prologue[] = {
blr_begin, blr_message, 0, 1, 0, blr_long, 0,
blr_send, 0, blr_begin, blr_assignment, blr_gen_id,
};
static SCHAR gen_epilogue[] = {
blr_parameter, 0, 0, 0, blr_end, blr_end
};
int l;
CON constant;
SLONG value;
/* copy the beginning of the blr into the buffer */
l = sizeof(gen_prologue);
p = gen_prologue;
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
/* stuff in the name length and the name */
symbol = (SYM) node->nod_arg[1];
CHECK_BLR(1);
STUFF(l = symbol->sym_length);
p = (SCHAR *) symbol->sym_string;
if (l) {
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}
/* now for the increvent value */
CHECK_BLR(7);
STUFF(blr_literal);
constant = (CON) node->nod_arg[0]->nod_arg[0];
STUFF(blr_long);
STUFF(constant->con_desc.dsc_scale);
p = (SCHAR *) constant->con_data;
value = *(SLONG *) p;
STUFF_WORD(value);
STUFF_WORD(value >> 16);
/* complete the string */
l = sizeof(gen_epilogue);
p = (SCHAR *) gen_epilogue;
CHECK_BLR(l);
do
STUFF(*p++);
while (--l);
}