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

putrec.c

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

Click here to get the file

Size 14.5 kB - File type text/plain

File contents

/*ident	"@(#)G2++:g2++lib/putrec.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 <g2ctype.h>
#include <g2debug.h>
#include <g2io.h>
#include <Vblock.h>
#include <stdlib.h>
#include <iostream.h>
#ifdef __GNUG__
#define IOSTREAMH
#endif

static char sccs_id[] = "@(#)G2++ library, version 093096";

#ifdef IOSTREAMH
#define OSWRITE os.write
#else
#define OSWRITE os.put
#endif

static void emit_node(int, void*, G2DESC*, ostream& os);
static void emit_builtin(ostream& os, int, void*, int);

//  Current name hierarchy:

static struct {
	char* name;	       // NULL name implies index 
	int   index;
	int   maxarray;        // if maxarray != 0, it is an array size
} namestk[G2MAXDEPTH_ATTLC];  // TBD_fixed_limit

static int outlevel=0; // depth of name hierarchy 

static int
isnull_leaf(void *vp, G2DESC *rd) {
	int retval;
	if (rd->size == 0) { // user-defined type
		retval = rd->isn(vp);	// run the "is_null" function
					// for the user-defined type
	}
	else { // builtin type
		switch (rd->size) {
		case LONG_INT_ATTLC+1:
			retval = *(long*)vp == 0L;
			break;
		case SHORT_INT_ATTLC+1:
			retval = *(short*)vp == 0;
			break;
		case CHAR_INT_ATTLC+1:
			retval = *(char*)vp == 0;
			break;
		case STRING_INT_ATTLC+1:
		{
			String& temp = *(String*)vp;
			retval = temp.is_empty();
		}
		} /* end switch */
	}
	return (retval);
}

static int
isnull_general(void *base, G2DESC *rd) {
	int retval = 1;
	switch (rd->type) {
	case 'L':
		retval = isnull_leaf(base, rd);
		break;
	case 'S':
	{
		G2DESC *child = rd->child;
		int nel = rd->nel;
		for (; --nel >= 0; child++) {
			if (child->type != 'L') {
				void *vp;
				vp = (char*)base + child->offset;
				if (isnull_general(vp, child) == 0) {
					retval = 0;
					break;
				}
			}
			else {
				void *vp = ((char*)base + child->offset);
				if (!isnull_leaf(vp, child)) {
					retval = 0;
					break;
				}
			}
		}
		break;
	}
	case 'A':
	{
		void* vp = ((Vb_ATTLC*)base)->beginning();
		int nel = ((Vb_ATTLC*)base)->size();
		G2DESC* element = rd->child;
		if (element->type != 'L') {
			int i = 0;
			for (; --nel >= 0; vp = (char*)vp + element->size) {
				if (i >= rd->nel && rd->nel > 0) {
					break;
				}
				if (!isnull_general(vp, element)) {
					retval = 0;
					break;
				}
			}
		}
		else {
			int i = 0;
			for (; --nel >= 0; vp = ((char*)vp + REALSIZE(element->size)),i++) {
				if (i >= rd->nel && rd->nel > 0) {
					break;
				}
				if (!isnull_leaf(vp, element)) {
					retval = 0;
					break;
				}
				if (element->size == 0) {
					vp = (char*)vp + element->nel;
				}
			}
		}
	}
	} /* end switch */
	return (retval);
}
static int getmaxarray(void *base, G2DESC *rd) {
	void* vp = ((Vb_ATTLC*)base)->beginning();
	int nel = ((Vb_ATTLC*)base)->size();
	G2DESC* element = rd->child;
		
	int incr_size;
	if (element->type != 'L') {
		incr_size = element->size;
	}
	else {
		if (element->size == 0) {
			incr_size = element->nel;
		}
		else {
			incr_size = REALSIZE(element->size);
		}
	}
	int i = 0;
	int max_defined = -1;
	for (; --nel >= 0; vp = (char*)vp + incr_size) {
		if (!isnull_general(vp, element)) {
			// os << i << " ";
			if (i > max_defined) {
				max_defined = i;
			}
		}
		i++;
	}
	return (max_defined + 1);
}
	
