Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / config / dmxparse.c
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@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
56 dmxConfigLog(const char *format, ...)
57 {
58 va_list args;
59
60 va_start(args, format);
61 vprintf(format, args); /* RATS: All calls to dmxConfigLog from
62 * dmxparse.c and dmxprint.c use a
63 * trusted format. */
64 va_end(args);
65 }
66
67 void *
68 dmxConfigAlloc(unsigned long bytes)
69 {
70 void *area = calloc(1, bytes);
71
72 if (!area) {
73 dmxConfigLog("dmxConfigAlloc: out of memory\n");
74 return NULL;
75 }
76 return area;
77 }
78
79 void *
80 dmxConfigRealloc(void *orig, unsigned long orig_bytes, unsigned long bytes)
81 {
82 unsigned char *area = realloc(orig, bytes);
83
84 if (!area) {
85 dmxConfigLog("dmxConfigRealloc: out of memory\n");
86 return NULL;
87 }
88 memset(area + orig_bytes, 0, bytes - orig_bytes);
89 return area;
90 }
91
92 const char *
93 dmxConfigCopyString(const char *string, int length)
94 {
95 char *copy;
96
97 if (!length)
98 length = strlen(string);
99 copy = dmxConfigAlloc(length + 1);
100 if (length)
101 strncpy(copy, string, length);
102 copy[length] = '\0';
103 return copy;
104 }
105
106 void
107 dmxConfigFree(void *area)
108 {
109 free(area);
110 }
111
112 DMXConfigTokenPtr
113 dmxConfigCreateToken(int token, int line, const char *comment)
114 {
115 DMXConfigTokenPtr pToken = dmxConfigAlloc(sizeof(*pToken));
116
117 pToken->token = token;
118 pToken->line = line;
119 pToken->comment = comment;
120 return pToken;
121 }
122
123 void
124 dmxConfigFreeToken(DMXConfigTokenPtr p)
125 {
126 if (!p)
127 return;
128 dmxConfigFree((void *) p->comment);
129 dmxConfigFree(p);
130 }
131
132 DMXConfigStringPtr
133 dmxConfigCreateString(int token, int line,
134 const char *comment, const char *string)
135 {
136 DMXConfigStringPtr pString = dmxConfigAlloc(sizeof(*pString));
137
138 pString->token = token;
139 pString->line = line;
140 pString->comment = comment;
141 pString->string = string;
142 return pString;
143 }
144
145 void
146 dmxConfigFreeString(DMXConfigStringPtr p)
147 {
148 DMXConfigStringPtr next;
149
150 if (!p)
151 return;
152 do {
153 next = p->next;
154 dmxConfigFree((void *) p->comment);
155 dmxConfigFree((void *) p->string);
156 dmxConfigFree(p);
157 } while ((p = next));
158 }
159
160 DMXConfigNumberPtr
161 dmxConfigCreateNumber(int token, int line, const char *comment, int number)
162 {
163 DMXConfigNumberPtr pNumber = dmxConfigAlloc(sizeof(*pNumber));
164
165 pNumber->token = token;
166 pNumber->line = line;
167 pNumber->comment = comment;
168 pNumber->number = number;
169 return pNumber;
170 }
171
172 void
173 dmxConfigFreeNumber(DMXConfigNumberPtr p)
174 {
175 if (!p)
176 return;
177 dmxConfigFree((void *) p->comment);
178 dmxConfigFree(p);
179 }
180
181 DMXConfigPairPtr
182 dmxConfigCreatePair(int token, int line,
183 const char *comment, int x, int y, int xsign, int ysign)
184 {
185 DMXConfigPairPtr pPair = dmxConfigAlloc(sizeof(*pPair));
186
187 pPair->token = token;
188 pPair->line = line;
189 pPair->comment = comment;
190 pPair->x = x;
191 pPair->y = y;
192 pPair->xsign = (xsign < 0) ? -1 : 1;
193 pPair->ysign = (ysign < 0) ? -1 : 1;
194 return pPair;
195 }
196
197 void
198 dmxConfigFreePair(DMXConfigPairPtr p)
199 {
200 if (!p)
201 return;
202 dmxConfigFree((void *) p->comment);
203 dmxConfigFree(p);
204 }
205
206 DMXConfigCommentPtr
207 dmxConfigCreateComment(int token, int line, const char *comment)
208 {
209 DMXConfigCommentPtr pComment = dmxConfigAlloc(sizeof(*pComment));
210
211 pComment->token = token;
212 pComment->line = line;
213 pComment->comment = comment;
214 return pComment;
215 }
216
217 void
218 dmxConfigFreeComment(DMXConfigCommentPtr p)
219 {
220 if (!p)
221 return;
222 dmxConfigFree((void *) p->comment);
223 dmxConfigFree(p);
224 }
225
226 DMXConfigPartDimPtr
227 dmxConfigCreatePartDim(DMXConfigPairPtr pDim, DMXConfigPairPtr pOffset)
228 {
229 DMXConfigPartDimPtr pPart = dmxConfigAlloc(sizeof(*pPart));
230
231 pPart->dim = pDim;
232 pPart->offset = pOffset;
233 return pPart;
234 }
235
236 void
237 dmxConfigFreePartDim(DMXConfigPartDimPtr p)
238 {
239 if (!p)
240 return;
241 dmxConfigFreePair(p->dim);
242 dmxConfigFreePair(p->offset);
243 dmxConfigFree(p);
244 }
245
246 DMXConfigFullDimPtr
247 dmxConfigCreateFullDim(DMXConfigPartDimPtr pScrn, DMXConfigPartDimPtr pRoot)
248 {
249 DMXConfigFullDimPtr pFull = dmxConfigAlloc(sizeof(*pFull));
250
251 pFull->scrn = pScrn;
252 pFull->root = pRoot;
253 return pFull;
254 }
255
256 void
257 dmxConfigFreeFullDim(DMXConfigFullDimPtr p)
258 {
259 if (!p)
260 return;
261 dmxConfigFreePartDim(p->scrn);
262 dmxConfigFreePartDim(p->root);
263 dmxConfigFree(p);
264 }
265
266 DMXConfigDisplayPtr
267 dmxConfigCreateDisplay(DMXConfigTokenPtr pStart,
268 DMXConfigStringPtr pName,
269 DMXConfigFullDimPtr pDim,
270 DMXConfigPairPtr pOrigin, DMXConfigTokenPtr pEnd)
271 {
272 DMXConfigDisplayPtr pDisplay = dmxConfigAlloc(sizeof(*pDisplay));
273
274 pDisplay->start = pStart;
275 pDisplay->dname = pName;
276 pDisplay->dim = pDim;
277 pDisplay->origin = pOrigin;
278 pDisplay->end = pEnd;
279
280 pDisplay->name = pName ? pName->string : NULL;
281 pDisplay->rootXOrigin = pOrigin ? pOrigin->x : 0;
282 pDisplay->rootYOrigin = pOrigin ? pOrigin->y : 0;
283
284 if (pDim && pDim->scrn && pDim->scrn->dim) {
285 pDisplay->scrnWidth = pDim->scrn->dim->x;
286 pDisplay->scrnHeight = pDim->scrn->dim->y;
287 }
288 if (pDim && pDim->scrn && pDim->scrn->offset) {
289 pDisplay->scrnX = pDim->scrn->offset->x;
290 pDisplay->scrnY = pDim->scrn->offset->y;
291 pDisplay->scrnXSign = pDim->scrn->offset->xsign;
292 pDisplay->scrnYSign = pDim->scrn->offset->ysign;
293 }
294
295 if (pDim && pDim->root) {
296 if (pDim->root->dim) {
297 pDisplay->rootWidth = pDim->root->dim->x;
298 pDisplay->rootHeight = pDim->root->dim->y;
299 }
300 if (pDim->root->offset) {
301 pDisplay->rootX = pDim->root->offset->x;
302 pDisplay->rootY = pDim->root->offset->y;
303 pDisplay->rootXSign = pDim->root->offset->xsign;
304 pDisplay->rootYSign = pDim->root->offset->ysign;
305 }
306 }
307 else { /* If no root specification, copy width
308 * and height from scrn -- leave offset
309 * as zero, since it is relative to
310 * scrn. */
311 pDisplay->rootWidth = pDisplay->scrnWidth;
312 pDisplay->rootHeight = pDisplay->scrnHeight;
313 }
314
315 return pDisplay;
316 }
317
318 void
319 dmxConfigFreeDisplay(DMXConfigDisplayPtr p)
320 {
321 if (!p)
322 return;
323 dmxConfigFreeToken(p->start);
324 dmxConfigFreeString(p->dname);
325 dmxConfigFreeFullDim(p->dim);
326 dmxConfigFreeToken(p->end);
327 dmxConfigFree(p);
328 }
329
330 DMXConfigWallPtr
331 dmxConfigCreateWall(DMXConfigTokenPtr pStart,
332 DMXConfigPairPtr pWallDim,
333 DMXConfigPairPtr pDisplayDim,
334 DMXConfigStringPtr pNameList, DMXConfigTokenPtr pEnd)
335 {
336 DMXConfigWallPtr pWall = dmxConfigAlloc(sizeof(*pWall));
337
338 pWall->start = pStart;
339 pWall->wallDim = pWallDim;
340 pWall->displayDim = pDisplayDim;
341 pWall->nameList = pNameList;
342 pWall->end = pEnd;
343
344 pWall->width = pDisplayDim ? pDisplayDim->x : 0;
345 pWall->height = pDisplayDim ? pDisplayDim->y : 0;
346 pWall->xwall = pWallDim ? pWallDim->x : 0;
347 pWall->ywall = pWallDim ? pWallDim->y : 0;
348
349 return pWall;
350 }
351
352 void
353 dmxConfigFreeWall(DMXConfigWallPtr p)
354 {
355 if (!p)
356 return;
357 dmxConfigFreeToken(p->start);
358 dmxConfigFreePair(p->wallDim);
359 dmxConfigFreePair(p->displayDim);
360 dmxConfigFreeString(p->nameList);
361 dmxConfigFreeToken(p->end);
362 dmxConfigFree(p);
363 }
364
365 DMXConfigOptionPtr
366 dmxConfigCreateOption(DMXConfigTokenPtr pStart,
367 DMXConfigStringPtr pOption, DMXConfigTokenPtr pEnd)
368 {
369 int length = 0;
370 int offset = 0;
371 DMXConfigStringPtr p;
372 DMXConfigOptionPtr option = dmxConfigAlloc(sizeof(*option));
373
374 for (p = pOption; p; p = p->next) {
375 if (p->string)
376 length += strlen(p->string) + 1;
377 }
378
379 option->string = dmxConfigAlloc(length + 1);
380
381 for (p = pOption; p; p = p->next) {
382 if (p->string) {
383 int len = strlen(p->string);
384
385 strncpy(option->string + offset, p->string, len);
386 offset += len;
387 if (p->next)
388 option->string[offset++] = ' ';
389 }
390 }
391 option->string[offset] = '\0';
392
393 option->start = pStart;
394 option->option = pOption;
395 option->end = pEnd;
396
397 return option;
398 }
399
400 void
401 dmxConfigFreeOption(DMXConfigOptionPtr p)
402 {
403 if (!p)
404 return;
405 free(p->string);
406 dmxConfigFreeToken(p->start);
407 dmxConfigFreeString(p->option);
408 dmxConfigFreeToken(p->end);
409 dmxConfigFree(p);
410 }
411
412 const char **
413 dmxConfigLookupParam(DMXConfigParamPtr p, const char *key, int *argc)
414 {
415 DMXConfigParamPtr pt;
416
417 for (pt = p; pt; pt = pt->next) {
418 if (pt->argv && !strcasecmp(pt->argv[0], key)) {
419 *argc = pt->argc;
420 return pt->argv;
421 }
422 }
423 *argc = 0;
424 return NULL;
425 }
426
427 DMXConfigParamPtr
428 dmxConfigCreateParam(DMXConfigTokenPtr pStart,
429 DMXConfigTokenPtr pOpen,
430 DMXConfigStringPtr pParam,
431 DMXConfigTokenPtr pClose, DMXConfigTokenPtr pEnd)
432 {
433 DMXConfigParamPtr param = dmxConfigAlloc(sizeof(*param));
434 DMXConfigStringPtr pt;
435
436 param->argc = 0;
437 param->argv = NULL;
438 for (pt = pParam; pt; pt = pt->next) {
439 if (pt->string) {
440 param->argv = realloc(param->argv,
441 (param->argc + 2) * sizeof(*param->argv));
442 param->argv[param->argc] = pt->string;
443 ++param->argc;
444 }
445 }
446 if (param->argv)
447 param->argv[param->argc] = NULL;
448
449 param->start = pStart;
450 param->open = pOpen;
451 param->param = pParam;
452 param->close = pClose;
453 param->end = pEnd;
454
455 return param;
456 }
457
458 void
459 dmxConfigFreeParam(DMXConfigParamPtr p)
460 {
461 DMXConfigParamPtr next;
462
463 if (!p)
464 return;
465 do {
466 next = p->next;
467 dmxConfigFreeToken(p->start);
468 dmxConfigFreeToken(p->open);
469 dmxConfigFreeString(p->param);
470 dmxConfigFreeToken(p->close);
471 dmxConfigFreeToken(p->end);
472 dmxConfigFree(p->argv);
473 dmxConfigFree(p);
474 } while ((p = next));
475 }
476
477 DMXConfigSubPtr
478 dmxConfigCreateSub(DMXConfigType type,
479 DMXConfigCommentPtr comment,
480 DMXConfigDisplayPtr display,
481 DMXConfigWallPtr wall,
482 DMXConfigOptionPtr option, DMXConfigParamPtr param)
483 {
484 DMXConfigSubPtr pSub = dmxConfigAlloc(sizeof(*pSub));
485
486 pSub->type = type;
487 switch (type) {
488 case dmxConfigComment:
489 pSub->comment = comment;
490 break;
491 case dmxConfigDisplay:
492 pSub->display = display;
493 break;
494 case dmxConfigWall:
495 pSub->wall = wall;
496 break;
497 case dmxConfigOption:
498 pSub->option = option;
499 break;
500 case dmxConfigParam:
501 pSub->param = param;
502 break;
503 default:
504 dmxConfigLog("Type %d not supported in subentry\n", type);
505 break;
506 }
507 return pSub;
508 }
509
510 void
511 dmxConfigFreeSub(DMXConfigSubPtr sub)
512 {
513 DMXConfigSubPtr pt;
514
515 for (pt = sub; pt; pt = pt->next) {
516 switch (pt->type) {
517 case dmxConfigComment:
518 dmxConfigFreeComment(pt->comment);
519 break;
520 case dmxConfigDisplay:
521 dmxConfigFreeDisplay(pt->display);
522 break;
523 case dmxConfigWall:
524 dmxConfigFreeWall(pt->wall);
525 break;
526 case dmxConfigOption:
527 dmxConfigFreeOption(pt->option);
528 break;
529 case dmxConfigParam:
530 dmxConfigFreeParam(pt->param);
531 break;
532 default:
533 dmxConfigLog("Type %d not supported in subentry\n", pt->type);
534 break;
535 }
536 }
537 dmxConfigFree(sub);
538 }
539
540 DMXConfigSubPtr
541 dmxConfigSubComment(DMXConfigCommentPtr comment)
542 {
543 return dmxConfigCreateSub(dmxConfigComment, comment, NULL, NULL, NULL,
544 NULL);
545 }
546
547 DMXConfigSubPtr
548 dmxConfigSubDisplay(DMXConfigDisplayPtr display)
549 {
550 return dmxConfigCreateSub(dmxConfigDisplay, NULL, display, NULL, NULL,
551 NULL);
552 }
553
554 DMXConfigSubPtr
555 dmxConfigSubWall(DMXConfigWallPtr wall)
556 {
557 return dmxConfigCreateSub(dmxConfigWall, NULL, NULL, wall, NULL, NULL);
558 }
559
560 DMXConfigSubPtr
561 dmxConfigSubOption(DMXConfigOptionPtr option)
562 {
563 return dmxConfigCreateSub(dmxConfigOption, NULL, NULL, NULL, option, NULL);
564 }
565
566 DMXConfigSubPtr
567 dmxConfigSubParam(DMXConfigParamPtr param)
568 {
569 return dmxConfigCreateSub(dmxConfigParam, NULL, NULL, NULL, NULL, param);
570 }
571
572 extern DMXConfigSubPtr
573 dmxConfigAddSub(DMXConfigSubPtr head, DMXConfigSubPtr sub)
574 {
575 DMXConfigSubPtr pt;
576
577 if (!head)
578 return sub;
579 for (pt = head; pt->next; pt = pt->next);
580 pt->next = sub;
581 return head;
582 }
583
584 DMXConfigVirtualPtr
585 dmxConfigCreateVirtual(DMXConfigTokenPtr pStart,
586 DMXConfigStringPtr pName,
587 DMXConfigPairPtr pDim,
588 DMXConfigTokenPtr pOpen,
589 DMXConfigSubPtr pSubentry, DMXConfigTokenPtr pClose)
590 {
591 DMXConfigVirtualPtr pVirtual = dmxConfigAlloc(sizeof(*pVirtual));
592
593 pVirtual->start = pStart;
594 pVirtual->vname = pName;
595 pVirtual->dim = pDim;
596 pVirtual->open = pOpen;
597 pVirtual->subentry = pSubentry;
598 pVirtual->close = pClose;
599
600 pVirtual->name = pName ? pName->string : NULL;
601 pVirtual->width = pDim ? pDim->x : 0;
602 pVirtual->height = pDim ? pDim->y : 0;
603
604 return pVirtual;
605 }
606
607 void
608 dmxConfigFreeVirtual(DMXConfigVirtualPtr virtual)
609 {
610 dmxConfigFreeToken(virtual->start);
611 dmxConfigFreeString(virtual->vname);
612 dmxConfigFreePair(virtual->dim);
613 dmxConfigFreeToken(virtual->open);
614 dmxConfigFreeSub(virtual->subentry);
615 dmxConfigFreeToken(virtual->close);
616 dmxConfigFree(virtual);
617 }
618
619 DMXConfigEntryPtr
620 dmxConfigCreateEntry(DMXConfigType type,
621 DMXConfigCommentPtr comment, DMXConfigVirtualPtr virtual)
622 {
623 DMXConfigEntryPtr pEntry = dmxConfigAlloc(sizeof(*pEntry));
624
625 pEntry->type = type;
626 switch (type) {
627 case dmxConfigComment:
628 pEntry->comment = comment;
629 break;
630 case dmxConfigVirtual:
631 pEntry->virtual = virtual;
632 break;
633 default:
634 dmxConfigLog("Type %d not supported in entry\n", type);
635 break;
636 }
637 return pEntry;
638 }
639
640 void
641 dmxConfigFreeEntry(DMXConfigEntryPtr entry)
642 {
643 DMXConfigEntryPtr pt;
644
645 for (pt = entry; pt; pt = pt->next) {
646 switch (pt->type) {
647 case dmxConfigComment:
648 dmxConfigFreeComment(pt->comment);
649 break;
650 case dmxConfigVirtual:
651 dmxConfigFreeVirtual(pt->virtual);
652 break;
653 default:
654 dmxConfigLog("Type %d not supported in entry\n", pt->type);
655 break;
656 }
657 }
658 dmxConfigFree(entry);
659 }
660
661 DMXConfigEntryPtr
662 dmxConfigAddEntry(DMXConfigEntryPtr head,
663 DMXConfigType type,
664 DMXConfigCommentPtr comment, DMXConfigVirtualPtr virtual)
665 {
666 DMXConfigEntryPtr child = dmxConfigCreateEntry(type, comment, virtual);
667 DMXConfigEntryPtr pt;
668
669 if (!head)
670 return child;
671
672 for (pt = head; pt->next; pt = pt->next);
673 pt->next = child;
674
675 return head;
676 }
677
678 DMXConfigEntryPtr
679 dmxConfigEntryComment(DMXConfigCommentPtr comment)
680 {
681 return dmxConfigCreateEntry(dmxConfigComment, comment, NULL);
682 }
683
684 DMXConfigEntryPtr
685 dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual)
686 {
687 return dmxConfigCreateEntry(dmxConfigVirtual, NULL, virtual);
688 }