File contents
/*ident "@(#)G2++:compsrc/desc.c 3.1" */
/******************************************************************************
*
* C++ Standard Components, Release 3.0.
*
* Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc.
* Copyright (c) 1988, 1989, 1990 AT&T. All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System
* Laboratories, Inc. The copyright notice above does not evidence
* any actual or intended publication of such source code.
*
******************************************************************************/
////--------------------------
//#include "descfns.h"
static char sccs_id[] = "@(#)G2++ compiler, version 082396";
#ifdef __GNUG__
#pragma implementation "Block.h"
#endif
#include <iostream.h>
#include <g2debug.h>
#include <Map.h>
#include <g2comp.h>
#include <g2ctype.h>
#include <g2io.h>
#include <g2io.h> /* needed for G2MAXDEPTH_ATTLC */
#include <g2mach.h>
#include <Block.h>
#include <stdlib.h>
struct X{
short pc;
short nel;
};
extern ostream& operator<<(ostream& os, const X& xval);
struct Y{
short pc;
short nel;
String size;
String align;
Y();
Y(const Y&);
Y& operator=(const Y&);
~Y();
};
extern ostream& operator<<(ostream& os, const Y& yval);
#ifdef _MSC_VER
Blockdeclare(X)
Blockdeclare(Y)
#endif
extern int pass2; // desc1 'pass' flag
extern int pc; // 'program counter'
extern int pctop; // max value assigned to pc
extern String dname; // descriptor name
#ifdef _MSC_VER
Mapdeclare(String,int)
extern Map(String,int) SoS; // record class names generated by 'ranstr'
#else
extern Map<String,int> SoS; // record class names generated by 'ranstr'
#endif
extern int cur_desc_level;
// Local functions
//inline int align(int offset, int align);
//inline int alignof(int ival);
X desc1(G2NODE*, G2NODE*, int, FILE*);
void desc12(int, G2NODE*, FILE*);
Y desc2(G2NODE*, G2NODE*, int, FILE*);
void desc3(G2NODE*, FILE*);
int gcd(int m, int n);
inline int INDEX(G2NODE* p);
//inline int lcm(int m, int n);
inline int NAME(G2NODE* p);
String xname(const String& name);
G2NODE* resolve(G2NODE* );
// Inline function definitions
inline
int NAME(G2NODE* p){
return isname1_ATTLC(p->name.char_at(0));
}
inline int
INDEX(G2NODE* p){
return isdigit_ATTLC(p->name.char_at(0));
}
#if 0
inline int
lcm(int m, int n){
return (m * n)/gcd(m,n);
}
inline int
align(int offset, int align){
return ((offset)+align-1)/align*align;
}
inline int
alignof(int ival){
return(
ival==LONG_INT_ATTLC ?(
LONG_ALIGN_ATTLC
):(
ival==STRING_INT_ATTLC ?(
STRING_ALIGN_ATTLC
):(
ival==CHAR_INT_ATTLC ?(
CHAR_ALIGN_ATTLC
):(
ival==SHORT_INT_ATTLC ?(
SHORT_ALIGN_ATTLC
):(
0
)
)
)
)
);
}
#endif
////--------------------------
ostream& operator<<(ostream& os, const X& xval) {
os << xval.pc << xval.nel << "\n";
return os;
}
Y::Y() : size(""), align("") {
pc = 0;
nel = 0;
}
Y::Y(const Y& y) : size(y.size), align(y.align) {
pc = y.pc;
nel = y.nel;
}
Y& Y::operator=(const Y& y) {
size = y.size;
align = y.align;
pc = y.pc;
nel = y.nel;
return *this;
}
Y::~Y() {}
ostream& operator<<(ostream& os, const Y& yval) {
os << yval.pc << yval.nel << yval.size << yval.align << "\n";
return os;
}
int pass2; // desc1 'pass' flag
int pc; // 'program counter'
int pctop; // max value assigned to pc
String dname; // descriptor name
int cur_desc_level = 0;
void
desc(G2NODE* gp, const String& name, FILE* f){
DEBUG(cerr << "enter desc with name=" << name << "\n" ;)
DEBUG(cerr << "and gp=\n";)
DEBUG(shownode_ATTLC(gp);)
// Recursively visits child nodes before their parents.
// consequently the root node is visited last.
// To make the root node the first entry in the descriptor
// table, two calls are made: the first emits only the root
// node; the second pass emits its descendents.
dname = name;
// fprintf(f, "static G2DESC %s[] = {\n", (const char*)dname);
fprintf(f, "static G2DESC %s_[] = {\n", (const char*)dname);
fprintf(f, " /* G2DESC fields:\n");
fprintf(f, " fieldname, type (L=leaf,S=struct,A=array), offset,\n");
fprintf(f, " size, number of elements (if it's a struct), ptr to first child,\n");
fprintf(f, " put func, get func., nullify func., isnull func. */\n");
fflush(f); // Debug
for(int pass=1; pass<=2; pass++){
DEBUG(cerr << "PASS " << pass << "\n" ;)
pass2 = (pass==2);
// desc1 generates the descriptor table with
// everything but size and offset filled in.
pc = 1;
desc1(NULL, // "parent node"
gp, // pointer to node describing type
0, // level
f // .c file
);
}
fprintf(f, "};\n\n");
fflush(f); // Debug
// desc2 generates static constructors containing
// size and offset computations
// fprintf(f, "static struct %s__{\n", (const char*)dname);
fprintf(f, "struct %s__{\n", (const char*)dname);
fprintf(f, "// The doinit() function in this class initializes\n");
// fprintf(f, "// the information in the table %s\n", (const char*)dname);
fprintf(f, "// the information in the table %s_\n", (const char*)dname);
fprintf(f, " int init_flag;\n");
fprintf(f, " void init() { if (!init_flag) doinit(); }\n");
fprintf(f, " void doinit();\n");
fprintf(f, " %s__() { init(); }\n", (const char*)dname);
// fprintf(f, "} %s___;\n\n", (const char*)dname);
fprintf(f, "};\nstatic struct %s__ %s___;\n\n",
(const char*)dname, (const char*)dname);
fprintf(f, "void %s__::doinit() {\n", (const char*)dname);
fprintf(f, " init_flag = 1;\n");
pctop = pc-1; // the highest assigned pc
pc = 1;
cur_desc_level=0;
desc2(NULL, // "parent node"
gp, // pointer to node describing type
0, // level
f // .c file
);
fprintf(f, "}\n\n");
// desc12 generates the body of the constructor
// for structures
DEBUG( cerr << "ready to call desc12\n"; )
desc12(0,gp,f);
}
X
desc1(G2NODE* gp, G2NODE* p, int level, FILE* f){
X result;
#ifdef _MSC_VER
Block(X) x(100);
#else
Block<X> x(100);
#endif
int i;
String name;
G2NODE* xp;
G2NODE tp; // local copy
DEBUG(cerr << "enter desc1\n";)
// The first loop does two things:
//
// 1. Sets x[i]'s for p and all its siblings
// that are not leaf nodes.
// 2. Generates 'anonymous' descriptors for
// array elements.
i = 0;
for(xp=p; xp && !(i>0 && gp==0); xp=g2next_ATTLC(xp), i++){
if(i==x.size()){
x.size((unsigned int)(1.414*x.size()));
DEBUG(cerr << "increase size of x to " << (X*)x.end()-(X*)x
<< "\n" ;)
}
DEBUG(cerr << "in for loop, xp=\n";)
DEBUG(showtree_ATTLC(xp,1);)
name = xp->name; // save current name
// Resolve the type of xp
// Example:
//
// a
// b LONG
// c SHORT
//
// d a
//
// After "resolving," tp will contain
//
// d
// b LONG
// c SHORT
//
tp=*resolve(xp);
tp.name = name; // restore current name
DEBUG(cerr << "after resolving, tp=\n"; )
DEBUG(showtree_ATTLC(&tp,1); )
if(g2child_ATTLC(&tp)){
// Tp is an array or structure. Recursively visit
// its children.
DEBUG(cerr << "g2chld(&tp) is true\n";)
DEBUG( cerr << "ready to call desc1 recursively\n"; )
x[i] = (desc1(&tp, g2child_ATTLC(&tp), level+1, f));
DEBUG(cerr << "back from desc1 for tp=\n";)
DEBUG(showtree_ATTLC(&tp,1);)
DEBUG(cerr << "the return value was:\n" << "\n"
<< " x[" << i << "].pc=" << x[i].pc << "\n"
<< " x[" << i << "].nel=" << x[i].nel << "\n" ;)
if(NAME(g2child_ATTLC(&tp))){ // letters, underscore
// Tp is a structure.
DEBUG(cerr << "Name(g2child_ATTLC(&tp) is true\n";)
if(INDEX(&tp)){
DEBUG(cerr << "INDEX(&tp) is true\n";)
// Corresponds to a case like this:
//
// 10
// h LONG
// i CHAR
//
// Manufacture an anonymous structure.
DEBUG(cerr << "manufacture anonymous struct\n";)
if((int)(level>0) ^ !pass2){
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
// "/*%d*/\t{%s,\t'S',\t%d,\t%d,\t%d,\t%s+%d,\t%d,\t%d},\n",
"/*%d*/\t{%s,\t'S',\t%d,\t%d,\t%d,\t%s_+%d,\t%d,\t%d},\n",
pc,
(const char*)xname(""), // field name
0, // offset
0, // size
x[i].nel, // number of elements
(const char*)dname, // name of array
x[i].pc, // index into array
0,
0
);
}
x[i].pc = pc++;
DEBUG(cerr << "x[" << i << "].pc=" << x[i].pc << "\n" ;)
}
}
}else{
// Tp is a leaf node.
if(INDEX(&tp)){
DEBUG(cerr << "INDEX(&tp) is true\n";)
// Tp is an index.
// Corresponds to a case like this:
//
// 10 CHAR
//
// Manufacture an anonymous leaf
DEBUG(cerr << "manufacture anonymous leaf\n";)
if(tp.val.char_at(0)=='-' ||
isdigit_ATTLC(tp.val.char_at(0))){
// Builtin type
int ival = atoi((const char*)tp.val);
DEBUG(cerr << "builtin type: ival = " << ival << "\n"; )
int nel=0;
if(ival>=0){
nel=ival;
ival=STRING_INT_ATTLC;
}
DEBUG(cerr << "ival=" << ival << "\n"
<< "nel=" << nel << "\n" ;)
if((int)(level>0) ^ !pass2){
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
"/*%d*/\t{%s,\t'L',\t%d,\t%d,\t%d,\t%d,\t%d,\t%d},\n",
pc,
(const char*)xname(""), // field name
0, // offset
0, // size
nel, // jfi
0,
0,
0
);
}
}else{
// User-defined type
DEBUG(cerr << "user-defined type\n";)
if((int)(level>0) ^ !pass2){
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
"/*%d*/\t{%s,\t'L',\t%d,\t%d,\t%d,\t%d,\tx_put_%s,\tx_get_%s,\t%s_nullify,\t%s_is_null},\n",
pc,
(const char*)xname(""), // field name
0, // offset
0, // size
0, // jfi
0,
(const char*)tp.val,
(const char*)tp.val,
(const char*)tp.val,
(const char*)tp.val
);
}
}
x[i].pc = pc++;
DEBUG(cerr << "x[" << i << "].pc=" << x[i].pc << "\n" ;)
}
}
}
// Begin debug:
DEBUG(i = 0;)
DEBUG(cerr << "*************At end of first loop:\n";)
DEBUG(for(xp=p; xp && !(i>0 && gp==0); xp=g2next_ATTLC(xp), i++){
DEBUG(showtree_ATTLC(xp,0);)
DEBUG(cerr
<< " x[" << i << "].pc =" << x[i].pc << "\n"
<< " x[" << i << "].nel =" << x[i].nel << "\n" ;)
})
// End debug
// The second loop does two things:
//
// 1. Sets x[i]'s for leaf nodes
// 2. Outputs a descriptor for each sibling
DEBUG(cerr << "Output a descriptor for each sibling\n";)
result.pc = pc;
i = 0;
for(xp=p; xp && !(i>0 && gp==0); xp=g2next_ATTLC(xp), i++){
DEBUG(cerr << "in for loop, xp=\n";)
DEBUG(showtree_ATTLC(xp,1);)
DEBUG(cerr << "...and i=" << i << "\n" ;)
DEBUG(cerr << "...and\n" << " x[" << i << "].pc=" << x[i].pc
<< "\n" ;)
name=xp->name; // save current name
// Resolve indirection - make a local copy
tp=*resolve(xp);
tp.name = name; // restore current name
DEBUG(cerr << "after resolving tp=\n";)
DEBUG(showtree_ATTLC(&tp,1);)
if(NAME(&tp)){
DEBUG(cerr << "NAME(&tp) is true\n";)
if(g2child_ATTLC(&tp)){
DEBUG(cerr << "g2child_ATTLC(&tp) is true\n";)
if(NAME(g2child_ATTLC(&tp))){
DEBUG(cerr << "NAME(g2child_ATTLC(&tp) is true\n";)
// Create a Structure descriptor
// Example:
//
// x
// y CHAR
// z LONG
if((int)(level>0) ^! pass2){
DEBUG(cerr
<< "pc=" << pc << "\n"
<< "dname=" << dname << "\n"
<< "i=" << i << "\n"
<< "xname(xp->name)=" << xname(xp->name) << "\n" ;)
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
// "/*%d*/\t{%s,\t'S',\t%d,\t%d,\t%d,\t%s+%d,\t%d,\t%d},\n",
"/*%d*/\t{%s,\t'S',\t%d,\t%d,\t%d,\t%s_+%d,\t%d,\t%d},\n",
pc,
(const char*)xname(xp->name), // field name
0, // offset
0, // size
x[i].nel, // number of elements
(const char*)dname, // name of array
x[i].pc, // index into array
0,
0
);
}
}else{
// Create an Array descriptor
// Example:
//
// x
// 10 CHAR
int nel=atoi((const char*)g2child_ATTLC(&tp)->name);
DEBUG(cerr << "nel=" << nel << "\n" ;)
if((int)(level>0) ^! pass2){
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
// "/*%d*/\t{%s,\t'A',\t%d,\t%d,\t%d,\t%s+%d,\t%d,\t%d},\n",
"/*%d*/\t{%s,\t'A',\t%d,\t%d,\t%d,\t%s_+%d,\t%d,\t%d},\n",
pc,
(const char*)xname(xp->name), // field name
0, // offset
0, // jfi
nel, // number of elements
(const char*)dname, // name of array
x[i].pc, // index into array
0,
0
);
}
}
}else{
// Create a Leaf descriptor
// Example:
//
// x CHAR
//
DEBUG(cerr << "leaf\n";)
if(tp.val.char_at(0)=='-' ||
isdigit_ATTLC(tp.val.char_at(0))){
// Builtin type
int ival = atoi((const char*)tp.val);
int nel=0;
if(ival>=0){
nel=ival;
ival=STRING_INT_ATTLC;
}
ival += 1;
DEBUG(cerr << "ival=" << ival << "\n" ;)
if((int)(level>0) ^! pass2){
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
"/*%d*/\t{%s,\t'L',\t%d,\t%d,\t%d,\t%d,\t%d,\t%d},\n",
pc,
(const char*)xname(xp->name), // field name
0, // offset
0, // size
nel, // jfi
0,
0,
0
);
}
}else{
// User-defined type
DEBUG(cerr << "user-defined type\n";)
if((int)(level>0) ^! pass2){
DEBUG(cerr << "put out descriptor\n";)
fprintf(f,
"/*%d*/\t{%s,\t'L',\t%d,\t%d,\t%d,\t%d,\tx_put_%s,\tx_get_%s,\t%s_nullify,\t%s_is_null},\n",
pc,
(const char*)xname(xp->name), // field name
0, // offset
0, // size
0, // jfi
0,
(const char*)tp.val,
(const char*)tp.val,
(const char*)tp.val,
(const char*)tp.val
);
}
}
}
pc++;
DEBUG(cerr << "pc++ =" << pc << "\n" ;)
}else{
if(gp && NAME(gp)){
// An index under a name is hoisted into the name
// and, so here, we just skip over to the child
result = x[i];
}else{
int nel = atoi((const char*)(&tp)->name);
DEBUG(cerr << "nel=" << nel << "\n" ;)
if((int)(level>0) ^! pass2){
DEBUG(cerr << "put out descriptor:\n";)
DEBUG(cerr
<< "/*"
<< pc
<< "*/\t{"
<< (const char*)xname("")
<< ",\t'A',\t0,\t0,\t"
<< nel
<< ",\t"
<< (const char*)dname
<< "+"
<< x[i].pc
<< "},\n"
;)
fprintf(f,
// "/*%d*/\t{%s,\t'A',\t%d,\t%d,\t%d,\t%s+%d},\n",
"/*%d*/\t{%s,\t'A',\t%d,\t%d,\t%d,\t%s_+%d},\n",
pc,
(const char*)xname(""), // field name
0, // offset
0, // size
nel, // number of elements
(const char*)dname, // name of array
x[i].pc // index into array
);
}
pc++;
}
}
}
result.nel = i;
// Begin debug:
DEBUG(i = 0;)
DEBUG(cerr << "*************At end of second loop:\n";)
DEBUG(for(xp=p; xp && !(i>0 && gp==0); xp=g2next_ATTLC(xp), i++){
DEBUG(showtree_ATTLC(xp,0);)
DEBUG(cerr << " x[" << i << "].pc =" << x[i].pc << "\n"
<< " x[" << i << "].nel =" << x[i].nel << "\n" ;)
})
// End debug
DEBUG(cerr << "ready to return from desc1\n";)
return result;
}
////--------------------------
//#include "descfns.h"
void
desc12(int level, G2NODE* gp, FILE* cf){
DEBUG( cerr << "enter desc12 with gp =\n"; )
DEBUG(showtree_ATTLC(gp,0);)
G2NODE* cp = g2child_ATTLC(gp);
if(cp==0)return;
G2NODE* t=cp;
do{
DEBUG(cerr << "ready to call desc12 recursively\n";)
desc12(level+1, t, cf);
}while(t=t->next);
DEBUG( cerr << "exit from t-loop\n"; )
if(cp && !isdigit_ATTLC(cp->name.char_at(0))){
// The node is a structure
DEBUG( cerr << "the node is a structure\n"; )
String name;
if(level>0){
name=upper(gp->val);
}else{
name=upper(gp->name);
}
DEBUG(cerr << "put to .c file:\n ***"
<< name << "::" << name << "()\n" ;)
fprintf(cf, "%s::%s()",
(const char*)name,
(const char*)name);
int first=1;
G2NODE *t;
for(t=cp; t; t=t->next){
int is_string = isdigit_ATTLC(t->val.char_at(0));
int is_block = (t->child &&
isdigit_ATTLC(t->child->name.char_at(0)));
if(is_string || is_block){
if(first){
first=0;
DEBUG(cerr << "put to .c file:\n ***:" ;)
fprintf(cf, ":\n ");
}else{
DEBUG(cerr << "put to .c file:\n ***," ;)
fprintf(cf, ",\n ");
}
if(is_string){
DEBUG( cerr << "is_string is true\n"; )
int size;
DEBUG(cerr << "t->val = " << t->val << '\n' ;)
if(t->val.char_at(0)=='0'){
// If there is an initial reserve specification of the
// form *(n), use it; otherwise, use the default
if(t->val.length()>=4 &&
t->val.char_at(1)=='('){
size=atoi(t->val.chunk(2));
}else{
size=DEFAULT_INITIAL_STRING_SIZE_ATTLC;
}
}else{
size=atoi(t->val);
}
DEBUG(cerr << "put to .c file:\n ***"
<< t->name << "(Stringsize(" << size << "+1))" ;)
fprintf(cf, "%s(Stringsize(%d+1))",
(const char*)t->name, size);
}else if(is_block){
DEBUG( cerr << "is_block is true\n"; )
int size;
DEBUG(cerr << "t->child->name = "
<< t->child->name << '\n' ;)
if(t->child->name.char_at(0)=='0'){
// If there is an initial reserve specification of the
// form *(n), use it; otherwise, use the default
if(t->child->name.length()>=4 &&
t->child->name.char_at(1)=='('){
size=atoi(t->child->name.chunk(2));
}else{
size=DEFAULT_INITIAL_BLOCK_SIZE_ATTLC;
}
}else{
size=atoi(t->child->name);
}
DEBUG(cerr << "put to .c file:\n ***"
<< t->name << "(" << size << ")" ;)
fprintf(cf, "%s(%d)", (const char*)t->name, size);
}
}
}
// The constructor body only calls g2clear_ATTLC
// at level 0
if(level==0){
DEBUG(cerr << "put to .c file:\n ***{\n"
<< "put to .c file:\n ***" << gp->name << "___.init();\n"
<< "put to .c file:\n ***{::g2clear_ATTLC(::"
<< gp->name << ",this);\n}\n"
;)
fprintf(cf, "\n{\n");
fprintf(cf, " %s___.init();\n", (const char*)gp->name);
// fprintf(cf, " ::g2clear_ATTLC(::%s,this);\n}\n",
// only call g2clear_ATTLC() if user-defined G2++ record type
if (! SoS.element(gp->name)) {
fprintf(cf, " ::g2clear_ATTLC(::%s_,this);\n",
(const char*) gp->name);
}
fprintf(cf, "}\n");
}else{
DEBUG(cerr << "put to .c file:\n ***{ }\n"; )
fprintf(cf, "{ }\n");
}
}
}
String
xname(const String& name){
DEBUG(cerr << "\nenter xname with name=" << name << "\n" ;)
if(name.is_empty()){
DEBUG(cerr << "name is empty\n";)
return String("0");
}else{
DEBUG(cerr << "name is non-empty\n";)
return '"' + name + '"';
}
}
int
gcd(int m, int n){
int i;
if(m < n){
return gcd(n,m);
}
if(i = m %n){
return gcd(n,i);
}
return n;
}
// Trace the type of p back to its original record
// definition and return a pointer to it.
G2NODE*
resolve(G2NODE* rp){
DEBUG(cerr << "enter resolve with rp->val= " << rp->val << "\n"; ;)
while(1){
if(rp->val.length()==0 ||
rp->val.char_at(0) == '-'){ // optimization
DEBUG( cerr << "optimization succeeded\n"; )
break;
}
G2NODE* yp=lookup(rp->val);
if(!yp){
break;
}
DEBUG(cerr << "lookup returned yp=\n"; )
DEBUG(showtree_ATTLC(yp,1);)
rp=yp;
}
return rp;
}
int inline
top(int i){
return (
i==pctop ?(
0
):(
i
)
);
}
Y
desc2(G2NODE* gp, G2NODE* p, int level, FILE* f){
Y result;
#ifdef _MSC_VER
Block(Y) x(100);
#else
Block<Y> x(100);
#endif
int i;
String name;
G2NODE* xp;
G2NODE tp; // local copy
DEBUG( cerr << "enter desc2 with level = " << level << endl; )
DEBUG( cerr << "and p = " << endl; )
DEBUG(showtree_ATTLC(p,0);)
DEBUG( cerr << "and gp = " << endl; )
DEBUG(showtree_ATTLC(gp,0);)
// The first loop sets x[i]'s for p and all
// its siblings that are not leaf nodes.
i = 0;
for(xp=p; xp && !(i>0 && gp==0); xp=g2next_ATTLC(xp), i++){
DEBUG( cerr << "in forloop" << endl; )
DEBUG( cerr << "xp = *********************" << endl; )
DEBUG(showtree_ATTLC(xp,0);)
if(i==x.size()){
x.size((unsigned int)(1.414*x.size()));
}
name = xp->name; // save current name
// Resolve the type of xp
// Example:
//
// a
// b LONG
// c SHORT
//
// d a
//
// After "resolving," tp will contain
//
// d
// b LONG
// c SHORT
//
tp=*resolve(xp);
tp.name = name; // restore current name
DEBUG( cerr << "after resolving, tp = " << endl; )
DEBUG( shownode_ATTLC(&tp); )
if(g2child_ATTLC(&tp)){
DEBUG( cerr << "tp is an array or structure" << endl; )
// Tp is an array or structure. Recursively visit
// its children.
DEBUG( cerr << "ready to call desc2 recursively" << endl; )
x[i] = (desc2(&tp, g2child_ATTLC(&tp), level+1, f));
DEBUG( cerr << "back from desc2 with tp = " << endl; )
DEBUG( shownode_ATTLC(&tp); )
if(NAME(g2child_ATTLC(&tp))){ // letters, underscore
DEBUG( cerr << "tp is a structure" << endl; )
// Tp is a structure.
x[i].align = ( "lcm(" + x[i].align + ",STRUCT_ALIGN_ATTLC)");
x[i].size = ( "align(" + x[i].size + "," + x[i].align + ")");
if(INDEX(&tp)){
DEBUG( cerr << "manufacture an anonymous structure" << endl; )
// Corresponds to a case like this:
//
// 10
// h LONG
// i CHAR
//
// Manufacture an anonymous structure.
fprintf(f,
// " %s[%d].offset=0;\n %s[%d].size=%s;\n\n",
" %s_[%d].offset=0;\n %s_[%d].size=%s;\n\n",
(const char*)dname,
top(pc),
(const char*)dname,
top(pc),
(const char*)x[i].size // size
);
x[i].pc = pc++;
}
}
else {
DEBUG( cerr << "tp is an array" << endl; )
// Tp is an array.
// x[i].align = ( "lcm(" + x[i].align + ",VBLOCK_ALIGN_ATTLC)");
x[i].align = ( "VBLOCK_ALIGN_ATTLC");
x[i].size = ( "align(" + x[i].size + "," + x[i].align + ")");
}
}else{
DEBUG( cerr << "tp is a leaf node" << endl; )
// Tp is a leaf node.
if(INDEX(&tp)){
DEBUG( cerr << "tp is an index" << endl; )
// Tp is an index.
// Corresponds to a case like this:
//
// 10 CHAR
//
// Manufacture an anonymous leaf
DEBUG(cerr << "manufacture anonymous leaf\n";)
if(tp.val.char_at(0)=='-' ||
isdigit_ATTLC(tp.val.char_at(0))){
// Builtin type
int ival = atoi((const char*)tp.val);
DEBUG(cerr << "builtin type: ival = " << ival << "\n"; )
if(ival>=0){
ival=STRING_INT_ATTLC;
}
x[i].align = ( "alignof(" + int_to_str(ival) + ")");
x[i].size = ( "(" + int_to_str(ival) + "+1)");
fprintf(f,
// " %s[%d].offset=0;\n %s[%d].size=%s;\n\n",
" %s_[%d].offset=0;\n %s_[%d].size=%s;\n\n",
(const char*)dname,
top(pc),
(const char*)dname,
top(pc),
(const char*)x[i].size // size
);
x[i].size = ("REALSIZE(" + int_to_str(ival+1) + ")");
x[i].pc = pc;
}else{
// User-defined type
DEBUG(cerr << "user-defined type\n";)
// x[i].align=tp.val + "_ALIGN";
x[i].align="get_" + tp.val + "_ALIGN()";
x[i].size=tp.val + "_SIZE";
/* the following statement helps to fix the "array of
user-defined types" bug */
fprintf(f,
" %s_[%d].nel=%s;/* sizeof user defined type */\n\n",
(const char*)dname,
top(pc),
(const char*)x[i].size // size
);
}
pc++;
}
}
}
// The second loop sets x[i]'s for leaf nodes.
result.pc = pc;
result.align = "1";
cur_desc_level++;
fprintf(f," align_val[%d] = 1;\n", cur_desc_level);
String size = "0";
i = 0;
for(xp=p; xp && !(i>0 && gp==0); xp=g2next_ATTLC(xp), i++){
name=xp->name; // save current name
DEBUG( cerr << "resolve indirection\n"; )
// Resolve indirection - make a local copy
tp=*resolve(xp);
tp.name = name; // restore current name
if(NAME(&tp)){
if(g2child_ATTLC(&tp)){
if(NAME(g2child_ATTLC(&tp))){
DEBUG( cerr << "create a structure descriptor\n"; )
// Create a Structure descriptor
// Example:
//
// x
// y CHAR
// z LONG
size = ( "align(" + size + "," + x[i].align + ")");
fprintf(f,
// " %s[%d].offset=%s;\n %s[%d].size=%s;\n\n",
" %s_[%d].offset=%s;\n %s_[%d].size=%s;\n\n",
(const char*)dname,
top(pc),
(const char*)size, // offset
(const char*)dname,
top(pc),
(const char*)x[i].size // size
);
// size = dname + "[" + int_to_str(top(pc)) + "].offset";
size = dname + "_[" + int_to_str(top(pc)) + "].offset";
size = ( "(" + size + "+" + x[i].size + ")");
}else{
DEBUG( cerr << "create an array descriptor\n"; )
// Create an Array descriptor
// Example:
//
// x
// 10 CHAR
size = ( "align(" + size + "," + x[i].align + ")");
fprintf(f,
// " %s[%d].offset=%s;\n %s[%d].size=VBLOCK_SIZE_ATTLC;\n\n",
" %s_[%d].offset=%s;\n %s_[%d].size=VBLOCK_SIZE_ATTLC;\n\n",
(const char*)dname,
top(pc),
(const char*)size, // offset
(const char*)dname,
top(pc)
);
// size = dname + "[" + int_to_str(top(pc)) + "].offset";
size = dname + "_[" + int_to_str(top(pc)) + "].offset";
size = ( "(" + size + "+VBLOCK_SIZE_ATTLC)");
}
}else{
DEBUG( cerr << "create a leaf descriptor\n"; )
DEBUG( cerr << "tp.name = " << tp.name << '\n'
<< "tp.val = " << tp.val << '\n' ;)
// Create a Leaf descriptor
// Example:
//
// login 0(20)
//
// Adjust the amount of space used since
// char, long, short, and String use different amounts
int ival=0;
if(tp.val.char_at(0)=='-' ||
isdigit_ATTLC(tp.val.char_at(0))){
DEBUG(cerr << "isdigit_ATTLC(tp.val.char_at(0)) returns TRUE\n";)
ival = atoi((const char*)tp.val);
DEBUG(cerr << "ival=" << ival << "\n" ;)
// A builtin type
DEBUG( cerr << "a builtin type\n"; )
if(ival>=0){
DEBUG(cerr << "it is a string\n";)
ival=STRING_INT_ATTLC;
}
ival += 1;
DEBUG(cerr << "prior to switch, ival=" << ival << "\n" ;)
switch(ival-1){
case CHAR_INT_ATTLC:{
DEBUG(cerr << "CHAR\n";)
x[i].align="CHAR_ALIGN_ATTLC";
x[i].size="CHAR_SIZE_ATTLC";
break;
}case SHORT_INT_ATTLC:{
DEBUG(cerr << "SHORT\n";)
x[i].align="SHORT_ALIGN_ATTLC";
x[i].size="SHORT_SIZE_ATTLC";
break;
}case LONG_INT_ATTLC:{
DEBUG(cerr << "LONG\n";)
x[i].align="LONG_ALIGN_ATTLC";
x[i].size="LONG_SIZE_ATTLC";
break;
}case STRING_INT_ATTLC:{
DEBUG(cerr << "STRING\n";)
x[i].align="STRING_ALIGN_ATTLC";
x[i].size="STRING_SIZE_ATTLC";
break;
}default:{
DEBUG(cerr << "Shouldn't get here\n";)
abort();
break;
}
}
}else if(isname_ATTLC(tp.val)){
// User-defined type
DEBUG(cerr << "user-defined type\n";)
// x[i].align=tp.val + "_ALIGN";
x[i].align="get_" + tp.val + "_ALIGN()";
x[i].size=tp.val + "_SIZE";
}else{
DEBUG(cerr << "shouldn't get here\n";)
abort();
}
// Common offset and size code
size = ( "align(" + size + "," + x[i].align + ")");
fprintf(f,
// " %s[%d].offset=%s;\n %s[%d].size=%d;\n\n",
" %s_[%d].offset=%s;\n %s_[%d].size=%d;\n\n",
(const char*)dname,
top(pc),
(const char*)size, // offset
(const char*)dname,
top(pc),
ival // size
);
if (ival == 0) {
fprintf(f, " %s_[%d].nel=%s; /* sizeof user defined type */\n\n",
(const char *)dname, top(pc), (const char *)x[i].size);
}
// size = dname + "[" + int_to_str(top(pc)) + "].offset";
size = dname + "_[" + int_to_str(top(pc)) + "].offset";
size = ( "(" + size + "+" + x[i].size + ")");
}
pc++;
}else{
if(gp && NAME(gp)){
// An index under a name is hoisted into the name
// and, so here, we just skip over to the child
result = x[i];
size = ( "(" + size + "+" + x[i].size + ")");
size = "(" + size + "+" + x[i].size + ")";
}else{
fprintf(f,
// " %s[%d].offset=%s;\n %s[%d].size=VBLOCK_SIZE_ATTLC;\n\n",
" %s_[%d].offset=%s;\n %s_[%d].size=VBLOCK_SIZE_ATTLC;\n\n",
(const char*)dname,
top(pc),
(const char*)size, // offset
(const char*)dname,
top(pc)
);
// size = dname + "[" + int_to_str(top(pc)) + "].offset";
size = dname + "_[" + int_to_str(top(pc)) + "].offset";
pc++;
size = ( "(" + size + "+VBLOCK_SIZE_ATTLC)"); }
}
/*
result.align = ( "lcm(" + result.align + "," + x[i].align + ")");
*/
fprintf(f, " align_val[%d] = lcm(align_val[%d], %s);\n",
cur_desc_level,
cur_desc_level,
(const char *) x[i].align
);
}
result.align = "align_val[" + int_to_str(cur_desc_level) + "]";
result.size = ( "align(" + size + "," + result.align + ")");
result.nel = i;
return result;
}
#ifdef _MSC_VER
Blockimplement(X)
Blockimplement(Y)
Blockimplement(String)
#endif
#ifdef __GNUG__
template class Block<X>;
template class Block<Y>;
template class Block<String>;
#endif