//  Map a C structure to an output stream
int 
putrec_ATTLC(void* rec, G2DESC* rd, ostream& os) {
	g2err_ATTLC = 0;
	DEBUG(cerr << "\nenter putrec_ATTLC with rd=\n";)
	DEBUG(showdesc_ATTLC(rd);)
	DEBUG(cerr << "rec=" << rec << "\n";)

//  Emit name 

	os << rd->name;		// print the name of the record type
	DEBUG(cerr << "Emit name: " << rd->name << "\n";)
	DEBUG(cerr << "rd->type=" << char(rd->type) << '\n';)

	if (rd->type == 'L') { 
//  Record is a Leaf
		DEBUG(cerr << "Record is a leaf\n";)
		int size = rd->size;
		DEBUG(cerr << "size=" << size << "\n";)

		if (isnull_leaf(rec, rd)) {
			DEBUG(cerr << "null: filter out\n";)
		}
		else {
			if (size == 0) {
				DEBUG(cerr << "emit it by calling pfn\n";)
				rd->pfn(os,rec);
				DEBUG(cerr << "back from call to pfn\n";)
			}
			else {
				DEBUG(cerr << "emit tab\n";)
				os << '\t';
//  Call emit_builtin to emit value
				DEBUG(cerr << "emit value by calling emit_builtin\n";)
				emit_builtin(os, size, rec, rd->nel);
			}
		}
		DEBUG(cerr << "emit newline\n";)
		os << '\n';
	}
	else {
//  Record is a Structure or Array
		DEBUG(cerr << "Record is a Structure or Array\n";)
		if (rd->type == 'A') {
			os << '\t' << getmaxarray(rec, rd);
		}
		DEBUG(cerr << "emit newline\n";)
		os << '\n';
		namestk[0].name = rd->name;
		DEBUG(cerr << "namestk[0].name gets " << rd->name << "\n";)

//  Call emit_node with this record

		DEBUG(cerr << "Call emit_node with this record\n";)
		outlevel = 1;
		// call emit_node with level, base, record descriptor, output
		emit_node(1, rec, rd, os);
	}

//  Calculate checksum and return error flag

	DEBUG(cerr << "Calculate checksum and return error flag\n";)
	if (Cchksum(os)) {
		_g2putdot_ATTLC(os);
	}
	else {
		os << '\n';
	}
	/*Eor(os);*/
	return (Check_error(os)? -1 : 0);
}

