412 lines
12 KiB
C
412 lines
12 KiB
C
#ifndef lint
|
|
#ifdef sccs
|
|
static char sccsid[] = "@(#)attr.c 1.1 94/10/31";
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
* Copyright (c) 1986 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <sunwindow/attr_impl.h>
|
|
#include <sunwindow/sun.h>
|
|
#include <sunwindow/sv_malloc.h>
|
|
|
|
/* Note that changes to the basic attribute-value traversal
|
|
* should also be made in attr_portable.c for portable implmentations.
|
|
*/
|
|
|
|
|
|
/* attr_create creates an avlist from the VARARGS passed
|
|
* on the stack.
|
|
*/
|
|
/*VARARGS2*/
|
|
Attr_avlist
|
|
attr_create(listhead, listlen, va_alist)
|
|
caddr_t *listhead;
|
|
int listlen;
|
|
va_dcl
|
|
{
|
|
Attr_avlist avlist;
|
|
va_list valist;
|
|
|
|
va_start(valist);
|
|
avlist = attr_make(listhead, listlen, valist);
|
|
va_end(valist);
|
|
return avlist;
|
|
}
|
|
|
|
|
|
/* attr_make copies the attribute-value list pointed to by valist to
|
|
* the storage pointed to by listhead, or some new storage if that is
|
|
* null. If listhead is not null, then the list must be less than or equal
|
|
* to listlen ATTR_SIZE byte chunks; if not 0 is returned.
|
|
* The count of the avlist is returned in *count_ptr, if count_ptr is
|
|
* not NULL.
|
|
*/
|
|
Attr_avlist
|
|
attr_make_count(listhead, listlen, valist, count_ptr)
|
|
Attr_avlist listhead;
|
|
int listlen;
|
|
va_list valist;
|
|
int *count_ptr;
|
|
{
|
|
u_int count;
|
|
|
|
#ifdef NON_PORTABLE
|
|
count = (u_int) (LINT_CAST(attr_count((Attr_avlist) valist)));
|
|
#else
|
|
count = (u_int) (LINT_CAST(valist_count(valist)));
|
|
#endif
|
|
/* if the user supplied storage space for attributes is not big enough
|
|
* for the attributes in the attribute list, then exit!
|
|
*/
|
|
if (listhead) {
|
|
if (count > listlen) {
|
|
printf("Number of attributes(%d) in the attr list exceeds\n",count);
|
|
printf("the maximum number(%d) specified. Exit!\n",listlen);
|
|
exit(1);
|
|
}
|
|
} else {
|
|
listhead = (Attr_avlist) (LINT_CAST(sv_malloc((ATTR_SIZE * count)+1)));
|
|
}
|
|
#ifdef NON_PORTABLE
|
|
(void) attr_copy_avlist(listhead, (Attr_avlist) (LINT_CAST(valist)));
|
|
#else
|
|
(void) attr_copy_valist(listhead, valist);
|
|
#endif
|
|
|
|
if (count_ptr)
|
|
*count_ptr = count;
|
|
return(listhead);
|
|
}
|
|
|
|
|
|
#define avlist_get(avlist) *(avlist)++
|
|
|
|
/* Copy count elements from list to dest.
|
|
* Advance both list and dest to the next element after
|
|
* the last one copied.
|
|
*/
|
|
#define avlist_copy(avlist, dest, count) \
|
|
{ \
|
|
bcopy((char *) avlist, (char *) dest, (int)(count * ATTR_SIZE)); \
|
|
avlist += count; \
|
|
dest += count; \
|
|
}
|
|
|
|
|
|
/* A macro to copy attribute values
|
|
* count is the number of caddr_t size chunks to copy.
|
|
*/
|
|
#define avlist_copy_values(avlist, dest, count) \
|
|
if (count == 1) \
|
|
*dest++ = avlist_get(avlist); \
|
|
else { \
|
|
avlist_copy(avlist, dest, count); \
|
|
}
|
|
|
|
|
|
/* attr_copy_avlist copies the attribute-value list from
|
|
* avlist to dest. Recursive lists are collapsed into dest.
|
|
*/
|
|
|
|
Attr_avlist
|
|
attr_copy_avlist(dest, avlist)
|
|
register Attr_avlist dest;
|
|
register Attr_avlist avlist;
|
|
{
|
|
register Attr_attribute attr;
|
|
register u_int cardinality;
|
|
|
|
while (attr = (Attr_attribute) avlist_get(avlist)) {
|
|
cardinality = ATTR_CARDINALITY(attr);
|
|
switch(ATTR_LIST_TYPE(attr)) {
|
|
case ATTR_NONE: /* not a list */
|
|
*dest++ = (caddr_t) attr;
|
|
avlist_copy_values(avlist, 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 {
|
|
avlist_copy_values(avlist, dest, cardinality);
|
|
} while (*(dest - 1));
|
|
break;
|
|
|
|
case ATTR_LIST_IS_PTR:
|
|
*dest++ = avlist_get(avlist);
|
|
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 = avlist_get(avlist); /* copy the count */
|
|
count = ((u_int) *dest++) * cardinality;
|
|
avlist_copy_values(avlist, dest, count);
|
|
}
|
|
break;
|
|
|
|
case ATTR_LIST_IS_PTR:
|
|
*dest++ = avlist_get(avlist);
|
|
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_avlist(dest, avlist);
|
|
if (cardinality != 0) /* don't strip it */
|
|
dest++; /* move past the null terminator */
|
|
avlist = attr_skip(attr, avlist);
|
|
break;
|
|
|
|
case ATTR_LIST_IS_PTR:
|
|
if (cardinality != 0) /* don't collapse inline */
|
|
*dest++ = avlist_get(avlist);
|
|
else {
|
|
Attr_avlist new_avlist = (Attr_avlist)
|
|
(LINT_CAST(avlist_get(avlist)));
|
|
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);
|
|
}
|
|
|
|
|
|
/* attr_count counts the number of slots in the av-list avlist.
|
|
* Recursive lists are counted as being collapsed inline.
|
|
*/
|
|
int
|
|
attr_count(avlist)
|
|
Attr_avlist avlist;
|
|
{
|
|
/* count the null termination */
|
|
return(attr_count_avlist(avlist, 0) + 1);
|
|
}
|
|
|
|
static char *attr_names[ATTR_PKG_LAST-ATTR_PKG_FIRST+1] = {
|
|
"Generic",
|
|
"Panel",
|
|
"Scrollbar",
|
|
"Cursor",
|
|
"Menu",
|
|
"Textsw",
|
|
"Tool",
|
|
"Seln_base",
|
|
"Entity",
|
|
"Image",
|
|
"Win",
|
|
"Frame",
|
|
"Canvas",
|
|
"Tty",
|
|
"Icon",
|
|
"NOP",
|
|
"Pixwin",
|
|
"Alert",
|
|
"Help"
|
|
};
|
|
|
|
|
|
char *
|
|
attr_sprint(s, attr)
|
|
char *s;
|
|
register Attr_attribute attr;
|
|
{
|
|
static char msgbuf[100];
|
|
extern char *sprintf();
|
|
|
|
if (!s) s = msgbuf;
|
|
if (((int) ATTR_PKG(attr)) >= ((int) ATTR_PKG_FIRST) &&
|
|
((int) ATTR_PKG(attr)) <= ((int) ATTR_PKG_LAST)) {
|
|
char *name = attr_names[((int) ATTR_PKG(attr)) - ((int)ATTR_PKG_FIRST)];
|
|
|
|
if (!name) name = "Syspkg";
|
|
(void) sprintf(s, "Attr pkg= %s, id= %d, cardinality= %d (0x%x)",
|
|
name, ATTR_ORDINAL(attr), ATTR_CARDINALITY(attr), attr);
|
|
} else {
|
|
(void) sprintf(s, "Attr pkg= %s, id= %d, cardinality= %d (0x%x)",
|
|
ATTR_PKG(attr), ATTR_ORDINAL(attr), ATTR_CARDINALITY(attr), attr);
|
|
}
|
|
return(s);
|
|
}
|
|
|
|
void
|
|
attr_check_pkg(last_attr, attr)
|
|
Attr_attribute last_attr, attr;
|
|
{
|
|
if (!ATTR_VALID_PKG_ID(attr)) {
|
|
char expand_attr[100];
|
|
|
|
(void) fprintf(stderr,
|
|
"Malformed or non-terminated attribute-value list.\n");
|
|
(void) fprintf(stderr, "Last valid attribute was %s.\n",
|
|
attr_sprint(expand_attr, last_attr));
|
|
abort();
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
attr_count_avlist(avlist, last_attr)
|
|
register Attr_avlist avlist;
|
|
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) *avlist++) {
|
|
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;
|
|
avlist += cardinality;
|
|
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 (*avlist++)
|
|
count++;
|
|
count++; /* count the null terminator */
|
|
break;
|
|
|
|
case ATTR_LIST_IS_PTR:
|
|
count++;
|
|
avlist++;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ATTR_COUNTED: /* counted list */
|
|
switch (ATTR_LIST_PTR_TYPE(attr)) {
|
|
case ATTR_LIST_IS_INLINE:
|
|
num = ((u_int)(*avlist)) * cardinality + 1;
|
|
count += num;
|
|
avlist += num;
|
|
break;
|
|
case ATTR_LIST_IS_PTR:
|
|
count++;
|
|
avlist++;
|
|
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 += attr_count_avlist(avlist, attr);
|
|
if (cardinality != 0) /* count the null terminator */
|
|
count++;
|
|
avlist = attr_skip(attr, avlist);
|
|
break;
|
|
|
|
case ATTR_LIST_IS_PTR:
|
|
if (cardinality != 0) { /* don't collapse inline */
|
|
count++;
|
|
avlist++;
|
|
} else if (*avlist)
|
|
/* Here we count the elements of the
|
|
* recursive list as being inline.
|
|
* Don't count the null terminator.
|
|
*/
|
|
count += attr_count_avlist((Attr_avlist) (LINT_CAST
|
|
(*avlist++)), attr);
|
|
else
|
|
avlist++;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
/* attr_skip_value returns a pointer to the attribute after
|
|
* the value pointed to by avlist. attr should be the
|
|
* attribute which describes the value at avlist.
|
|
*/
|
|
Attr_avlist
|
|
attr_skip_value(attr, avlist)
|
|
register Attr_attribute attr;
|
|
register Attr_avlist avlist;
|
|
{
|
|
switch (ATTR_LIST_TYPE(attr)) {
|
|
case ATTR_NULL:
|
|
if (ATTR_LIST_PTR_TYPE(attr) == ATTR_LIST_IS_PTR)
|
|
avlist++;
|
|
else
|
|
while (*avlist++);
|
|
break;
|
|
|
|
case ATTR_RECURSIVE:
|
|
if (ATTR_LIST_PTR_TYPE(attr) == ATTR_LIST_IS_PTR)
|
|
avlist++;
|
|
else
|
|
while (attr = (Attr_attribute) *avlist++)
|
|
avlist = attr_skip_value(attr, avlist);
|
|
break;
|
|
|
|
case ATTR_COUNTED:
|
|
if (ATTR_LIST_PTR_TYPE(attr) == ATTR_LIST_IS_PTR)
|
|
avlist++;
|
|
else
|
|
avlist += ((int) *avlist) * ATTR_CARDINALITY(attr) + 1;
|
|
break;
|
|
|
|
case ATTR_NONE:
|
|
avlist += ATTR_CARDINALITY(attr);
|
|
break;
|
|
}
|
|
return avlist;
|
|
}
|
|
|
|
/* attr_free frees the attribute-value list
|
|
*/
|
|
void
|
|
attr_free(avlist)
|
|
Attr_avlist avlist;
|
|
{
|
|
free((char *) avlist);
|
|
}
|