Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source libSC G2++ compsrc desc.c
Document Actions

desc.c

by Michael L Powell last modified 2007-01-26 03:23

Click here to get the file

Size 29.7 kB - File type text/plain

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
« April 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: