xref: /OK3568_Linux_fs/external/xserver/hw/dmx/config/dmxparse.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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
dmxConfigLog(const char * format,...)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 *
dmxConfigAlloc(unsigned long bytes)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 *
dmxConfigRealloc(void * orig,unsigned long orig_bytes,unsigned long bytes)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 *
dmxConfigCopyString(const char * string,int length)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
dmxConfigFree(void * area)107 dmxConfigFree(void *area)
108 {
109     free(area);
110 }
111 
112 DMXConfigTokenPtr
dmxConfigCreateToken(int token,int line,const char * comment)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
dmxConfigFreeToken(DMXConfigTokenPtr p)124 dmxConfigFreeToken(DMXConfigTokenPtr p)
125 {
126     if (!p)
127         return;
128     dmxConfigFree((void *) p->comment);
129     dmxConfigFree(p);
130 }
131 
132 DMXConfigStringPtr
dmxConfigCreateString(int token,int line,const char * comment,const char * string)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
dmxConfigFreeString(DMXConfigStringPtr p)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
dmxConfigCreateNumber(int token,int line,const char * comment,int number)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
dmxConfigFreeNumber(DMXConfigNumberPtr p)173 dmxConfigFreeNumber(DMXConfigNumberPtr p)
174 {
175     if (!p)
176         return;
177     dmxConfigFree((void *) p->comment);
178     dmxConfigFree(p);
179 }
180 
181 DMXConfigPairPtr
dmxConfigCreatePair(int token,int line,const char * comment,int x,int y,int xsign,int ysign)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
dmxConfigFreePair(DMXConfigPairPtr p)198 dmxConfigFreePair(DMXConfigPairPtr p)
199 {
200     if (!p)
201         return;
202     dmxConfigFree((void *) p->comment);
203     dmxConfigFree(p);
204 }
205 
206 DMXConfigCommentPtr
dmxConfigCreateComment(int token,int line,const char * comment)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
dmxConfigFreeComment(DMXConfigCommentPtr p)218 dmxConfigFreeComment(DMXConfigCommentPtr p)
219 {
220     if (!p)
221         return;
222     dmxConfigFree((void *) p->comment);
223     dmxConfigFree(p);
224 }
225 
226 DMXConfigPartDimPtr
dmxConfigCreatePartDim(DMXConfigPairPtr pDim,DMXConfigPairPtr pOffset)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
dmxConfigFreePartDim(DMXConfigPartDimPtr p)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
dmxConfigCreateFullDim(DMXConfigPartDimPtr pScrn,DMXConfigPartDimPtr pRoot)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
dmxConfigFreeFullDim(DMXConfigFullDimPtr p)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
dmxConfigCreateDisplay(DMXConfigTokenPtr pStart,DMXConfigStringPtr pName,DMXConfigFullDimPtr pDim,DMXConfigPairPtr pOrigin,DMXConfigTokenPtr pEnd)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
dmxConfigFreeDisplay(DMXConfigDisplayPtr p)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
dmxConfigCreateWall(DMXConfigTokenPtr pStart,DMXConfigPairPtr pWallDim,DMXConfigPairPtr pDisplayDim,DMXConfigStringPtr pNameList,DMXConfigTokenPtr pEnd)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
dmxConfigFreeWall(DMXConfigWallPtr p)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
dmxConfigCreateOption(DMXConfigTokenPtr pStart,DMXConfigStringPtr pOption,DMXConfigTokenPtr pEnd)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             memcpy(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
dmxConfigFreeOption(DMXConfigOptionPtr p)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 **
dmxConfigLookupParam(DMXConfigParamPtr p,const char * key,int * argc)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
dmxConfigCreateParam(DMXConfigTokenPtr pStart,DMXConfigTokenPtr pOpen,DMXConfigStringPtr pParam,DMXConfigTokenPtr pClose,DMXConfigTokenPtr pEnd)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
dmxConfigFreeParam(DMXConfigParamPtr p)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
dmxConfigCreateSub(DMXConfigType type,DMXConfigCommentPtr comment,DMXConfigDisplayPtr display,DMXConfigWallPtr wall,DMXConfigOptionPtr option,DMXConfigParamPtr param)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
dmxConfigFreeSub(DMXConfigSubPtr sub)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
dmxConfigSubComment(DMXConfigCommentPtr comment)541 dmxConfigSubComment(DMXConfigCommentPtr comment)
542 {
543     return dmxConfigCreateSub(dmxConfigComment, comment, NULL, NULL, NULL,
544                               NULL);
545 }
546 
547 DMXConfigSubPtr
dmxConfigSubDisplay(DMXConfigDisplayPtr display)548 dmxConfigSubDisplay(DMXConfigDisplayPtr display)
549 {
550     return dmxConfigCreateSub(dmxConfigDisplay, NULL, display, NULL, NULL,
551                               NULL);
552 }
553 
554 DMXConfigSubPtr
dmxConfigSubWall(DMXConfigWallPtr wall)555 dmxConfigSubWall(DMXConfigWallPtr wall)
556 {
557     return dmxConfigCreateSub(dmxConfigWall, NULL, NULL, wall, NULL, NULL);
558 }
559 
560 DMXConfigSubPtr
dmxConfigSubOption(DMXConfigOptionPtr option)561 dmxConfigSubOption(DMXConfigOptionPtr option)
562 {
563     return dmxConfigCreateSub(dmxConfigOption, NULL, NULL, NULL, option, NULL);
564 }
565 
566 DMXConfigSubPtr
dmxConfigSubParam(DMXConfigParamPtr param)567 dmxConfigSubParam(DMXConfigParamPtr param)
568 {
569     return dmxConfigCreateSub(dmxConfigParam, NULL, NULL, NULL, NULL, param);
570 }
571 
572 extern DMXConfigSubPtr
dmxConfigAddSub(DMXConfigSubPtr head,DMXConfigSubPtr sub)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
dmxConfigCreateVirtual(DMXConfigTokenPtr pStart,DMXConfigStringPtr pName,DMXConfigPairPtr pDim,DMXConfigTokenPtr pOpen,DMXConfigSubPtr pSubentry,DMXConfigTokenPtr pClose)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
dmxConfigFreeVirtual(DMXConfigVirtualPtr virtual)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
dmxConfigCreateEntry(DMXConfigType type,DMXConfigCommentPtr comment,DMXConfigVirtualPtr virtual)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
dmxConfigFreeEntry(DMXConfigEntryPtr entry)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
dmxConfigAddEntry(DMXConfigEntryPtr head,DMXConfigType type,DMXConfigCommentPtr comment,DMXConfigVirtualPtr virtual)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
dmxConfigEntryComment(DMXConfigCommentPtr comment)679 dmxConfigEntryComment(DMXConfigCommentPtr comment)
680 {
681     return dmxConfigCreateEntry(dmxConfigComment, comment, NULL);
682 }
683 
684 DMXConfigEntryPtr
dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual)685 dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual)
686 {
687     return dmxConfigCreateEntry(dmxConfigVirtual, NULL, virtual);
688 }
689