Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / config / dmxparse.c
CommitLineData
a09e091a
JB
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. */
55void
56dmxConfigLog(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
67void *
68dmxConfigAlloc(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
79void *
80dmxConfigRealloc(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
92const char *
93dmxConfigCopyString(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
106void
107dmxConfigFree(void *area)
108{
109 free(area);
110}
111
112DMXConfigTokenPtr
113dmxConfigCreateToken(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
123void
124dmxConfigFreeToken(DMXConfigTokenPtr p)
125{
126 if (!p)
127 return;
128 dmxConfigFree((void *) p->comment);
129 dmxConfigFree(p);
130}
131
132DMXConfigStringPtr
133dmxConfigCreateString(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
145void
146dmxConfigFreeString(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
160DMXConfigNumberPtr
161dmxConfigCreateNumber(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
172void
173dmxConfigFreeNumber(DMXConfigNumberPtr p)
174{
175 if (!p)
176 return;
177 dmxConfigFree((void *) p->comment);
178 dmxConfigFree(p);
179}
180
181DMXConfigPairPtr
182dmxConfigCreatePair(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
197void
198dmxConfigFreePair(DMXConfigPairPtr p)
199{
200 if (!p)
201 return;
202 dmxConfigFree((void *) p->comment);
203 dmxConfigFree(p);
204}
205
206DMXConfigCommentPtr
207dmxConfigCreateComment(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
217void
218dmxConfigFreeComment(DMXConfigCommentPtr p)
219{
220 if (!p)
221 return;
222 dmxConfigFree((void *) p->comment);
223 dmxConfigFree(p);
224}
225
226DMXConfigPartDimPtr
227dmxConfigCreatePartDim(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
236void
237dmxConfigFreePartDim(DMXConfigPartDimPtr p)
238{
239 if (!p)
240 return;
241 dmxConfigFreePair(p->dim);
242 dmxConfigFreePair(p->offset);
243 dmxConfigFree(p);
244}
245
246DMXConfigFullDimPtr
247dmxConfigCreateFullDim(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
256void
257dmxConfigFreeFullDim(DMXConfigFullDimPtr p)
258{
259 if (!p)
260 return;
261 dmxConfigFreePartDim(p->scrn);
262 dmxConfigFreePartDim(p->root);
263 dmxConfigFree(p);
264}
265
266DMXConfigDisplayPtr
267dmxConfigCreateDisplay(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
318void
319dmxConfigFreeDisplay(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
330DMXConfigWallPtr
331dmxConfigCreateWall(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
352void
353dmxConfigFreeWall(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
365DMXConfigOptionPtr
366dmxConfigCreateOption(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
400void
401dmxConfigFreeOption(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
412const char **
413dmxConfigLookupParam(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
427DMXConfigParamPtr
428dmxConfigCreateParam(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
458void
459dmxConfigFreeParam(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
477DMXConfigSubPtr
478dmxConfigCreateSub(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
510void
511dmxConfigFreeSub(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
540DMXConfigSubPtr
541dmxConfigSubComment(DMXConfigCommentPtr comment)
542{
543 return dmxConfigCreateSub(dmxConfigComment, comment, NULL, NULL, NULL,
544 NULL);
545}
546
547DMXConfigSubPtr
548dmxConfigSubDisplay(DMXConfigDisplayPtr display)
549{
550 return dmxConfigCreateSub(dmxConfigDisplay, NULL, display, NULL, NULL,
551 NULL);
552}
553
554DMXConfigSubPtr
555dmxConfigSubWall(DMXConfigWallPtr wall)
556{
557 return dmxConfigCreateSub(dmxConfigWall, NULL, NULL, wall, NULL, NULL);
558}
559
560DMXConfigSubPtr
561dmxConfigSubOption(DMXConfigOptionPtr option)
562{
563 return dmxConfigCreateSub(dmxConfigOption, NULL, NULL, NULL, option, NULL);
564}
565
566DMXConfigSubPtr
567dmxConfigSubParam(DMXConfigParamPtr param)
568{
569 return dmxConfigCreateSub(dmxConfigParam, NULL, NULL, NULL, NULL, param);
570}
571
572extern DMXConfigSubPtr
573dmxConfigAddSub(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
584DMXConfigVirtualPtr
585dmxConfigCreateVirtual(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
607void
608dmxConfigFreeVirtual(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
619DMXConfigEntryPtr
620dmxConfigCreateEntry(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
640void
641dmxConfigFreeEntry(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
661DMXConfigEntryPtr
662dmxConfigAddEntry(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
678DMXConfigEntryPtr
679dmxConfigEntryComment(DMXConfigCommentPtr comment)
680{
681 return dmxConfigCreateEntry(dmxConfigComment, comment, NULL);
682}
683
684DMXConfigEntryPtr
685dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual)
686{
687 return dmxConfigCreateEntry(dmxConfigVirtual, NULL, virtual);
688}