[comp.windows.x] Problem porting XView 2.0 to DG AviiON

paulf@bksmel.oz.au (Paul Fitchett) (11/08/90)

Hi,
I'm trying to port XView 2.0 to the DG AViiON and have run into trouble with
the Attr_avlist stuff.
Certain code in the distribution assumes that va_list is of a type that
can be cast to unsigned long. On a Sun this happens to be true, as va_list is
defined to be char *, however on a DG va_list is a structure:

typedef struct {
        int  __va_arg;          /* argument number */
        int *__va_stk;          /* start of args passed on stack */
        int *__va_reg;          /* start of args passed in regs */
} va_list;

There appears to be a way around this using attr_create() to make the
Attr_avlist from the va_list, however this requires that NON_PORTABLE be
undefined in the file attr.c. A consquence of this is that the function
attr_copy_valist() (which is declared extern in attr_impl.h) is required.
I cannot find the *.c file containing the definition of attr_copy_valist() at
all. In the file attr.c there is a comment that refers to a file
attr_portable.c, which is not present, perhaps this file is the one I need.

The problem occurs in certain files (such as cms_pblc.c) which have the
following construct:

Pkg_private Xv_opaque
cms_get_attr(cms_public, status, attr, args)
    Cms                 cms_public;
    int                 *status;
    Cms_attribute       attr;
    va_list             args;
{
    Cms_info            *cms = CMS_PRIVATE(cms_public);
    Xv_opaque           value;
    Attr_avlist         avlist = (Attr_avlist) args;		<---
    int                 cms_status = 0;

    switch (attr) {

The line marked with <--- is rejected by the compiler on the DG and should
perhaps be replaced by a call to attr_create() to make the avlist from the
args in a portable way.

If anyone can help me by sending the missing files, or by explaining how to
get around this problem, or indeed by correcting a misunderstanding I may
have about any of this, I would be very grateful.

Thanks,
Paul Fitchett
(paulf@bksmel.oz.au)

jmck@norge.Eng.Sun.COM (John McKernan) (11/13/90)

Here's a copy of the file attr_portable.c. Please note that this file
is not needed to build XView, and has not been tested with the rest of
XView. Also note that while this file might be of some use to somebody
porting XView, it will by no means result in a ported/portable version
of XView. Such a port would likely require considerable work with the
textsw/ttysw and notifier package, among other things. I hope that we
will be able to include much more portability code in the next XView 
source release. 

John McKernan.                                                     
Windows and Graphics Software, Sun Microsystems.                  jmck@sun.com


#ifndef lint
#ifdef sccs
static char     sccsid[] = "@(#)attr_portable.c 20.10 90/06/21";
#endif
#endif

/*
 *	(c) Copyright 1989 Sun Microsystems, Inc. Sun design patents 
 *	pending in the U.S. and foreign countries. See LEGAL NOTICE 
 *	file for terms of the license.
 */

#include <xview_private/attr_impl.h>

#ifndef NON_PORTABLE

static int      valist_count_recursive();
static va_list  valist_skip_value();

#define	valist_get(valist)	va_arg(valist, caddr_t)

/*
 * Copy count elements from list to dest. Advance both list and dest to the
 * next element after the last one copied.
 */
#define	valist_copy_many(valist, dest, count)	\
    { \
	register caddr_t *last = dest + count; \
	\
	while (dest < last) \
	    *dest++ = valist_get(valist); \
    }


/*
 * A macro to copy attribute values count is the number of caddr_t size
 * chunks to copy.
 */
#define	valist_copy_values(src, dest, count) \
    if (count == 1) \
        *dest++ = valist_get(src); \
    else { \
	valist_copy_many(src, dest, count); \
    }


/*
 * copy the var-args list from * valist to dest.  Recursive lists are
 * collapsed into dest.
 */

Attr_avlist
attr_copy_valist(dest, valist)
    register Attr_avlist dest;
    register va_list valist;
{
    register Attr_attribute attr;
    register u_int  cardinality;

    while (attr = (Attr_attribute) valist_get(valist)) {
	cardinality = ATTR_CARDINALITY(attr);
	switch (ATTR_LIST_TYPE(attr)) {
	  case ATTR_NONE:	/* not a list */
	    *dest++ = (caddr_t) attr;
	    valist_copy_values(valist, dest, cardinality);
	    break;

	  case ATTR_NULL:	/* null terminated list */
	    *dest++ = (caddr_t) attr;
	    switch (ATTR_LIST_PTR_TYPE(attr)) {
	      case ATTR_LIST_IS_INLINE:
		/*
		 * Note that this only checks the first four bytes for the
		 * null termination. Copy each value element until we have
		 * copied the null termination.
		 */
		do {
		    valist_copy_values(valist, dest, cardinality);
		} while (*(dest - 1));
		break;

	      case ATTR_LIST_IS_PTR:
		*dest++ = valist_get(valist);
		break;
	    }
	    break;

	  case ATTR_COUNTED:	/* counted list */
	    *dest++ = (caddr_t) attr;
	    switch (ATTR_LIST_PTR_TYPE(attr)) {
	      case ATTR_LIST_IS_INLINE:{
		    register u_int  count;

		    *dest = valist_get(valist);	/* copy the count */
		    count = ((u_int) * dest++) * cardinality;
		    valist_copy_values(valist, dest, count);
		    break;
		}

	      case ATTR_LIST_IS_PTR:
		*dest++ = valist_get(valist);
		break;
	    }
	    break;

	  case ATTR_RECURSIVE:	/* recursive attribute-value list */
	    if (cardinality != 0)	/* don't strip it */
		*dest++ = (caddr_t) attr;

	    switch (ATTR_LIST_PTR_TYPE(attr)) {
	      case ATTR_LIST_IS_INLINE:
		dest = attr_copy_valist(dest, valist);
		if (cardinality != 0)	/* don't strip it */
		    dest++;	/* move past the null terminator */
		valist = valist_skip_value(attr, valist);
		break;

	      case ATTR_LIST_IS_PTR:
		if (cardinality != 0)	/* don't collapse inline */
		    *dest++ = valist_get(valist);
		else {
		    Attr_avlist     new_avlist = (Attr_avlist) valist_get(valist);
		    if (new_avlist)
			/*
			 * Copy the list inline -- don't move past the null
			 * termintor. Here both the attribute and null
			 * terminator will be stripped away.
			 */
			dest = attr_copy_avlist(dest, new_avlist);
		}
		break;
	    }
	    break;
	}
    }
    *dest = 0;
    return (dest);
}

/*
 * return a pointer to the attribute after the value pointed to by list.
 * attr should be the attribute which describes the value at list.
 */
static          va_list
valist_skip_value(attr, valist)
    register Attr_attribute attr;
    register va_list valist;
{
    switch (ATTR_LIST_TYPE(attr)) {
      case ATTR_NULL:
	if (ATTR_LIST_PTR_TYPE(attr) == ATTR_LIST_IS_PTR)
	    (void) valist_get(valist);
	else
	    while (valist_get(valist));
	break;

      case ATTR_RECURSIVE:
	if (ATTR_LIST_PTR_TYPE(attr) == ATTR_LIST_IS_PTR)
	    (void) valist_get(valist);
	else
	    while (attr = (Attr_attribute) valist_get(valist))
		valist = valist_skip_value(attr, valist);
	break;

      case ATTR_COUNTED:
	if (ATTR_LIST_PTR_TYPE(attr) == ATTR_LIST_IS_PTR) {
	    (void) valist_get(valist);
	    break;
	}
	/* else fall through ... */
      case ATTR_NONE:{
	    register u_int  count = ATTR_CARDINALITY(attr);

	    if (ATTR_LIST_TYPE(attr) == ATTR_COUNTED)
		/* use the count */
		count *= (u_int) valist_get(valist);
	    while (count--)
		(void) valist_get(valist);
	}
	break;
    }
    return valist;
}


/*
 * valist_count counts the number of slots in the varargs-list valist.
 * Recursive lists are counted as being collapsed inline.
 */
int
valist_count(valist)
    va_list         valist;
{
    /* count the null termination */
    return (valist_count_recursive(valist, 0) + 1);
}

static int
valist_count_recursive(valist, last_attr)
    register va_list valist;
    register Attr_attribute last_attr;
{
    register Attr_attribute attr;
    register u_int  count = 0;
    register u_int  num;
    register u_int  cardinality;

    while (attr = (Attr_attribute) valist_get(valist)) {
	count++;		/* count the attribute */
	cardinality = ATTR_CARDINALITY(attr);
	attr_check_pkg(last_attr, attr);
	last_attr = attr;
	switch (ATTR_LIST_TYPE(attr)) {
	  case ATTR_NONE:	/* not a list */
	    count += cardinality;
	    valist = valist_skip_value(attr, valist);
	    break;

	  case ATTR_NULL:	/* null terminated list */
	    switch (ATTR_LIST_PTR_TYPE(attr)) {
	      case ATTR_LIST_IS_INLINE:
		/*
		 * Note that this only checks the first four bytes for the
		 * null termination.
		 */
		while (valist_get(valist))
		    count++;
		count++;	/* count the null terminator */
		break;

	      case ATTR_LIST_IS_PTR:
		count++;
		(void) valist_get(valist);
		break;
	    }
	    break;

	  case ATTR_COUNTED:	/* counted list */
	    switch (ATTR_LIST_PTR_TYPE(attr)) {
	      case ATTR_LIST_IS_INLINE:{
		    va_list         orig_list = valist;

		    num = ((u_int) (valist_get(valist))) * cardinality + 1;
		    count += num;
		    valist = valist_skip_value(attr, orig_list);
		    break;
		}
	      case ATTR_LIST_IS_PTR:
		count++;
		(void) valist_get(valist);
		break;
	    }
	    break;

	  case ATTR_RECURSIVE:	/* recursive attribute-value list */
	    if (cardinality == 0)	/* don't include the attribute */
		count--;

	    switch (ATTR_LIST_PTR_TYPE(attr)) {
	      case ATTR_LIST_IS_INLINE:
		count += valist_count_recursive(valist, attr);
		if (cardinality != 0)	/* count the null terminator */
		    count++;
		valist = valist_skip_value(attr, valist);
		break;

	      case ATTR_LIST_IS_PTR:
		if (cardinality != 0) {	/* don't collapse inline */
		    count++;
		    (void) valist_get(valist);
		} else {
		    Attr_avlist     new_avlist = (Attr_avlist) valist_get(valist);

		    if (new_avlist)
			/*
			 * Here we count the elements of the recursive list
			 * as being inline. Don't count the null terminator.
			 */
			count += attr_count_avlist(new_avlist, attr);
		}
		break;
	    }
	    break;
	}
    }
    return count;
}

#endif	/* not NON_PORTABLE */