//  Map a Structure or Array to the output stream
static void 
emit_node(int level, void* base, G2DESC* rd, ostream& os) {
	DEBUG(cerr << "\nenter emit_node with" << "\n" <<
		"    level=" << level << "\n" <<
		"    base=" << base << "\n";)
	DEBUG(cerr << "rd=\n";)
	DEBUG(showdesc_ATTLC(rd);)

	switch (rd->type) {
	case 'S':
	{
//  This node is a Structure
		DEBUG(cerr << "This node is a Structure\n";)
		G2DESC* child = rd->child;
		int nel = rd->nel;

		// loop through each child of this node
		for (; --nel >= 0; child++) {
			int i;
			DEBUG(cerr << "in loop, consider child:\n";)
			DEBUG(showdesc_ATTLC(child);)
			if (child->type != 'L') {
//  This child is an Array or Structure
				DEBUG(cerr << "This child is an Array "
					<< "or Structure\n";)
				namestk[level].name = child->name;
				DEBUG(cerr << "namestk[" << level 
					<< "].name gets " << child->name
					<< "\n";)
				if (child->type == 'A') {
					namestk[level].maxarray =
					  getmaxarray((char*)base + child->offset, child);
				}
				
//  Calculate vp

				void* vp;
				DEBUG(cerr << "Calculate vp\n";)
				vp = (char*)base + child->offset;
				DEBUG(cerr << "base=" << base << "\n"
					<< "child->offset=" << child->offset
					<< "\n"	<< "vp=" << vp 	<< "\n";)

//  Call emit_node recursively for this child 

				DEBUG(cerr << "Call emit_node recursively\n";)
				emit_node(level+1, vp, child, os);

//  Fiddle with outlevel (?)

				DEBUG(cerr << "Fiddle with outlevel\n";)
				DEBUG(cerr << "return from from emit_node with " 
					<< "outlevel=" << outlevel << "\n";)
				if (outlevel > level) {
					outlevel = level;
					DEBUG(cerr << "adjust outlevel to "
						<< outlevel << "\n";)
				}
			}
			else {

//  This child is a Leaf
//
//  Note: the calculation of vp is common to the then_case
//  and the else_case of this if; factor it out!

				DEBUG(cerr << "The child is a leaf\n";)
				void* vp = ((char*)base + child->offset);
				DEBUG(cerr << "vp=" << vp << "\n";)
//  Filter out nulls
				if (isnull_leaf(vp, child)) {
					DEBUG(cerr << "null: filter out\n";)
					continue;
				}

//  Emit name hierarchy 
				DEBUG(cerr << "Emit name hierarchy\n";)
				// do for each level in outlevel..level-1
				for(; outlevel < level; outlevel++) {
					DEBUG(cerr << "in for loop, outlevel="
						<< outlevel << "\n";)
					i = outlevel;
					DEBUG(cerr << "emit " << i << " tabs\n";)
					while (--i >= 0) {
						os << '\t';
					}
					char* cp = namestk[outlevel].name;
					if (cp) {
//  Name is alphabetic
						DEBUG(cerr << "Name is alphabetic: \n";)
						os << cp;
						DEBUG( cerr << cp << "\n"; )
					}
					else {
//  Name is an index
						DEBUG(cerr << "Name is an index: ";)
						os << namestk[outlevel].index;
						DEBUG(cerr << namestk[outlevel].index << "\n";)
					}
/* new code to put the size of the array in an array record */
					if (namestk[outlevel].maxarray != 0) {
						os << "\t" << namestk[outlevel].maxarray;
						namestk[outlevel].maxarray = 0;
					}
					DEBUG(cerr << "emit newline\n";)
					os << '\n';
				}
//  Emit a name-value pair
				DEBUG(cerr << "ready to emit leaf\n";)
				i = level;

				DEBUG(cerr << "emit " << i << " tabs\n";)
				while (--i >= 0) {
					os << '\t';
				}
				DEBUG(cerr << "emit name: " << child->name << '\n';)
				os << child->name;
				DEBUG(cerr << "emit tab\n";)
				os << '\t';

				if (child->size == 0) {
//  User-defined type (case 3)
					DEBUG(cerr << "User-defined type (case 3)\n";)
					child->pfn(os,vp);
					DEBUG(cerr << "back from call to pfn\n";)
				}
				else {
//  Builtin type
					DEBUG(cerr << "builtin type\n";)
					DEBUG(cerr << "vp=" << vp << "\n";)
//  Call emit_builtin
					emit_builtin(os, child->size, vp, child->nel);
				}
				DEBUG(cerr << "emit newline\n";)
				os << '\n';
			}
		}  
		break;
	}


	case 'A':
	{
//  This node is an Array
		DEBUG(cerr << "This node is an Array\n";)
		void* vp = ((Vb_ATTLC*)base)->beginning();
		DEBUG(cerr << "base=" << base << "\n" << "vp=" << vp << "\n";)
		int nel = ((Vb_ATTLC*)base)->size();
		DEBUG(cerr << "rd->nel=" << rd->nel << "\n" << "nel=" 
			<< nel << "\n";)
		G2DESC* element = rd->child;
		DEBUG(cerr << "element=\n";)
		DEBUG(showdesc_ATTLC(element);)
		
		int incr_size;
		if (element->type != 'L') {
			incr_size = element->size;
		}
		else {
			if (element->size == 0) {
				incr_size = element->nel;
			}
			else {
				incr_size = REALSIZE(element->size);
			}
		}
		int i = 0;
		int max_defined = 0;
		for (; --nel >= 0; vp = (char*)vp + incr_size) {
			if (!isnull_general(vp, element)) {
				// os << i << " ";
				if (i > max_defined) {
					max_defined = i;
				}
			}
			i++;
		}
//		namestk[level].maxarray = max_defined + 1;

		vp = ((Vb_ATTLC*)base)->beginning();
		nel = ((Vb_ATTLC*)base)->size();

		if (element->type != 'L') {
//  Element type is 'A' or 'S
			DEBUG(cerr << "Element type is 'A or 'S'\n";)
			namestk[level].name = NULL;
			DEBUG(cerr << "namestk[" << level
				<< "].name gets NULL\n";)
			int i=0;

			// for each element in the array or structure
			for (; --nel >= 0; vp = (char*)vp + element->size) {
				DEBUG(cerr << "in forloop, " << "vp=" 
					<< vp << "\n";)
//  Truncate fixed arrays if necessary
				if (i>=rd->nel && rd->nel>0) {
					break;
				}
//  Set up namestk[level] for this element
				namestk[level].name = NULL;
				DEBUG(cerr << "namestk[" << level <<
					"].name = NULL\n";)
				DEBUG(cerr << "namestk[" << level <<
					"].index = " << i << "\n";)
				namestk[level].index = i++;
				DEBUG(cerr << "Call emit_node recursively:\n";)
//  Call emit_node recursively for this element
				emit_node(level+1, vp, element, os);
//  Fiddle with outlevel (?)
				DEBUG(cerr << "return from from emit_node with "
					<< "outlevel=" << outlevel << "\n";)
				DEBUG(cerr << "Fiddle with outlevel\n";)
				if (outlevel > level) {
					outlevel = level;
					DEBUG(cerr << "adjust outlevel to "
						<< outlevel << "\n";)
				}
			}
		}
		else {
//  Its element type is a leaf
			DEBUG(cerr << "Its element type is a leaf\n";)
			int i = 0;
			// for each element
			for (; --nel >= 0; vp = ((char*)vp + REALSIZE(element->size)),i++) {
				DEBUG(cerr << "in for loop:\n" << "    nel="
					<< nel << "\n" << "    vp=" 
					<< vp << "\n";)

//  Filter out nulls
				if (isnull_leaf(vp, element)) {
					if (element->size == 0 && element->isn(vp)) {
						vp = (char*)vp + element->nel;
						 /* size of user defined
						    type is in nel */
					}
					continue;
				}
				
//  Emit name hierarchy 
			DEBUG(cerr << "Emit name hierarchy\n";)
			// for each level in outlevel..level-1
			for (; outlevel < level; outlevel++) {
				DEBUG(cerr << "in for loop, outlevel=" 
					<< outlevel << "\n";)
				int j = outlevel;
				DEBUG(cerr << "emit " << j << " tabs\n";)
				while (--j >= 0) {
					os << '\t';
				}
				char* cp = namestk[outlevel].name;
				if (cp) {
//  Name is alphabetic
					DEBUG(cerr << "Name is alphabetic: ";)
					os << cp;
					DEBUG(cerr << cp << "\n";)
				}
				else {
//  Name is an index
					DEBUG(cerr << "Name is an index: ";)
					os << namestk[outlevel].index;
					DEBUG(cerr << namestk[outlevel].index << "\n";)
				}
/* new code to put the size of the array in an array record */
				if (namestk[outlevel].maxarray != 0) {
					os << "\t" << namestk[outlevel].maxarray;
					namestk[outlevel].maxarray = 0;
				}
				DEBUG(cerr << "emit newline\n";)
				os << '\n';
			}
			int j = level;

			DEBUG(cerr << "emit " << j << " tabs\n";)
			while (--j >= 0) {
				os << '\t';
			}
//  Emit builtin
			DEBUG( cerr << "emit builtin: " << i << '\n'; )
			os << i;
			DEBUG(cerr << "emit tab\n";)
			os << '\t';

			if (element->size < 0) {
				emit_builtin(os, element->size, vp, element->nel);
			}
			else if (element->size == 0) {
				element->pfn(os,vp);
				DEBUG(cerr << "back from call to pfn\n";)
				vp = (char*)vp + element->nel;
				 /* size of user defined type is in nel */
			}
			os << '\n';
		}  
	}   
	break;
	} /* end switch */
}
}

//  Emit a value of builtin type
static void 
emit_builtin(ostream& os, int size, void* vp, int max) {
	DEBUG(cerr << "\nenter emit_builtin with vp, size=" << vp 
		<< ", " << size << "\n";)
	switch (size) { 
		char buf[MAXINTSTR_ATTLC];   // TBD_fixed_limit
	case LONG_INT_ATTLC+1:
	{
		DEBUG(cerr << "emit LONG value: " << *((long*)vp) << '\n'; )
		os << *((long*)vp);
		break;
	}
	case SHORT_INT_ATTLC+1:
	{
		DEBUG(cerr << "emit SHORT value: " << *((short*)vp) << '\n'; )
		os << *((short*)vp);
		break;
	}
	case CHAR_INT_ATTLC+1:
	{
		DEBUG(cerr << "CHAR" << '\n';)
		if (isprint_ATTLC(*(unsigned char *)vp)) {
			DEBUG(cerr << "emit printable character: " 
				<< char(*(char*)vp) << "\n";)
			os << (*(char*)vp);
		}
		else {
			DEBUG(cerr << "string begins with unprintable character: \\";)
			os << '\\';
			char* p = _g2ctostr_ATTLC(buf, sizeof(buf), *(unsigned char *)vp);
			while (*p) {
				DEBUG(cerr << *p;)
				os << *p++;
			}
			DEBUG(cerr << "\n";)
		}
		break;
	}
	case STRING_INT_ATTLC+1:
	{
		DEBUG(cerr << "STRING\n";)
		const char* cp = (const char*)(*(String*)vp);
		const char* guard = cp+max;

		const char* p = cp;

		while (*p && (max==0 || p<guard) && isprint_ATTLC(*(unsigned char *)p)) {
			p++;
		}
		OSWRITE(cp,p-cp);
	}
	default:
	{
		g2err_ATTLC = G2BADLEAF;
	}
	break;
	} /* end switch */
}
« May 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 31
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: