mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 19:23:02 +01:00
523 lines
11 KiB
C++
523 lines
11 KiB
C++
//____________________________________________________________
|
|
//
|
|
// PROGRAM: C preprocessor
|
|
// MODULE: msc.cpp
|
|
// DESCRIPTION: Miscellaneous little stuff
|
|
//
|
|
// 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): ______________________________________.
|
|
// TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings
|
|
//
|
|
//
|
|
//____________________________________________________________
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
// ***************************************************
|
|
// THIS MODULE HAS SEVERAL KISSING COUSINS; IF YOU
|
|
// SHOULD CHANGE ONE OF THE MODULES IN THE FOLLOWING
|
|
// LIST, PLEASE BE SURE TO CHECK THE OTHERS FOR
|
|
// SIMILAR CHANGES:
|
|
//
|
|
// qli/all.cpp
|
|
// gpre/msc.cpp
|
|
//
|
|
// - THANK YOU
|
|
// **************************************************
|
|
|
|
#include "firebird.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "../gpre/gpre.h"
|
|
#include "../gpre/gpre_proto.h"
|
|
#include "../gpre/msc_proto.h"
|
|
#include "../yvalve/gds_proto.h"
|
|
|
|
|
|
struct gpre_space
|
|
{
|
|
gpre_space* spc_next;
|
|
SLONG spc_remaining;
|
|
};
|
|
|
|
static gpre_space* space;
|
|
static gpre_space* permanent_space;
|
|
static gpre_lls* free_lls;
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make an action and link it to a request.
|
|
//
|
|
|
|
act* MSC_action( gpre_req* request, act_t type)
|
|
{
|
|
act* action = (act*) MSC_alloc(ACT_LEN);
|
|
action->act_type = type;
|
|
|
|
if (request)
|
|
{
|
|
action->act_next = request->req_actions;
|
|
request->req_actions = action;
|
|
action->act_request = request;
|
|
}
|
|
|
|
return action;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
//
|
|
|
|
UCHAR* MSC_alloc(int size)
|
|
{
|
|
size = FB_ALIGN(size, FB_ALIGNMENT);
|
|
|
|
if (!space || size > space->spc_remaining)
|
|
{
|
|
const int n = MAX(size, 4096);
|
|
gpre_space* next = (gpre_space*) gds__alloc((SLONG) (n + sizeof(gpre_space)));
|
|
if (!next)
|
|
CPR_error("virtual memory exhausted");
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
// For V4.0 we don't care about gpre specific memory leaks
|
|
gds_alloc_flag_unfreed(next);
|
|
#endif
|
|
next->spc_next = space;
|
|
next->spc_remaining = n;
|
|
space = next;
|
|
}
|
|
|
|
space->spc_remaining -= size;
|
|
UCHAR* blk = ((UCHAR*) space + sizeof(gpre_space) + space->spc_remaining);
|
|
memset(blk, 0, size);
|
|
|
|
return blk;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Allocate a block in permanent memory.
|
|
//
|
|
|
|
UCHAR* MSC_alloc_permanent(int size)
|
|
{
|
|
size = FB_ALIGN(size, FB_ALIGNMENT);
|
|
|
|
if (!permanent_space || size > permanent_space->spc_remaining)
|
|
{
|
|
const int n = MAX(size, 4096);
|
|
gpre_space* next = (gpre_space*) gds__alloc((SLONG) (n + sizeof(gpre_space)));
|
|
if (!next)
|
|
CPR_error("virtual memory exhausted");
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
// For V4.0 we don't care about gpre specific memory leaks
|
|
gds_alloc_flag_unfreed(next);
|
|
#endif
|
|
next->spc_next = permanent_space;
|
|
next->spc_remaining = n;
|
|
permanent_space = next;
|
|
}
|
|
|
|
permanent_space->spc_remaining -= size;
|
|
UCHAR* blk = (UCHAR*) permanent_space + sizeof(gpre_space) + permanent_space->spc_remaining;
|
|
memset(blk, 0, size);
|
|
|
|
return blk;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make a binary node.
|
|
//
|
|
|
|
gpre_nod* MSC_binary(nod_t type, gpre_nod* arg1, gpre_nod* arg2)
|
|
{
|
|
gpre_nod* node = MSC_node(type, 2);
|
|
node->nod_arg[0] = arg1;
|
|
node->nod_arg[1] = arg2;
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make a new context for a request and link it up to the request.
|
|
//
|
|
|
|
gpre_ctx* MSC_context(gpre_req* request)
|
|
{
|
|
// allocate and initialize
|
|
|
|
gpre_ctx* context = (gpre_ctx*) MSC_alloc(CTX_LEN);
|
|
context->ctx_request = request;
|
|
context->ctx_internal = request->req_internal++;
|
|
context->ctx_scope_level = request->req_scope_level;
|
|
|
|
// link in with the request block
|
|
|
|
context->ctx_next = request->req_contexts;
|
|
request->req_contexts = context;
|
|
|
|
return context;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Copy one string into another.
|
|
//
|
|
|
|
void MSC_copy(const char* from, int length, char* to)
|
|
{
|
|
|
|
if (length)
|
|
memcpy(to, from, length);
|
|
|
|
to[length] = 0;
|
|
}
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Copy two strings into another.
|
|
//
|
|
|
|
void MSC_copy_cat(const char* from1, int length1, const char* from2, int length2, char* to)
|
|
{
|
|
|
|
if (length1)
|
|
memcpy(to, from1, length1);
|
|
if (length2)
|
|
memcpy(to + length1, from2, length2);
|
|
|
|
to[length1 + length2] = 0;
|
|
}
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Find a symbol of a particular type.
|
|
//
|
|
|
|
gpre_sym* MSC_find_symbol(gpre_sym* symbol, sym_t type)
|
|
{
|
|
|
|
for (; symbol; symbol = symbol->sym_homonym)
|
|
if (symbol->sym_type == type)
|
|
return symbol;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Free a block.
|
|
//
|
|
|
|
void MSC_free(void*)
|
|
{
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Get rid of an erroroneously allocated request block.
|
|
//
|
|
|
|
void MSC_free_request( gpre_req* request)
|
|
{
|
|
|
|
gpreGlob.requests = request->req_next;
|
|
gpreGlob.cur_routine->act_object = (ref*) request->req_routine;
|
|
MSC_free(request);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Initialize (or more properly, re-initialize) the memory
|
|
// allocator.
|
|
//
|
|
|
|
void MSC_init()
|
|
{
|
|
free_lls = NULL;
|
|
|
|
gpre_space* stuff;
|
|
while (stuff = space)
|
|
{
|
|
space = space->spc_next;
|
|
gds__free(stuff);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Match the current token against a keyword. If successful,
|
|
// advance the token stream and return true. Otherwise return
|
|
// false.
|
|
//
|
|
|
|
bool MSC_match(const kwwords_t keyword)
|
|
{
|
|
|
|
if (gpreGlob.token_global.tok_keyword == KW_none && gpreGlob.token_global.tok_symbol)
|
|
{
|
|
gpre_sym* symbol;
|
|
for (symbol = gpreGlob.token_global.tok_symbol->sym_collision; symbol;
|
|
symbol = symbol->sym_collision)
|
|
{
|
|
if ((strcmp(symbol->sym_string, gpreGlob.token_global.tok_string) == 0) &&
|
|
symbol->sym_keyword != KW_none)
|
|
{
|
|
gpreGlob.token_global.tok_symbol = symbol;
|
|
gpreGlob.token_global.tok_keyword = static_cast<kwwords_t>(symbol->sym_keyword);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gpreGlob.token_global.tok_keyword != keyword)
|
|
return false;
|
|
|
|
CPR_token();
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef NOT_USED_OR_REPLACED
|
|
//____________________________________________________________
|
|
//
|
|
// Determinate where a specific object is
|
|
// represented on a linked list stack.
|
|
//
|
|
|
|
bool MSC_member(const gpre_nod* object, const gpre_lls* stack)
|
|
{
|
|
|
|
for (; stack; stack = stack->lls_next)
|
|
if (stack->lls_object == object)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Allocate and initialize a syntax node.
|
|
//
|
|
|
|
gpre_nod* MSC_node(nod_t type, SSHORT count)
|
|
{
|
|
gpre_nod* node = (gpre_nod*) MSC_alloc(NOD_LEN(count));
|
|
node->nod_count = count;
|
|
node->nod_type = type;
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Pop an item off a linked list stack. Free the stack node.
|
|
//
|
|
|
|
gpre_nod* MSC_pop(gpre_lls** pointer)
|
|
{
|
|
gpre_lls* stack = *pointer;
|
|
gpre_nod* node = stack->lls_object;
|
|
*pointer = stack->lls_next;
|
|
|
|
stack->lls_next = free_lls;
|
|
free_lls = stack;
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Allocate a new privilege (grant/revoke) block.
|
|
//
|
|
|
|
PRV MSC_privilege_block()
|
|
{
|
|
PRV privilege_block = (PRV) MSC_alloc(PRV_LEN);
|
|
privilege_block->prv_privileges = PRV_no_privs;
|
|
privilege_block->prv_username = 0;
|
|
privilege_block->prv_relation = 0;
|
|
privilege_block->prv_fields = 0;
|
|
privilege_block->prv_next = 0;
|
|
|
|
return privilege_block;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Push an arbitrary object onto a linked list stack.
|
|
//
|
|
|
|
void MSC_push( gpre_nod* object, gpre_lls** pointer)
|
|
{
|
|
gpre_lls* stack = free_lls;
|
|
if (stack)
|
|
free_lls = stack->lls_next;
|
|
else
|
|
stack = (gpre_lls*) MSC_alloc(LLS_LEN);
|
|
|
|
stack->lls_object = object;
|
|
stack->lls_next = *pointer;
|
|
*pointer = stack;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a reference and possibly link the reference into
|
|
// a linked list.
|
|
//
|
|
|
|
ref* MSC_reference(ref** link)
|
|
{
|
|
ref* reference = (ref*) MSC_alloc(REF_LEN);
|
|
|
|
if (link)
|
|
{
|
|
reference->ref_next = *link;
|
|
*link = reference;
|
|
}
|
|
|
|
return reference;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Set up for a new request. Make request and action
|
|
// blocks, all linked up and ready to go.
|
|
//
|
|
|
|
gpre_req* MSC_request(req_t type)
|
|
{
|
|
gpre_req* request = (gpre_req*) MSC_alloc(REQ_LEN);
|
|
request->req_type = type;
|
|
request->req_next = gpreGlob.requests;
|
|
gpreGlob.requests = request;
|
|
|
|
request->req_routine = (gpre_req*) gpreGlob.cur_routine->act_object;
|
|
gpreGlob.cur_routine->act_object = (ref*) request;
|
|
|
|
if (!(gpreGlob.cur_routine->act_flags & ACT_main))
|
|
request->req_flags |= REQ_local;
|
|
if (gpreGlob.sw_sql_dialect <= SQL_DIALECT_V5)
|
|
request->req_flags |= REQ_blr_version4;
|
|
|
|
return request;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Copy a string into a permanent block.
|
|
//
|
|
|
|
SCHAR* MSC_string(const TEXT* input)
|
|
{
|
|
TEXT* string = (TEXT*) MSC_alloc(static_cast<int>(strlen(input) + 1));
|
|
strcpy(string, input);
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Allocate and initialize a symbol block.
|
|
//
|
|
|
|
gpre_sym* MSC_symbol(sym_t type, const TEXT* string, USHORT length, gpre_ctx* object)
|
|
{
|
|
gpre_sym* symbol = (gpre_sym*) MSC_alloc(SYM_LEN + length);
|
|
symbol->sym_type = type;
|
|
symbol->sym_object = object;
|
|
TEXT* p = symbol->sym_name;
|
|
symbol->sym_string = p;
|
|
|
|
if (length)
|
|
memcpy(p, string, length);
|
|
|
|
return symbol;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make a ternary node.
|
|
//
|
|
|
|
gpre_nod* MSC_ternary(nod_t type, gpre_nod* arg1, gpre_nod* arg2, gpre_nod* arg3)
|
|
{
|
|
gpre_nod* node = MSC_node(type, 3);
|
|
node->nod_arg[0] = arg1;
|
|
node->nod_arg[1] = arg2;
|
|
node->nod_arg[2] = arg3;
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make a unary node.
|
|
//
|
|
|
|
gpre_nod* MSC_unary(nod_t type, gpre_nod* arg)
|
|
{
|
|
gpre_nod* node = MSC_node(type, 1);
|
|
node->nod_arg[0] = arg;
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Set up for a new username.
|
|
//
|
|
|
|
gpre_usn* MSC_username(const SCHAR* name, USHORT name_dyn)
|
|
{
|
|
gpre_usn* username = (gpre_usn*) MSC_alloc(USN_LEN);
|
|
char* newname = (char*) MSC_alloc(static_cast<int>(strlen(name) + 1));
|
|
username->usn_name = newname;
|
|
strcpy(newname, name);
|
|
username->usn_dyn = name_dyn;
|
|
|
|
username->usn_next = 0;
|
|
|
|
return username;
|
|
}
|
|
|