/*
* Copyright (c) 1995, 1996, 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
*
* This file is part of Flick, the Flexible IDL Compiler Kit.
*
* Flick is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Flick is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Flick; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
*/
#include "helpers.hh"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <mom/compiler.h>
#include <mom/libmeta.h>
#include <mom/libaoi.h>
/*
* `ALLOW_ROOT_TYPECODE' allows IDL specifications to use `TypeCode' as a
* built-in equivalent to `CORBA::TypeCode'. (This is not standard CORBA IDL.)
*
* If `ALLOW_ROOT_TYPECODE' is defined, IDL files need not `#include <orb.idl>'
* in order to use `TypeCode'. In short, we handle `TypeCode' in much the same
* way as we handle `Object' as a built-in. References to `CORBA::TypeCode'
* are always interpreted correctly, whether or not this symbol is defined.
*
* XXX --- Really, `ALLOW_ROOT_TYPECODE' is wrong: correct IDL must refer to
* `CORBA::TypeCode', not simply `TypeCode'. We support this behavior only
* because TAO 0.3.23 allows it. In the near future, we will undefine this
* symbol by default.
*/
#define ALLOW_ROOT_TYPECODE (1)
/*****************************************************************************/
extern int warningcount;
extern int errorcount;
extern io_file_index builtin_file;
extern io_file_index root_file;
extern io_file_index current_i_file;
/* #define PACKED - use this for 6 chars/word packing */
#define UPCASE(ch) ((ch >= 'a' && ch <= 'z') ? (ch & 0x5F) : ch)
/*
* Case-sensitive string comparison. We wrap `strcmp' within a C++ function in
* order to avoid a warning from the Sun WorkShop C++ 5.0 compiler about C/C++
* linkage:
*
* ``Warning (Anachronism): Using extern "C" int(*)(const char*,const char*) to
* initialize int(*)(const char*,const char*).''
*/
static int
string_cmp(const char *a, const char *b)
{
return strcmp(a, b);
}
/*
* Case-insentive string comparison. XXX --- This should be rewritten simply
* as a C++ wrapper around `flick_strcasecmp'.
*/
static int
string_icmp(const char *a, const char *b)
{
while (*a && *b) {
if (UPCASE(*a) != UPCASE(*b))
return UPCASE(*a) - UPCASE(*b);
a++, b++;
}
if (*a != *b)
return (*a ? 1 : -1);
return 0;
}
typedef int (*cmp)(const char *, const char *);
static cmp compare = &string_cmp;
static ref_list *the_scope = 0;
/* `undefined' stores names that are reported as undefined. */
static VoidArray undefined;
#define UNDEFINED_ARRAY_ELEM_TYPE const char *
/*****************************************************************************/
void
AddScope(char *a)
{
scope++;
assert(a);
ref_list *end;
if (!the_scope)
the_scope = new ref_list(a, 0);
else {
end = the_scope;
while (end->next)
end = end->next;
end->next = new ref_list(a, 0);
}
}
void
DelScope()
{
assert(the_scope);
ref_list *tmp, tmp2(0, the_scope);
tmp = &tmp2;
while (tmp->next->next)
tmp = tmp->next;
if (tmp->next == the_scope)
the_scope = 0;
delete tmp->next;
tmp->next = 0;
scope--;
}
static const char *
GetFullScopePrefix(ref_list *sc = the_scope)
{
if (!sc)
return "";
if (!sc->next)
return flick_asprintf("%s::", sc->name);
return flick_asprintf("%s::%s",
sc->name,
GetFullScopePrefix(sc->next));
}
/*****************************************************************************/
void
DupeError(aoi_def *d, aoi_kind kind)
{
/* Override the `kind' passed in, if this has already been defined. */
if (d->binding)
kind = d->binding->kind;
if (*d->name && /* if not "" */
(kind != AOI_ERROR)) {
int pos;
pos = cur_aoi.defs.defs_len - 1;
while( (pos >= 0) &&
(cur_aoi.defs.defs_val[pos].scope >= scope) )
pos--;
/* Disallow using the name of the
immediately enclosing scope */
if ((pos < 0) ||
((!cur_aoi.defs.defs_val[pos].name ||
((cur_aoi.defs.defs_val[pos].scope + 1) != d->scope) ||
strcmp(cur_aoi.defs.defs_val[pos].name, d->name)) &&
!aoi_def_has_member(&cur_aoi, &cur_aoi.defs.defs_val[pos],
d->name))) {
cmp func = compare;
compare = &string_icmp;
/* Find this name, but don't report errors. */
pos = FindLocalName(d->name, 0);
compare = func;
if (pos < 0) /* It wasn't found; no problem... */
return;
if (cur_aoi.defs.defs_val[pos].scope != d->scope)
return;
/* Forward interface cases. */
if ((cur_aoi.defs.defs_val[pos].binding->kind ==
AOI_INTERFACE)
&& (kind == AOI_FWD_INTRFC))
return;
if ((cur_aoi.defs.defs_val[pos].binding->kind ==
AOI_FWD_INTRFC)
&& (kind == AOI_INTERFACE))
return;
if ((cur_aoi.defs.defs_val[pos].binding->kind ==
AOI_FWD_INTRFC)
&& (kind == AOI_FWD_INTRFC))
return;
/* Errors and namespaces. */
if (cur_aoi.defs.defs_val[pos].binding->kind ==
AOI_ERROR)
return;
if ((cur_aoi.defs.defs_val[pos].binding->kind ==
AOI_NAMESPACE)
&& (kind == AOI_NAMESPACE))
return;
}
SemanticError("`%s' already defined", d->name);
}
#if 0 /* KBF - Hopefully, this is now fixed */
int pos = GetScopedNameList(the_scope);
if (pos >= 0) {
if (!i)
i = 1;
else
i = (cur_aoi.defs.defs_val[pos].binding->kind
!= AOI_FWD_INTRFC);
if (i && (cur_aoi.defs.defs_val[pos].binding->kind !=
AOI_ERROR)) {
SemanticError("`%s' already defined", a);
}
}
#endif /* 0 */
}
void
UndefError(char *name)
{
for (int i = 0; i < undefined.cur_num; ++i)
if (!compare(name,
ARRAY_REF(undefined,
UNDEFINED_ARRAY_ELEM_TYPE,
i)
))
return;
SemanticError("`%s' not defined", name);
ADD_TO_ARRAY(undefined, UNDEFINED_ARRAY_ELEM_TYPE, name);
}
/* Simply allocates and initializes a new `aoi_def'. */
aoi_def *
new_aoi_def(const char *name, int scope)
{
aoi_def *def = (aoi_def *) mustcalloc(sizeof(aoi_def));
def->name = ir_strlit(name);
def->scope = scope;
return def;
}
int
new_error_ref(const char *name)
{
aoi_def *error_def;
error_def = new_aoi_def(name, scope);
error_def->idl_file = 0;
error_def->binding = (aoi_type) mustcalloc(sizeof(aoi_type_u));
error_def->binding->kind = AOI_ERROR;
AddDef(error_def, AOI_ERROR);
return cur_aoi.defs.defs_len - 1;
}
/*****************************************************************************/
static aoi_type
xl_predef_int(int min, unsigned range)
{
aoi_type node = (aoi_type) mustcalloc(sizeof(aoi_type_u));
node->kind = AOI_INTEGER;
node->aoi_type_u_u.integer_def.min = min;
node->aoi_type_u_u.integer_def.range = range;
return node;
}
#ifdef PACKED
static aoi_type
xl_predef_array_of_int(int array_min, unsigned array_range)
{
aoi_type t = (aoi_type) mustcalloc(sizeof(aoi_type_u));
t->kind = AOI_ARRAY;
t->aoi_type_u_u.array_def.element_type = xl_predef_int(0,4294967295U);
t->aoi_type_u_u.array_def.length_type = xl_predef_int(array_min,
array_range);
t->aoi_type_u_u.array_def.flgs = AOI_ARRAY_FLAG_NONE;
return t;
}
#else
static aoi_type
xl_predef_char(int bits)
{
aoi_type node = (aoi_type) mustcalloc(sizeof(aoi_type_u));
node->kind = AOI_CHAR;
node->aoi_type_u_u.char_def.bits = bits;
node->aoi_type_u_u.char_def.flags = AOI_CHAR_FLAG_NONE;
return node;
}
static aoi_type
xl_predef_string(int array_min, unsigned array_range)
{
aoi_type t = (aoi_type) mustcalloc(sizeof(aoi_type_u));
t->kind = AOI_ARRAY;
t->aoi_type_u_u.array_def.element_type = xl_predef_char(8);
t->aoi_type_u_u.array_def.length_type = xl_predef_int(array_min,
array_range);
t->aoi_type_u_u.array_def.flgs = AOI_ARRAY_FLAG_NULL_TERMINATED_STRING;
return t;
}
#endif /* PACKED */
/*****************************************************************************/
void
Start()
{
init_meta(&cur_aoi.meta_data);
meta_add_channel(&cur_aoi.meta_data,
meta_add_file(&cur_aoi.meta_data, "(generated)",
IO_FILE_INPUT),
"");
builtin_file = meta_add_file(&cur_aoi.meta_data,
"(builtin)",
IO_FILE_BUILTIN);
/*
* We strip off any leading path on `root_filename'. We don't want AOI
* files to differ based on the path to the input file.
*/
root_file = meta_add_file(&cur_aoi.meta_data,
file_part(root_filename),
IO_FILE_INPUT|IO_FILE_ROOT);
current_i_file = root_file;
cur_aoi.defs.defs_len = 0;
cur_aoi.defs.defs_val = (aoi_def *) mustcalloc(8*sizeof(aoi_def));
saved_aoi_len = 0; /* Initial value not important. */
aoi_length = 8;
cur_interface = GetNewInterface();
aoi_def *tmp = new_aoi_def("CORBA", 0);
tmp->binding = (aoi_type) mustcalloc(sizeof(aoi_type_u));
tmp->binding->kind = AOI_NAMESPACE;
AddDef(tmp, AOI_NAMESPACE);
cur_aoi.defs.defs_val[cur_aoi.defs.defs_len - 1].idl_file =
builtin_file;
tmp = new_aoi_def("Object", 1);
tmp->binding = (aoi_type) mustcalloc(sizeof(aoi_type_u));
tmp->binding->kind = AOI_FWD_INTRFC;
AddDef(tmp, AOI_FWD_INTRFC);
cur_aoi.defs.defs_val[cur_aoi.defs.defs_len - 1].idl_file =
builtin_file;
#ifdef ALLOW_ROOT_TYPECODE
/*
* A hack: TAO 0.3.23 allows IDL to use `TypeCode' instead of requiring
* one to `#include <orb.idl>' and then refer to `CORBA::TypeCode'. To
* support that behavior, we can make an implied `TypeCode' interface.
*/
tmp = new_aoi_def("TypeCode", 0);
tmp->binding = (aoi_type) mustcalloc(sizeof(aoi_type_u));
tmp->binding->kind = AOI_FWD_INTRFC;
AddDef(tmp, AOI_FWD_INTRFC);
cur_aoi.defs.defs_val[cur_aoi.defs.defs_len - 1].idl_file =
builtin_file;
#endif /* ALLOW_ROOT_TYPECODE */
NEW_ARRAY(undefined, UNDEFINED_ARRAY_ELEM_TYPE, "");
}
void
Finish()
{
/* Right now, there's nothing needed for cleanup. */
}
aoi_interface *
GetNewInterface(void)
{
aoi_interface *res = (aoi_interface *)
mustcalloc(sizeof(aoi_interface));
res->idl = AOI_IDL_CORBA;
/* XXX ---- This uses PACKED STRINGS, not char arrays. */
#ifdef PACKED
res->code_type = xl_predef_array_of_int(0, ~0);
#else
res->code_type = xl_predef_string(0, 66000);
#endif
res->code = 0;
res->parents.parents_len = 0;
res->parents.parents_val = 0;
res->op_code_type = res->code_type;
res->ops.ops_len = 0;
res->ops.ops_val = 0;
res->attribs.attribs_len = 0;
res->attribs.attribs_val = 0;
res->excepts.excepts_len = 0;
res->excepts.excepts_val = 0;
return res;
}
aoi_def *
AoiConst(types t, char *name, aoi_const val)
{
aoi_def *res = new_aoi_def(name, scope);
/* XXX --- Need to check type against kind. */
if (t != kERROR) {
res->binding = (aoi_type) mustcalloc(sizeof(aoi_type_u));
res->binding->kind = AOI_CONST;
res->binding->aoi_type_u_u.const_def.type = MakeAoiType(t);
res->binding->aoi_type_u_u.const_def.value = val;
}
return res;
}
aoi_def *
AddDef(aoi_def *def, aoi_kind kind)
{
DupeError(def, kind);
if (aoi_length == (signed int) cur_aoi.defs.defs_len) {
aoi_length += 8;
aoi_def *array = (aoi_def *) mustcalloc(sizeof(aoi_def)
* aoi_length);
for (int tmp = 0;
tmp <(signed int) cur_aoi.defs.defs_len;
++tmp)
array[tmp] = cur_aoi.defs.defs_val[tmp];
/* free(cur_aoi.defs.defs_val); */
cur_aoi.defs.defs_val = array;
}
def->idl_file = current_i_file;
cur_aoi.defs.defs_val[cur_aoi.defs.defs_len++] = *def;
return &cur_aoi.defs.defs_val[cur_aoi.defs.defs_len - 1];
}
void
AddAttrs(VoidArray *attrs)
{
if (!cur_interface->attribs.attribs_len) {
cur_interface->attribs.attribs_len
= attrs->cur_num;
cur_interface->attribs.attribs_val
= &(ARRAY_REF(*attrs, aoi_attribute, 0));
} else {
aoi_attribute *old = cur_interface->attribs.attribs_val;
int total = (attrs->cur_num
+ cur_interface->attribs.attribs_len);
int tmp;
cur_interface->attribs.attribs_val
= (aoi_attribute *) mustcalloc(sizeof(aoi_attribute)
* total);
for (tmp = 0;
tmp < (signed int) cur_interface->attribs.attribs_len;
++tmp)
cur_interface->attribs.attribs_val[tmp] = old[tmp];
for (int z = 0; z < attrs->cur_num; ++z)
cur_interface->attribs.attribs_val[tmp + z]
= ARRAY_REF(*attrs, aoi_attribute, z);
cur_interface->attribs.attribs_len = total;
}
}
void
AddOp(aoi_operation *op)
{
aoi_def fake_def;
fake_def.binding = 0;
fake_def.name = op->name;
fake_def.scope = scope;
DupeError(&fake_def, AOI_STRUCT);
aoi_operation *ops = (aoi_operation *)
mustcalloc(sizeof(aoi_operation)
* (cur_interface->ops.ops_len + 1));
for (int tmp = 0; tmp < (signed int) cur_interface->ops.ops_len; ++tmp)
ops[tmp] = cur_interface->ops.ops_val[tmp];
ops[cur_interface->ops.ops_len++] = *op;
/* free(cur_interface->ops.ops_val); */
cur_interface->ops.ops_val = ops;
}
void
AddParents(VoidArray *parents)
{
int ref;
cur_interface->parents.parents_len
= parents->cur_num;
cur_interface->parents.parents_val
= (aoi_type *) mustcalloc(sizeof(aoi_type) * parents->cur_num);
for (int tmp = 0; tmp < parents->cur_num; ++tmp) {
aoi_type par = (aoi_type) mustcalloc(sizeof(aoi_type_u));
par->kind = AOI_INDIRECT;
ref = par->aoi_type_u_u.indirect_ref = ARRAY_REF(*parents,
int, tmp);
if (cur_aoi.defs.defs_val[ref].binding
&& (cur_aoi.defs.defs_val[ref].binding->kind !=
AOI_INTERFACE)) {
SemanticError("`%s' is not defined as an interface",
cur_aoi.defs.defs_val[ref].name);
}
cur_interface->parents.parents_val[tmp] = par;
}
}
int
FindLocalName(char *name, int err)
{
ref_list *scopes = new ref_list(0, 0);
int cur_pos = cur_aoi.defs.defs_len - 1;
int last_scope = scope;
int res;
/* Build the maximum scoped name to search for. */
while (cur_pos >= 0) {
while ((cur_pos >= 0)
&& (cur_aoi.defs.defs_val[cur_pos].scope >= last_scope))
cur_pos--;
if (cur_pos >= 0) {
scopes = new ref_list(cur_aoi.defs.defs_val[cur_pos].
name, scopes);
last_scope = cur_aoi.defs.defs_val[cur_pos].scope;
}
}
/* Step through each possibility from `a::b::c' to `a::c' to `::c'. */
while (1) {
ref_list *tmp = scopes, *parent = scopes;
while (tmp->name) {
parent = tmp;
tmp = tmp->next;
}
tmp->name = name;
res = GetScopedNameList(scopes);
if (res >= 0)
return res;
if (parent == tmp) {
if (err) {
UndefError(name);
return new_error_ref(name);
}
return -1;
}
parent->name = 0;
parent->next = 0;
delete tmp;
}
}
int
FindGlobalName(char *name)
{
int res;
ref_list tmp(name, 0);
res = GetScopedNameList(&tmp);
if (res < 0) {
UndefError(name);
return new_error_ref(name);
}
return res;
}
int
FindScopedName(char *name, int ref)
{
ref_list *scopes = new ref_list(cur_aoi.defs.defs_val[ref].name,
new ref_list(name, 0));
int last_scope = cur_aoi.defs.defs_val[ref].scope;
/* Build the maximum scoped name to search for. */
while (ref >= 0) {
while ((cur_aoi.defs.defs_val[ref].scope >= last_scope) &&
(ref >= 0))
ref--;
if (ref >= 0) {
scopes = new ref_list(cur_aoi.defs.defs_val[ref].name,
scopes);
last_scope = cur_aoi.defs.defs_val[ref].scope;
}
}
int res = GetScopedNameList(scopes);
if (res < 0) {
UndefError(name);
return new_error_ref(name);
}
return res;
}
int
GetScopedNameList(ref_list *scopes)
{
int res, pos, last_if = -1;
for (pos = 0; pos < (signed int) cur_aoi.defs.defs_len; ++pos) {
if (!compare(scopes->name, cur_aoi.defs.defs_val[pos].name)
&& (cur_aoi.defs.defs_val[pos].scope == 0)) {
if (!scopes->next) {
/* The value is a top scope and we found it. */
if (cur_aoi.defs.defs_val[pos].binding
&& (cur_aoi.defs.defs_val[pos].binding->
kind == AOI_FWD_INTRFC))
last_if = pos;
else
return pos;
}
res = GetInsideScope(scopes->next, pos);
if (res >= 0) {
if (cur_aoi.defs.defs_val[res].binding
&& (cur_aoi.defs.defs_val[res].binding->
kind == AOI_FWD_INTRFC))
last_if = res;
else
return res;
}
}
}
return last_if;
}
int
GetInsideScope(ref_list *scopes, int pos)
{
/* Search for the scoped name ONLY within the specified scope. */
unsigned int top = pos + 1;
unsigned int bottom = pos + 1;
int par_scope = cur_aoi.defs.defs_val[pos].scope;
int res;
int last_if = -1;
while ((bottom < cur_aoi.defs.defs_len)
&& (cur_aoi.defs.defs_val[bottom].scope > par_scope))
bottom++;
while (top < bottom) {
if (!compare(scopes->name, cur_aoi.defs.defs_val[top].name)
&& (cur_aoi.defs.defs_val[top].scope == par_scope + 1)) {
if (!scopes->next) {
if (cur_aoi.defs.defs_val[top].binding
&& (cur_aoi.defs.defs_val[top].binding->
kind == AOI_FWD_INTRFC))
last_if = top;
else
return top;
}
res = GetInsideScope(scopes->next, top);
if (res >= 0) {
if (cur_aoi.defs.defs_val[res].binding
&& (cur_aoi.defs.defs_val[res].binding->
kind == AOI_FWD_INTRFC))
last_if = res;
else
return res;
}
}
top++;
}
return last_if;
}
types
GetConstType(aoi_ref type)
{
aoi_kind k = cur_aoi.defs.defs_val[type].binding->kind;
switch (k) {
case AOI_INTEGER: {
aoi_integer t = cur_aoi.defs.defs_val[type].binding->
aoi_type_u_u.integer_def;
if (t.min < -32768)
return kSLONG;
else if (t.min < 0)
return kSSHORT;
else if (t.range > 65536)
return kULONG;
else if (t.range > 256)
return kUSHORT;
else if (t.range > 1)
return kOCTET;
else
return kBOOL;
}
case AOI_FLOAT: {
aoi_float f = cur_aoi.defs.defs_val[type].binding->
aoi_type_u_u.float_def;
return ((f.bits > 32) ? kDOUBLE : kFLOAT);
}
case AOI_CHAR:
return kCHAR;
case AOI_INDIRECT:
return GetConstType(cur_aoi.defs.defs_val[type].binding->
aoi_type_u_u.indirect_ref);
case AOI_ERROR:
return kERROR;
default:
SemanticError("`%s' is not a valid type for a constant",
cur_aoi.defs.defs_val[type].name);
return kERROR;
}
}
aoi_const
GetConstVal(aoi_ref r)
{
if (cur_aoi.defs.defs_val[r].binding->kind == AOI_INDIRECT)
return GetConstVal(cur_aoi.defs.defs_val[r].binding->
aoi_type_u_u.indirect_ref);
if (cur_aoi.defs.defs_val[r].binding->kind == AOI_ERROR) {
aoi_const error_const = (aoi_const)
mustcalloc(sizeof(aoi_const_u));
error_const->kind = AOI_CONST_INT;
error_const->aoi_const_u_u.const_int = 0;
return error_const;
} else {
if (cur_aoi.defs.defs_val[r].binding->kind != AOI_CONST) {
SemanticError("incorrect type (not a constant)");
ConfusedExit();
}
return (cur_aoi.defs.defs_val[r].binding->aoi_type_u_u.
const_def.value);
}
}
/* A helper function for `GetAoiType', below. */
static int
GetAoiTypeSpecial(aoi_ref r, aoi_type at)
{
int is_special = 0;
aoi_ref scope_ref;
/*****/
if ((r < 0) || (r >= ((signed int) cur_aoi.defs.defs_len)))
InternalError("invalid `aoi_ref' in `GetAoiTypeSpecial'.");
/*
* If `r' refers to `CORBA::TypeCode', set `is_special' to true and
* set `at' to be an `AOI_TYPE_TAG'.
*/
if (!strcmp(cur_aoi.defs.defs_val[r].name, "TypeCode")) {
/* It's a `TypeCode', but is it a `CORBA::TypeCode'? */
scope_ref = aoi_get_parent_scope(&cur_aoi, r);
if ((scope_ref == aoi_ref_null)
|| strcmp(cur_aoi.defs.defs_val[scope_ref].name, "CORBA")
|| (cur_aoi.defs.defs_val[scope_ref].scope != 0)) {
/* It's not `CORBA::TypeCode'. */
is_special = 0;
} else {
/* Yes, it's `CORBA::TypeCode'. */
is_special = 1;
at->kind = AOI_TYPE_TAG;
}
#ifdef ALLOW_ROOT_TYPECODE
/*
* If we allow IDL to use `TypeCode', then references to that
* interface are special, too.
*/
if (scope_ref == aoi_ref_null) {
/* Yes, it's `TypeCode' in the root scope. */
is_special = 1;
at->kind = AOI_TYPE_TAG;
}
#endif /* ALLOW_ROOT_TYPECODE */
}
return is_special;
}
aoi_type
GetAoiType(aoi_ref r)
{
aoi_type res = (aoi_type) mustcalloc(sizeof(aoi_type_u));
/*
* The simple and overwhelmingly common case is simply to make an
* `AOI_INDIRECT' reference to the AOI definition at `r'; this
* represents a use of a named type.
*
* But there are special cases: e.g., a reference to `CORBA::TypeCode'
* must be turned into a literal `AOI_TYPE_TAG'. This special meaning
* for `CORBA::TypeCode' is part of the semantics of the CORBA IDL ---
* not particular to any single presentation --- and so we must make
* the translation here rather than in the PG. Special translations
* are handled by a separate `GetAoiTypeSpecial' function.
*/
if (GetAoiTypeSpecial(r, res) == 0) {
res->kind = AOI_INDIRECT;
res->aoi_type_u_u.indirect_ref = r;
}
return res;
}
aoi_type
MakeAoiType(types t)
{
aoi_type res = (aoi_type) mustcalloc(sizeof(aoi_type_u));
switch (t) {
case kBOOL:
res->kind = AOI_INTEGER;
res->aoi_type_u_u.integer_def.min = 0;
res->aoi_type_u_u.integer_def.range = 1U;
break;
case kCHAR:
res->kind = AOI_CHAR;
res->aoi_type_u_u.char_def.bits = 8;
res->aoi_type_u_u.char_def.flags = AOI_CHAR_FLAG_NONE;
break;
case kDOUBLE:
res->kind = AOI_FLOAT;
res->aoi_type_u_u.float_def.bits = 64;
break;
case kFLOAT:
res->kind = AOI_FLOAT;
res->aoi_type_u_u.float_def.bits = 32;
break;
case kOCTET:
res->kind = AOI_INTEGER;
res->aoi_type_u_u.integer_def.min = 0;
res->aoi_type_u_u.integer_def.range = 255U;
break;
case kSSHORT:
res->kind = AOI_INTEGER;
res->aoi_type_u_u.integer_def.min = -32768;
res->aoi_type_u_u.integer_def.range = 65535U;
break;
case kSLONG:
res->kind = AOI_INTEGER;
res->aoi_type_u_u.integer_def.min = (-2147483647 - 1);
res->aoi_type_u_u.integer_def.range = 4294967295U;
break;
case kUSHORT:
res->kind = AOI_INTEGER;
res->aoi_type_u_u.integer_def.min = 0;
res->aoi_type_u_u.integer_def.range = 65535U;
break;
case kULONG:
res->kind = AOI_INTEGER;
res->aoi_type_u_u.integer_def.min = 0;
res->aoi_type_u_u.integer_def.range = 4294967295U;
break;
case kOBJECT:
res->kind = AOI_INDIRECT;
res->aoi_type_u_u.indirect_ref = 1;
break;
case kANY:
/*
* A CORBA IDL `any' represents a type-tagged value, i.e., an
* `AOI_TYPED', not just an `AOI_ANY'.
*/
res->kind = AOI_TYPED;
res->aoi_type_u_u.typed_def.tag
= (aoi_type) mustcalloc(sizeof(aoi_type_u));
res->aoi_type_u_u.typed_def.tag->kind
= AOI_TYPE_TAG;
res->aoi_type_u_u.typed_def.type
= (aoi_type) mustcalloc(sizeof(aoi_type_u));
res->aoi_type_u_u.typed_def.type->kind
= AOI_ANY;
break;
case kERROR:
res->kind = AOI_ERROR;
break;
case kSLLONG:
case kULLONG:
res->kind = AOI_SCALAR;
res->aoi_type_u_u.scalar_def.bits = 64;
res->aoi_type_u_u.scalar_def.flags
= ((t == kULLONG) ?
AOI_SCALAR_FLAG_UNSIGNED :
AOI_SCALAR_FLAG_NONE);
break;
case kSTRING:
default:
InternalError("unknown type from which to create an AOI_TYPE");
break;
}
return res;
}
aoi_type
GetAoiTypeFromDecl(aoi_type type, Declaration d)
{
if (d.sizes.cur_num == 0)
return type;
else {
aoi_type res = (aoi_type) mustcalloc(sizeof(aoi_type_u));
res->kind = AOI_ARRAY;
res->aoi_type_u_u.array_def.length_type
= xl_predef_int(ARRAY_REF(d.sizes, unsigned int, 0),
0);
res->aoi_type_u_u.array_def.flgs = AOI_ARRAY_FLAG_NONE;
d.sizes.cur_num--;
d.sizes.data = &(ARRAY_REF(d.sizes, unsigned int, 1));
res->aoi_type_u_u.array_def.element_type
= GetAoiTypeFromDecl(type, d);
return res;
}
}
aoi_def *
GetAoiDefFromDecl(aoi_type type, Declaration d)
{
aoi_def *res = (aoi_def *) mustcalloc(sizeof(aoi_def));
res->scope = scope;
res->name = d.name;
res->binding = GetAoiTypeFromDecl(type, d);
return res;
}
aoi_const
GetReadRequest(char *attr_name)
{
return GetRequest(flick_asprintf("_get_%s", attr_name));
}
aoi_const
GetReadReply(char *attr_name)
{
return GetReply(flick_asprintf("<_get_%s", attr_name));
}
aoi_const
GetWriteRequest(char *attr_name, int val)
{
return (val ? 0 : GetRequest(flick_asprintf("_set_%s", attr_name)));
}
aoi_const
GetWriteReply(char *attr_name, int val)
{
return (val ? 0 : GetRequest(flick_asprintf("<_set_%s", attr_name)));
}
aoi_const
GetRequest(char *name)
{
return MakeConstPackedString(name);
}
aoi_const
GetReply(char *name)
{
return MakeConstPackedString(flick_asprintf("$%s", name));
}
aoi_const
GetInterfaceCode(char *name)
{
return MakeConstPackedString(flick_asprintf("%s%s",
GetFullScopePrefix(),
name));
}
unsigned int
GetPosInt(aoi_const c)
{
unsigned int res = 1;
if (!c)
InternalError(("null constant provided as positive constant "
"integer"));
else if (c->kind != AOI_CONST_INT)
SemanticError(("invalid type provided as positive constant "
"integer"));
else
res = (unsigned int) (c->aoi_const_u_u.const_int);
return res;
}
/*****************************************************************************/
int
isInt(aoi_const_u c)
{
return (c.kind == AOI_CONST_INT);
}
int
isFloat(aoi_const_u c)
{
return (c.kind == AOI_CONST_FLOAT);
}
#define INT_OPER(op1, op2, oper) { \
if (!op1 || !op2) \
InternalError("null constant passed to operator"); \
if (!isInt(*op1) || !isInt(*op2)) { \
SemanticError("invalid type passed to operator"); \
return op1; \
} \
return MakeConstInt(op1->aoi_const_u_u.const_int oper \
op2->aoi_const_u_u.const_int); \
}
aoi_const
const_or(aoi_const a, aoi_const b)
{
INT_OPER(a, b, |);
}
aoi_const
const_xor(aoi_const a, aoi_const b)
{
INT_OPER(a, b, ^);
}
aoi_const
const_and(aoi_const a, aoi_const b)
{
INT_OPER(a, b, &);
}
aoi_const
const_lshft(aoi_const a, aoi_const b)
{
INT_OPER(a, b, <<);
}
aoi_const
const_rshft(aoi_const a, aoi_const b)
{
INT_OPER(a, b, >>);
}
#define FLOAT_INT_OP(op1, op2, oper) { \
if (!op1 || !op2) \
InternalError("null constant passed to operator"); \
\
int isfloat = isFloat(*op1) || isFloat(*op2); \
\
if ( !(isInt(*op1) || isFloat(*op1)) \
|| !(isInt(*op2) || isFloat(*op2))) { \
SemanticError("invalid type passed to operator"); \
return op1; \
} \
if (isfloat) { \
double val1 = isInt(*op1) ? \
(double) op1->aoi_const_u_u.const_int : \
op1->aoi_const_u_u.const_float; \
double val2 = isInt(*op2) ? \
(double) op2->aoi_const_u_u.const_int : \
op2->aoi_const_u_u.const_float; \
return MakeConstReal(val1 oper val2); \
} else \
return MakeConstInt(op1->aoi_const_u_u.const_int oper \
op2->aoi_const_u_u.const_int); \
}
aoi_const
const_mul(aoi_const a, aoi_const b)
{
FLOAT_INT_OP(a, b, *);
}
aoi_const
const_div(aoi_const a, aoi_const b)
{
FLOAT_INT_OP(a, b, /);
}
aoi_const
const_add(aoi_const a, aoi_const b)
{
FLOAT_INT_OP(a, b, +);
}
aoi_const
const_sub(aoi_const a, aoi_const b)
{
FLOAT_INT_OP(a, b, +);
}
aoi_const
const_mod(aoi_const a, aoi_const b)
{
INT_OPER(a, b, %);
}
aoi_const
const_bit(aoi_const a)
{
if (!a)
InternalError("null constant passed to `~' operator");
if (!isInt(*a)) {
SemanticError("invalid type passed to `~' operator");
return a;
}
return MakeConstInt(~(a->aoi_const_u_u.const_int));
}
aoi_const
const_neg(aoi_const a)
{
if (!a)
InternalError("null constant passed to `-' operator");
if (isInt(*a))
return MakeConstInt(-(a->aoi_const_u_u.const_int));
if (isFloat(*a))
return MakeConstReal(-(a->aoi_const_u_u.const_float));
SemanticError("invalid type passed to `-' operator");
return a;
}
aoi_const
const_pos(aoi_const a)
{
if (!a)
InternalError("null constant passed to `+' operator");
if (!isInt(*a) || !isFloat(*a))
SemanticError("invalid type passed to `+' operator");
return a;
}
aoi_const
MakeConstInt(int a)
{
aoi_const res = (aoi_const) mustcalloc(sizeof(aoi_const_u));
res->kind = AOI_CONST_INT;
res->aoi_const_u_u.const_int = a;
return res;
}
aoi_const
MakeConstReal(double a)
{
aoi_const res = (aoi_const) mustcalloc(sizeof(aoi_const_u));
res->kind = AOI_CONST_FLOAT;
res->aoi_const_u_u.const_float = a;
return res;
}
aoi_const
MakeConstChar(char a)
{
aoi_const res = (aoi_const) mustcalloc(sizeof(aoi_const_u));
res->kind = AOI_CONST_CHAR;
res->aoi_const_u_u.const_char = a;
return res;
}
aoi_const
MakeConstString(char *a)
{
aoi_const res = (aoi_const) mustcalloc(sizeof(aoi_const_u));
int len = strlen(a) + 1;
res->kind = AOI_CONST_ARRAY;
res->aoi_const_u_u.const_array.aoi_const_array_len
= len;
res->aoi_const_u_u.const_array.aoi_const_array_val
= (aoi_const *) mustcalloc(sizeof(aoi_const) * len);
for (int tmp = 0; tmp < len; ++tmp) {
aoi_const elem = (aoi_const) mustcalloc(sizeof(aoi_const_u));
elem->kind = AOI_CONST_CHAR;
elem->aoi_const_u_u.const_char = a[tmp];
res->aoi_const_u_u.const_array.aoi_const_array_val[tmp] = elem;
}
return res;
}
#ifdef PACKED
static int
GetCharVal(char c)
{
switch (c) {
case '_':
return 27;
case '<':
return 28;
case '>':
return 29;
case '$':
return 30;
default:
return (c & 31);
}
}
#endif
aoi_const
MakeConstPackedString(char *a)
{
/*
* If you want to remove this optimization,
* `return MakeConstString(a)' and fix the code you'll find with an
* XXX about packed strings.
*/
#ifdef PACKED
aoi_const res = (aoi_const) mustcalloc(sizeof(aoi_const_u));
int slen = strlen(a);
int len = (slen + 5) / 6;
res->kind = AOI_CONST_ARRAY;
res->aoi_const_u_u.const_array.aoi_const_array_len
= len;
res->aoi_const_u_u.const_array.aoi_const_array_val
= (aoi_const *) mustcalloc(sizeof(aoi_const) * len);
for (int tmp = 0; tmp < len; ++tmp) {
aoi_const elem = (aoi_const) mustcalloc(sizeof(aoi_const_u));
elem->kind = AOI_CONST_INT;
int val = 0;
for (int z = 0; (tmp * 6 + z < slen) && (z < 6); ++z)
val = val * 32 + GetCharVal(a[tmp * 6 + z]);
elem->aoi_const_u_u.const_int = val;
res->aoi_const_u_u.const_array.aoi_const_array_val[tmp] = elem;
}
return res;
#else
return MakeConstString(a);
#endif /* PACKED */
}
/*****************************************************************************/
/*
* Check that the given `aoi_union_case' array does not already contain a case
* with the given discriminator value. If the value is found in the array,
* report an error.
*/
void
CheckUnionCaseDuplicate(VoidArray *void_array, aoi_union_case *new_case)
{
int i, j;
aoi_union_case * cases;
aoi_def fake_def;
/*****/
cases = (aoi_union_case *) (void_array->data);
for (i = 0; i < void_array->cur_num; ++i) {
if (aoi_const_eq(cases[i].val, new_case->val)) {
SemanticError("duplicate case value in union");
break;
}
for (j = 0; j < void_array->cur_num; j++) {
if (!strcmp(cases[i].var.name, new_case->var.name)) {
SemanticError("Case name '%s' already used",
new_case->var.name);
break;
}
}
}
fake_def.binding = 0;
fake_def.scope = scope;
fake_def.name = new_case->var.name;
DupeError(&fake_def, AOI_STRUCT);
}
/*****************************************************************************/
/*
* This will make a connection from the forward interfaces to their real
* interfaces.
*/
void
ResolveForwardInterfaces()
{
unsigned int i;
aoi_ref par_ref;
for (i = 0; i < cur_aoi.defs.defs_len; i++) {
if (cur_aoi.defs.defs_val[i].binding->kind == AOI_FWD_INTRFC) {
/*
* Set to -1 so we will know if it's been connected to
* a real interface or not. Note: This is needed for
* implied interfaces so that we will still make the
* stub.
*/
cur_aoi.defs.defs_val[i].binding->aoi_type_u_u.
fwd_intrfc_def = -1;
if (cur_aoi.defs.defs_val[i].idl_file !=
builtin_file) {
par_ref = aoi_deref_fwd(&cur_aoi, i);
/*
* If there isn't a real interface then signal
* a warning, but a marshal and unmarshal stub
* will still be made.
*/
if (par_ref == -1) {
SemanticWarning(
("interface `%s' has not been "
"defined"),
cur_aoi.defs.defs_val[i].name
);
}
cur_aoi.defs.defs_val[i].binding->aoi_type_u_u.
fwd_intrfc_def = par_ref;
}
}
}
}
/*****************************************************************************/
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1