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 */