Varargs.c revision 9e7bcd65
1/* 2 3Copyright 1985, 1986, 1987, 1988, 1989, 1994, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30#include "IntrinsicI.h" 31#include "VarargsI.h" 32#include "StringDefs.h" 33 34static String XtNxtConvertVarToArgList = "xtConvertVarToArgList"; 35 36/* 37 * Given a nested list, _XtCountNestedList() returns counts of the 38 * total number of attribute-value pairs and the count of those 39 * attributes that are typed. The list is counted recursively. 40 */ 41static void 42_XtCountNestedList( 43 XtTypedArgList avlist, 44 int *total_count, 45 int *typed_count) 46{ 47 for (; avlist->name != NULL; avlist++) { 48 if (strcmp(avlist->name, XtVaNestedList) == 0) { 49 _XtCountNestedList((XtTypedArgList)avlist->value, total_count, 50 typed_count); 51 } else { 52 if (avlist->type != NULL) { 53 ++(*typed_count); 54 } 55 ++(*total_count); 56 } 57 } 58} 59 60 61/* 62 * Given a variable length attribute-value list, _XtCountVaList() 63 * returns counts of the total number of attribute-value pairs, 64 * and the count of the number of those attributes that are typed. 65 * The list is counted recursively. 66 */ 67void 68_XtCountVaList(va_list var, int* total_count, int* typed_count) 69{ 70 String attr; 71 72 *total_count = 0; 73 *typed_count = 0; 74 75 for(attr = va_arg(var, String) ; attr != NULL; 76 attr = va_arg(var, String)) { 77 if (strcmp(attr, XtVaTypedArg) == 0) { 78 (void)va_arg(var, String); 79 (void)va_arg(var, String); 80 (void)va_arg(var, XtArgVal); 81 (void)va_arg(var, int); 82 ++(*total_count); 83 ++(*typed_count); 84 } else if (strcmp(attr, XtVaNestedList) == 0) { 85 _XtCountNestedList(va_arg(var, XtTypedArgList), total_count, 86 typed_count); 87 } else { 88 (void)va_arg(var, XtArgVal); 89 ++(*total_count); 90 } 91 } 92} 93 94 95/* 96 * Given a variable length attribute-value list, XtVaCreateArgsList() 97 * constructs an attribute-value list of type XtTypedArgList and 98 * returns the list. 99 */ 100XtVarArgsList 101XtVaCreateArgsList(XtPointer unused, ...) 102{ 103 va_list var; 104 XtTypedArgList avlist; 105 int count = 0; 106 String attr; 107 108 /* 109 * Count the number of attribute-value pairs in the list. 110 * Note: The count is required only to allocate enough space to store 111 * the list. Therefore nested lists are not counted recursively. 112 */ 113 va_start(var,unused); 114 for(attr = va_arg(var, String) ; attr != NULL; 115 attr = va_arg(var, String)) { 116 ++count; 117 if (strcmp(attr, XtVaTypedArg) == 0) { 118 (void)va_arg(var, String); 119 (void)va_arg(var, String); 120 (void)va_arg(var, XtArgVal); 121 (void)va_arg(var, int); 122 } else { 123 (void)va_arg(var, XtArgVal); 124 } 125 } 126 va_end(var); 127 128 va_start(var,unused); 129 avlist = _XtVaCreateTypedArgList(var, count); 130 va_end(var); 131 return (XtVarArgsList)avlist; 132} 133 134 135XtTypedArgList _XtVaCreateTypedArgList(va_list var, register int count) 136{ 137 String attr; 138 XtTypedArgList avlist; 139 140 avlist = (XtTypedArgList) 141 __XtCalloc((int)count + 1, (unsigned)sizeof(XtTypedArg)); 142 143 for(attr = va_arg(var, String), count = 0; attr != NULL; 144 attr = va_arg(var, String)) { 145 if (strcmp(attr, XtVaTypedArg) == 0) { 146 avlist[count].name = va_arg(var, String); 147 avlist[count].type = va_arg(var, String); 148 avlist[count].value = va_arg(var, XtArgVal); 149 avlist[count].size = va_arg(var, int); 150 } else { 151 avlist[count].name = attr; 152 avlist[count].type = NULL; 153 avlist[count].value = va_arg(var, XtArgVal); 154 } 155 ++count; 156 } 157 avlist[count].name = NULL; 158 159 return avlist; 160} 161 162 163/* 164 * TypedArgToArg() invokes a resource converter to convert the 165 * passed typed arg into a name/value pair and stores the name/value 166 * pair in the passed Arg structure. If memory is allocated for the 167 * converted value, the address is returned in the value field of 168 * memory_return; otherwise that field is NULL. The function returns 169 * 1 if the conversion succeeded and 0 if the conversion failed. 170 */ 171static int 172TypedArgToArg( 173 Widget widget, 174 XtTypedArgList typed_arg, 175 ArgList arg_return, 176 XtResourceList resources, 177 Cardinal num_resources, 178 ArgList memory_return) 179{ 180 String to_type = NULL; 181 XrmValue from_val, to_val; 182 183 184 if (widget == NULL) { 185 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 186 "nullWidget", XtNxtConvertVarToArgList, XtCXtToolkitError, 187 "XtVaTypedArg conversion needs non-NULL widget handle", 188 (String *)NULL, (Cardinal *)NULL); 189 return(0); 190 } 191 192 /* again we assume that the XtResourceList is un-compiled */ 193 194 for (; num_resources--; resources++) 195 if (strcmp(typed_arg->name, resources->resource_name) == 0) { 196 to_type = resources->resource_type; 197 break; 198 } 199 200 if (to_type == NULL) { 201 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 202 "unknownType", XtNxtConvertVarToArgList, XtCXtToolkitError, 203 "Unable to find type of resource for conversion", 204 (String *)NULL, (Cardinal *)NULL); 205 return(0); 206 } 207 208 to_val.addr = NULL; 209 from_val.size = typed_arg->size; 210 if ((strcmp(typed_arg->type, XtRString) == 0) || 211 ((unsigned) typed_arg->size > sizeof(XtArgVal))) { 212 from_val.addr = (XPointer)typed_arg->value; 213 } else { 214 from_val.addr = (XPointer)&typed_arg->value; 215 } 216 217 LOCK_PROCESS; 218 XtConvertAndStore(widget, typed_arg->type, &from_val, to_type, &to_val); 219 220 if (to_val.addr == NULL) { 221 UNLOCK_PROCESS; 222 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 223 "conversionFailed", XtNxtConvertVarToArgList, XtCXtToolkitError, 224 "Type conversion failed", (String *)NULL, (Cardinal *)NULL); 225 return(0); 226 } 227 228 arg_return->name = typed_arg->name; 229 memory_return->value = (XtArgVal) NULL; 230 231 if (strcmp(to_type, XtRString) == 0) { 232 arg_return->value = (XtArgVal) to_val.addr; 233 } 234 else { 235 if (to_val.size == sizeof(long)) 236 arg_return->value = (XtArgVal) *(long *)to_val.addr; 237 else if (to_val.size == sizeof(int)) 238 arg_return->value = (XtArgVal) *(int *)to_val.addr; 239 else if (to_val.size == sizeof(short)) 240 arg_return->value = (XtArgVal) *(short *)to_val.addr; 241 else if (to_val.size == sizeof(char)) 242 arg_return->value = (XtArgVal) *(char *)to_val.addr; 243 else if (to_val.size == sizeof(XtArgVal)) 244 arg_return->value = *(XtArgVal *)to_val.addr; 245 else if (to_val.size > sizeof(XtArgVal)) { 246 arg_return->value = (XtArgVal) __XtMalloc(to_val.size); 247 memory_return->value = (XtArgVal) 248 memcpy((void *)arg_return->value, to_val.addr, to_val.size); 249 } 250 } 251 UNLOCK_PROCESS; 252 253 return(1); 254} 255 256 257/* 258 * NestedArgtoArg() converts the passed nested list into 259 * an ArgList/count. 260 */ 261static int 262NestedArgtoArg( 263 Widget widget, 264 XtTypedArgList avlist, 265 ArgList args, 266 XtResourceList resources, 267 Cardinal num_resources, 268 ArgList memory_return) 269{ 270 int count = 0; 271 272 for (; avlist->name != NULL; avlist++) { 273 if (avlist->type != NULL) { 274 /* If widget is NULL, the typed arg is ignored */ 275 if (widget != NULL) { 276 /* this is a typed arg */ 277 count += TypedArgToArg(widget, avlist, (args+count), 278 resources, num_resources, 279 (memory_return+count)); 280 } 281 } else if (strcmp(avlist->name, XtVaNestedList) == 0) { 282 count += NestedArgtoArg(widget, (XtTypedArgList)avlist->value, 283 (args+count), resources, num_resources, 284 (memory_return+count)); 285 } else { 286 (args+count)->name = avlist->name; 287 (args+count)->value = avlist->value; 288 ++count; 289 } 290 } 291 292 return(count); 293} 294 295/* 296 * Free memory allocated through _XtVaToArgList. The actual args array 297 * size is expected to be total_count * 2, where total_count is the number 298 * of elements needed for resource representations. The lower half of the 299 * array contains pairs of resource names and values as usual. For each 300 * element [n] in the lower half of the array, the value field of the 301 * corresponding element [n + total_count] in the upper half of the array 302 * has been pressed into service in order to note whether the resource value 303 * is a pointer to memory that was allocated in TypedArgToArg. In the 304 * upper half, if the value field is not NULL, it contains the address of 305 * memory which should now be freed. That memory could have been allocated 306 * only as a result of the conversion of typed arguments. Therefore, if 307 * there were no typed arguments in the original varargs, there is no need 308 * to examine the upper half of the array. In the choice of data structure 309 * to make this representation, priority was given to the wish to retrofit 310 * the release of memory around the existing signature of _XtVaToArgList. 311 */ 312void 313_XtFreeArgList( 314 ArgList args, /* as returned by _XtVaToArgList */ 315 int total_count, /* argument count returned by _XtCountVaList */ 316 int typed_count) /* typed arg count returned by _XtCountVaList */ 317{ 318 ArgList p; 319 320 if (args) { 321 if (typed_count) 322 for (p = args + total_count; total_count--; ++p) { 323 XtFree((char *)p->value); 324 } 325 XtFree((char *)args); 326 } 327} 328 329 330static void GetResources(Widget widget, XtResourceList *res_list, 331 Cardinal *number); 332 333 334/* 335 * Given a variable argument list, _XtVaToArgList() returns the 336 * equivalent ArgList and count. _XtVaToArgList() handles nested 337 * lists and typed arguments. If typed arguments are present, the 338 * ArgList should be freed with _XtFreeArgList. 339 */ 340void 341_XtVaToArgList( 342 Widget widget, 343 va_list var, 344 int max_count, 345 ArgList *args_return, 346 Cardinal *num_args_return) 347{ 348 String attr; 349 int count; 350 ArgList args = (ArgList)NULL; 351 XtTypedArg typed_arg; 352 XtResourceList resources = (XtResourceList)NULL; 353 Cardinal num_resources; 354 Boolean fetched_resource_list = False; 355 356 if (max_count == 0) { 357 *num_args_return = 0; 358 *args_return = (ArgList)NULL; 359 return; 360 } 361 362 args = (ArgList)__XtMalloc((unsigned)(max_count * 2 * sizeof(Arg))); 363 for (count = max_count * 2; --count >= 0; ) 364 args[count].value = (XtArgVal) NULL; 365 count = 0; 366 367 for(attr = va_arg(var, String) ; attr != NULL; 368 attr = va_arg(var, String)) { 369 if (strcmp(attr, XtVaTypedArg) == 0) { 370 typed_arg.name = va_arg(var, String); 371 typed_arg.type = va_arg(var, String); 372 typed_arg.value = va_arg(var, XtArgVal); 373 typed_arg.size = va_arg(var, int); 374 375 /* if widget is NULL, typed args are ignored */ 376 if (widget != NULL) { 377 if (!fetched_resource_list) { 378 GetResources(widget, &resources, &num_resources); 379 fetched_resource_list = True; 380 } 381 count += TypedArgToArg(widget, &typed_arg, &args[count], 382 resources, num_resources, 383 &args[max_count + count]); 384 } 385 } else if (strcmp(attr, XtVaNestedList) == 0) { 386 if (widget != NULL) { 387 if (!fetched_resource_list) { 388 GetResources(widget, &resources, &num_resources); 389 fetched_resource_list = True; 390 } 391 } 392 393 count += NestedArgtoArg(widget, va_arg(var, XtTypedArgList), 394 &args[count], resources, num_resources, 395 &args[max_count + count]); 396 } else { 397 args[count].name = attr; 398 args[count].value = va_arg(var, XtArgVal); 399 count ++; 400 } 401 } 402 403 XtFree((XtPointer)resources); 404 405 *num_args_return = (Cardinal)count; 406 *args_return = (ArgList)args; 407} 408 409/* Function Name: GetResources 410 * Description: Retreives the normal and constraint resources 411 * for this widget. 412 * Arguments: widget - the widget. 413 * RETURNED res_list - the list of resource for this widget 414 * RETURNED number - the number of resources in the above list. 415 * Returns: none 416 */ 417 418static void 419GetResources( 420 Widget widget, 421 XtResourceList * res_list, 422 Cardinal * number) 423{ 424 Widget parent = XtParent(widget); 425 426 XtInitializeWidgetClass(XtClass(widget)); 427 XtGetResourceList(XtClass(widget), res_list, number); 428 429 if (!XtIsShell(widget) && parent && XtIsConstraint(parent)) { 430 XtResourceList res, constraint, cons_top; 431 Cardinal num_constraint, temp; 432 433 XtGetConstraintResourceList(XtClass(parent), &constraint, 434 &num_constraint); 435 436 cons_top = constraint; 437 *res_list = (XtResourceList) XtRealloc((char*)*res_list, 438 ((*number + num_constraint) * 439 sizeof(XtResource))); 440 441 for (temp= num_constraint, res= *res_list + *number; temp != 0; temp--) 442 *res++ = *constraint++; 443 444 *number += num_constraint; 445 XtFree( (XtPointer) cons_top); 446 } 447} 448 449static int NestedArgtoTypedArg( 450 XtTypedArgList args, 451 XtTypedArgList avlist) 452{ 453 int count = 0; 454 455 for (; avlist->name != NULL; avlist++) { 456 if (avlist->type != NULL) { 457 (args+count)->name = avlist->name; 458 (args+count)->type = avlist->type; 459 (args+count)->size = avlist->size; 460 (args+count)->value = avlist->value; 461 ++count; 462 } else if(strcmp(avlist->name, XtVaNestedList) == 0) { 463 count += NestedArgtoTypedArg((args+count), 464 (XtTypedArgList)avlist->value); 465 } else { 466 (args+count)->name = avlist->name; 467 (args+count)->type = NULL; 468 (args+count)->value = avlist->value; 469 ++count; 470 } 471 } 472 return(count); 473} 474 475 476/* 477 * Given a variable argument list, _XtVaToTypedArgList() returns 478 * the equivalent TypedArgList. _XtVaToTypedArgList() handles nested 479 * lists. 480 * Note: _XtVaToTypedArgList() does not do type conversions. 481 */ 482void 483_XtVaToTypedArgList( 484 va_list var, 485 int max_count, 486 XtTypedArgList *args_return, 487 Cardinal *num_args_return) 488{ 489 XtTypedArgList args = NULL; 490 String attr; 491 int count; 492 493 args = (XtTypedArgList) 494 __XtMalloc((unsigned)(max_count * sizeof(XtTypedArg))); 495 496 for(attr = va_arg(var, String), count = 0 ; attr != NULL; 497 attr = va_arg(var, String)) { 498 if (strcmp(attr, XtVaTypedArg) == 0) { 499 args[count].name = va_arg(var, String); 500 args[count].type = va_arg(var, String); 501 args[count].value = va_arg(var, XtArgVal); 502 args[count].size = va_arg(var, int); 503 ++count; 504 } else if (strcmp(attr, XtVaNestedList) == 0) { 505 count += NestedArgtoTypedArg(&args[count], 506 va_arg(var, XtTypedArgList)); 507 } else { 508 args[count].name = attr; 509 args[count].type = NULL; 510 args[count].value = va_arg(var, XtArgVal); 511 ++count; 512 } 513 } 514 515 *args_return = args; 516 *num_args_return = count; 517} 518