1 /* 2 * Copyright 2002 Red Hat Inc., Durham, North Carolina. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation on the rights to use, copy, modify, merge, 10 * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 28 /* 29 * Authors: 30 * Rickard E. (Rik) Faith <faith (at) redhat.com> 31 * 32 */ 33 34 /** \file 35 * 36 * This file provides support routines and helper functions to be used 37 * by the DMX configuration file parser. 38 * 39 * Because the DMX configuration file parsing should be capable of being 40 * used in a stand-alone fashion (i.e., independent from the DMX server 41 * source tree), no dependencies on other DMX routines are made. */ 42 43 #ifdef HAVE_DMX_CONFIG_H 44 #include <dmx-config.h> 45 #endif 46 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <stdarg.h> 51 #include "dmxparse.h" 52 53 /** A general error logging routine that does not depend on the dmxLog 54 * functions. */ 55 void dmxConfigLog(const char *format, ...) 56 { 57 va_list args; 58 59 va_start(args, format); 60 vprintf(format, args); /* RATS: All calls to dmxConfigLog from 61 * dmxparse.c and dmxprint.c use a 62 * trusted format. */ 63 va_end(args); 64 } 65 66 void *dmxConfigAlloc(unsigned long bytes) 67 { 68 void *area = calloc(1, bytes); 69 if (!area) { 70 dmxConfigLog("dmxConfigAlloc: out of memory\n"); 71 return NULL; 72 } 73 return area; 74 } 75 76 void *dmxConfigRealloc(void *orig, unsigned long orig_bytes, 77 unsigned long bytes) 78 { 79 unsigned char *area = realloc(orig, bytes); 80 if (!area) { 81 dmxConfigLog("dmxConfigRealloc: out of memory\n"); 82 return NULL; 83 } 84 memset(area + orig_bytes, 0, bytes - orig_bytes); 85 return area; 86 } 87 88 const char *dmxConfigCopyString(const char *string, int length) 89 { 90 char *copy; 91 92 if (!length) length = strlen(string); 93 copy = dmxConfigAlloc(length + 1); 94 if (length) strncpy(copy, string, length); 95 copy[length] = '\0'; 96 return copy; 97 } 98 99 void dmxConfigFree(void *area) 100 { 101 free(area); 102 } 103 104 DMXConfigTokenPtr dmxConfigCreateToken(int token, int line, 105 const char *comment) 106 { 107 DMXConfigTokenPtr pToken = dmxConfigAlloc(sizeof(*pToken)); 108 pToken->token = token; 109 pToken->line = line; 110 pToken->comment = comment; 111 return pToken; 112 } 113 114 void dmxConfigFreeToken(DMXConfigTokenPtr p) 115 { 116 if (!p) return; 117 dmxConfigFree((void *)p->comment); 118 dmxConfigFree(p); 119 } 120 121 DMXConfigStringPtr dmxConfigCreateString(int token, int line, 122 const char *comment, 123 const char *string) 124 { 125 DMXConfigStringPtr pString = dmxConfigAlloc(sizeof(*pString)); 126 127 pString->token = token; 128 pString->line = line; 129 pString->comment = comment; 130 pString->string = string; 131 return pString; 132 } 133 134 void dmxConfigFreeString(DMXConfigStringPtr p) 135 { 136 DMXConfigStringPtr next; 137 138 if (!p) return; 139 do { 140 next = p->next; 141 dmxConfigFree((void *)p->comment); 142 dmxConfigFree((void *)p->string); 143 dmxConfigFree(p); 144 } while ((p = next)); 145 } 146 147 DMXConfigNumberPtr dmxConfigCreateNumber(int token, int line, 148 const char *comment, 149 int number) 150 { 151 DMXConfigNumberPtr pNumber = dmxConfigAlloc(sizeof(*pNumber)); 152 153 pNumber->token = token; 154 pNumber->line = line; 155 pNumber->comment = comment; 156 pNumber->number = number; 157 return pNumber; 158 } 159 160 void dmxConfigFreeNumber(DMXConfigNumberPtr p) 161 { 162 if (!p) return; 163 dmxConfigFree((void *)p->comment); 164 dmxConfigFree(p); 165 } 166 167 DMXConfigPairPtr dmxConfigCreatePair(int token, int line, 168 const char *comment, 169 int x, int y, 170 int xsign, int ysign) 171 { 172 DMXConfigPairPtr pPair = dmxConfigAlloc(sizeof(*pPair)); 173 174 pPair->token = token; 175 pPair->line = line; 176 pPair->comment = comment; 177 pPair->x = x; 178 pPair->y = y; 179 pPair->xsign = (xsign < 0) ? -1 : 1; 180 pPair->ysign = (ysign < 0) ? -1 : 1; 181 return pPair; 182 } 183 184 void dmxConfigFreePair(DMXConfigPairPtr p) 185 { 186 if (!p) return; 187 dmxConfigFree((void *)p->comment); 188 dmxConfigFree(p); 189 } 190 191 DMXConfigCommentPtr dmxConfigCreateComment(int token, int line, 192 const char *comment) 193 { 194 DMXConfigCommentPtr pComment = dmxConfigAlloc(sizeof(*pComment)); 195 196 pComment->token = token; 197 pComment->line = line; 198 pComment->comment = comment; 199 return pComment; 200 } 201 202 void dmxConfigFreeComment(DMXConfigCommentPtr p) 203 { 204 if (!p) return; 205 dmxConfigFree((void *)p->comment); 206 dmxConfigFree(p); 207 } 208 209 DMXConfigPartDimPtr dmxConfigCreatePartDim(DMXConfigPairPtr pDim, 210 DMXConfigPairPtr pOffset) 211 { 212 DMXConfigPartDimPtr pPart = dmxConfigAlloc(sizeof(*pPart)); 213 pPart->dim = pDim; 214 pPart->offset = pOffset; 215 return pPart; 216 } 217 218 void dmxConfigFreePartDim(DMXConfigPartDimPtr p) 219 { 220 if (!p) return; 221 dmxConfigFreePair(p->dim); 222 dmxConfigFreePair(p->offset); 223 dmxConfigFree(p); 224 } 225 226 DMXConfigFullDimPtr dmxConfigCreateFullDim(DMXConfigPartDimPtr pScrn, 227 DMXConfigPartDimPtr pRoot) 228 { 229 DMXConfigFullDimPtr pFull = dmxConfigAlloc(sizeof(*pFull)); 230 pFull->scrn = pScrn; 231 pFull->root = pRoot; 232 return pFull; 233 } 234 235 void dmxConfigFreeFullDim(DMXConfigFullDimPtr p) 236 { 237 if (!p) return; 238 dmxConfigFreePartDim(p->scrn); 239 dmxConfigFreePartDim(p->root); 240 dmxConfigFree(p); 241 } 242 243 DMXConfigDisplayPtr dmxConfigCreateDisplay(DMXConfigTokenPtr pStart, 244 DMXConfigStringPtr pName, 245 DMXConfigFullDimPtr pDim, 246 DMXConfigPairPtr pOrigin, 247 DMXConfigTokenPtr pEnd) 248 { 249 DMXConfigDisplayPtr pDisplay = dmxConfigAlloc(sizeof(*pDisplay)); 250 251 pDisplay->start = pStart; 252 pDisplay->dname = pName; 253 pDisplay->dim = pDim; 254 pDisplay->origin = pOrigin; 255 pDisplay->end = pEnd; 256 257 pDisplay->name = pName ? pName->string : NULL; 258 pDisplay->rootXOrigin = pOrigin ? pOrigin->x : 0; 259 pDisplay->rootYOrigin = pOrigin ? pOrigin->y : 0; 260 261 if (pDim && pDim->scrn && pDim->scrn->dim) { 262 pDisplay->scrnWidth = pDim->scrn->dim->x; 263 pDisplay->scrnHeight = pDim->scrn->dim->y; 264 } 265 if (pDim && pDim->scrn && pDim->scrn->offset) { 266 pDisplay->scrnX = pDim->scrn->offset->x; 267 pDisplay->scrnY = pDim->scrn->offset->y; 268 pDisplay->scrnXSign = pDim->scrn->offset->xsign; 269 pDisplay->scrnYSign = pDim->scrn->offset->ysign; 270 } 271 272 if (pDim && pDim->root) { 273 if (pDim->root->dim) { 274 pDisplay->rootWidth = pDim->root->dim->x; 275 pDisplay->rootHeight = pDim->root->dim->y; 276 } 277 if (pDim->root->offset) { 278 pDisplay->rootX = pDim->root->offset->x; 279 pDisplay->rootY = pDim->root->offset->y; 280 pDisplay->rootXSign = pDim->root->offset->xsign; 281 pDisplay->rootYSign = pDim->root->offset->ysign; 282 } 283 } else { /* If no root specification, copy width 284 * and height from scrn -- leave offset 285 * as zero, since it is relative to 286 * scrn. */ 287 pDisplay->rootWidth = pDisplay->scrnWidth; 288 pDisplay->rootHeight = pDisplay->scrnHeight; 289 } 290 291 292 return pDisplay; 293 } 294 295 void dmxConfigFreeDisplay(DMXConfigDisplayPtr p) 296 { 297 if (!p) return; 298 dmxConfigFreeToken(p->start); 299 dmxConfigFreeString(p->dname); 300 dmxConfigFreeFullDim(p->dim); 301 dmxConfigFreeToken(p->end); 302 dmxConfigFree(p); 303 } 304 305 DMXConfigWallPtr dmxConfigCreateWall(DMXConfigTokenPtr pStart, 306 DMXConfigPairPtr pWallDim, 307 DMXConfigPairPtr pDisplayDim, 308 DMXConfigStringPtr pNameList, 309 DMXConfigTokenPtr pEnd) 310 { 311 DMXConfigWallPtr pWall = dmxConfigAlloc(sizeof(*pWall)); 312 313 pWall->start = pStart; 314 pWall->wallDim = pWallDim; 315 pWall->displayDim = pDisplayDim; 316 pWall->nameList = pNameList; 317 pWall->end = pEnd; 318 319 pWall->width = pDisplayDim ? pDisplayDim->x : 0; 320 pWall->height = pDisplayDim ? pDisplayDim->y : 0; 321 pWall->xwall = pWallDim ? pWallDim->x : 0; 322 pWall->ywall = pWallDim ? pWallDim->y : 0; 323 324 return pWall; 325 } 326 327 void dmxConfigFreeWall(DMXConfigWallPtr p) 328 { 329 if (!p) return; 330 dmxConfigFreeToken(p->start); 331 dmxConfigFreePair(p->wallDim); 332 dmxConfigFreePair(p->displayDim); 333 dmxConfigFreeString(p->nameList); 334 dmxConfigFreeToken(p->end); 335 dmxConfigFree(p); 336 } 337 338 DMXConfigOptionPtr dmxConfigCreateOption(DMXConfigTokenPtr pStart, 339 DMXConfigStringPtr pOption, 340 DMXConfigTokenPtr pEnd) 341 { 342 int length = 0; 343 int offset = 0; 344 DMXConfigStringPtr p; 345 DMXConfigOptionPtr option = dmxConfigAlloc(sizeof(*option)); 346 347 for (p = pOption; p; p = p->next) { 348 if (p->string) length += strlen(p->string) + 1; 349 } 350 351 option->string = dmxConfigAlloc(length + 1); 352 353 for (p = pOption; p; p = p->next) { 354 if (p->string) { 355 int len = strlen(p->string); 356 strncpy(option->string + offset, p->string, len); 357 offset += len; 358 if (p->next) option->string[offset++] = ' '; 359 } 360 } 361 option->string[offset] = '\0'; 362 363 option->start = pStart; 364 option->option = pOption; 365 option->end = pEnd; 366 367 return option; 368 } 369 370 void dmxConfigFreeOption(DMXConfigOptionPtr p) 371 { 372 if (!p) return; 373 free(p->string); 374 dmxConfigFreeToken(p->start); 375 dmxConfigFreeString(p->option); 376 dmxConfigFreeToken(p->end); 377 dmxConfigFree(p); 378 } 379 380 const char **dmxConfigLookupParam(DMXConfigParamPtr p, const char *key, 381 int *argc) 382 { 383 DMXConfigParamPtr pt; 384 385 for (pt = p; pt; pt = pt->next) { 386 if (pt->argv && !strcasecmp(pt->argv[0], key)) { 387 *argc = pt->argc; 388 return pt->argv; 389 } 390 } 391 *argc = 0; 392 return NULL; 393 } 394 395 DMXConfigParamPtr dmxConfigCreateParam(DMXConfigTokenPtr pStart, 396 DMXConfigTokenPtr pOpen, 397 DMXConfigStringPtr pParam, 398 DMXConfigTokenPtr pClose, 399 DMXConfigTokenPtr pEnd) 400 { 401 DMXConfigParamPtr param = dmxConfigAlloc(sizeof(*param)); 402 DMXConfigStringPtr pt; 403 404 param->argc = 0; 405 param->argv = NULL; 406 for (pt = pParam; pt; pt = pt->next) { 407 if (pt->string) { 408 param->argv = realloc(param->argv, 409 (param->argc+2) * sizeof(*param->argv)); 410 param->argv[param->argc] = pt->string; 411 ++param->argc; 412 } 413 } 414 if (param->argv) param->argv[param->argc] = NULL; 415 416 param->start = pStart; 417 param->open = pOpen; 418 param->param = pParam; 419 param->close = pClose; 420 param->end = pEnd; 421 422 return param; 423 } 424 425 void dmxConfigFreeParam(DMXConfigParamPtr p) 426 { 427 DMXConfigParamPtr next; 428 429 if (!p) return; 430 do { 431 next = p->next; 432 dmxConfigFreeToken(p->start); 433 dmxConfigFreeToken(p->open); 434 dmxConfigFreeString(p->param); 435 dmxConfigFreeToken(p->close); 436 dmxConfigFreeToken(p->end); 437 dmxConfigFree(p->argv); 438 dmxConfigFree(p); 439 } while ((p = next)); 440 } 441 442 DMXConfigSubPtr dmxConfigCreateSub(DMXConfigType type, 443 DMXConfigCommentPtr comment, 444 DMXConfigDisplayPtr display, 445 DMXConfigWallPtr wall, 446 DMXConfigOptionPtr option, 447 DMXConfigParamPtr param) 448 { 449 DMXConfigSubPtr pSub = dmxConfigAlloc(sizeof(*pSub)); 450 pSub->type = type; 451 switch (type) { 452 case dmxConfigComment: pSub->comment = comment; break; 453 case dmxConfigDisplay: pSub->display = display; break; 454 case dmxConfigWall: pSub->wall = wall; break; 455 case dmxConfigOption: pSub->option = option; break; 456 case dmxConfigParam: pSub->param = param; break; 457 default: dmxConfigLog("Type %d not supported in subentry\n", type); break; 458 } 459 return pSub; 460 } 461 462 void dmxConfigFreeSub(DMXConfigSubPtr sub) 463 { 464 DMXConfigSubPtr pt; 465 466 for (pt = sub; pt; pt = pt->next) { 467 switch (pt->type) { 468 case dmxConfigComment: dmxConfigFreeComment(pt->comment); break; 469 case dmxConfigDisplay: dmxConfigFreeDisplay(pt->display); break; 470 case dmxConfigWall: dmxConfigFreeWall(pt->wall); break; 471 case dmxConfigOption: dmxConfigFreeOption(pt->option); break; 472 case dmxConfigParam: dmxConfigFreeParam(pt->param); break; 473 default: 474 dmxConfigLog("Type %d not supported in subentry\n", pt->type); 475 break; 476 } 477 } 478 dmxConfigFree(sub); 479 } 480 481 DMXConfigSubPtr dmxConfigSubComment(DMXConfigCommentPtr comment) 482 { 483 return dmxConfigCreateSub(dmxConfigComment, comment, NULL, NULL, NULL, 484 NULL); 485 } 486 487 DMXConfigSubPtr dmxConfigSubDisplay(DMXConfigDisplayPtr display) 488 { 489 return dmxConfigCreateSub(dmxConfigDisplay, NULL, display, NULL, NULL, 490 NULL); 491 } 492 493 DMXConfigSubPtr dmxConfigSubWall(DMXConfigWallPtr wall) 494 { 495 return dmxConfigCreateSub(dmxConfigWall, NULL, NULL, wall, NULL, NULL); 496 } 497 498 DMXConfigSubPtr dmxConfigSubOption(DMXConfigOptionPtr option) 499 { 500 return dmxConfigCreateSub(dmxConfigOption, NULL, NULL, NULL, option, NULL); 501 } 502 503 DMXConfigSubPtr dmxConfigSubParam(DMXConfigParamPtr param) 504 { 505 return dmxConfigCreateSub(dmxConfigParam, NULL, NULL, NULL, NULL, param); 506 } 507 508 extern DMXConfigSubPtr dmxConfigAddSub(DMXConfigSubPtr head, 509 DMXConfigSubPtr sub) 510 { 511 DMXConfigSubPtr pt; 512 513 if (!head) return sub; 514 for (pt = head; pt->next; pt = pt->next); 515 pt->next = sub; 516 return head; 517 } 518 519 DMXConfigVirtualPtr dmxConfigCreateVirtual(DMXConfigTokenPtr pStart, 520 DMXConfigStringPtr pName, 521 DMXConfigPairPtr pDim, 522 DMXConfigTokenPtr pOpen, 523 DMXConfigSubPtr pSubentry, 524 DMXConfigTokenPtr pClose) 525 { 526 DMXConfigVirtualPtr pVirtual = dmxConfigAlloc(sizeof(*pVirtual)); 527 528 pVirtual->start = pStart; 529 pVirtual->vname = pName; 530 pVirtual->dim = pDim; 531 pVirtual->open = pOpen; 532 pVirtual->subentry = pSubentry; 533 pVirtual->close = pClose; 534 535 pVirtual->name = pName ? pName->string : NULL; 536 pVirtual->width = pDim ? pDim->x : 0; 537 pVirtual->height = pDim ? pDim->y : 0; 538 539 return pVirtual; 540 } 541 542 void dmxConfigFreeVirtual(DMXConfigVirtualPtr virtual) 543 { 544 dmxConfigFreeToken(virtual->start); 545 dmxConfigFreeString(virtual->vname); 546 dmxConfigFreePair(virtual->dim); 547 dmxConfigFreeToken(virtual->open); 548 dmxConfigFreeSub(virtual->subentry); 549 dmxConfigFreeToken(virtual->close); 550 dmxConfigFree(virtual); 551 } 552 553 DMXConfigEntryPtr dmxConfigCreateEntry(DMXConfigType type, 554 DMXConfigCommentPtr comment, 555 DMXConfigVirtualPtr virtual) 556 { 557 DMXConfigEntryPtr pEntry = dmxConfigAlloc(sizeof(*pEntry)); 558 pEntry->type = type; 559 switch (type) { 560 case dmxConfigComment: pEntry->comment = comment; break; 561 case dmxConfigVirtual: pEntry->virtual = virtual; break; 562 default: dmxConfigLog("Type %d not supported in entry\n", type); break; 563 } 564 return pEntry; 565 } 566 567 void dmxConfigFreeEntry(DMXConfigEntryPtr entry) 568 { 569 DMXConfigEntryPtr pt; 570 571 for (pt = entry; pt; pt = pt->next) { 572 switch (pt->type) { 573 case dmxConfigComment: dmxConfigFreeComment(pt->comment); break; 574 case dmxConfigVirtual: dmxConfigFreeVirtual(pt->virtual); break; 575 default: 576 dmxConfigLog("Type %d not supported in entry\n", pt->type); 577 break; 578 } 579 } 580 dmxConfigFree(entry); 581 } 582 583 DMXConfigEntryPtr dmxConfigAddEntry(DMXConfigEntryPtr head, 584 DMXConfigType type, 585 DMXConfigCommentPtr comment, 586 DMXConfigVirtualPtr virtual) 587 { 588 DMXConfigEntryPtr child = dmxConfigCreateEntry(type, comment, virtual); 589 DMXConfigEntryPtr pt; 590 591 if (!head) return child; 592 593 for (pt = head; pt->next; pt = pt->next); 594 pt->next = child; 595 596 return head; 597 } 598 599 DMXConfigEntryPtr dmxConfigEntryComment(DMXConfigCommentPtr comment) 600 { 601 return dmxConfigCreateEntry(dmxConfigComment, comment, NULL); 602 } 603 604 DMXConfigEntryPtr dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual) 605 { 606 return dmxConfigCreateEntry(dmxConfigVirtual, NULL, virtual); 607 } 608