689 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			689 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright 2002 Red Hat Inc., Durham, North Carolina.
 | |
|  *
 | |
|  * All Rights Reserved.
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining
 | |
|  * a copy of this software and associated documentation files (the
 | |
|  * "Software"), to deal in the Software without restriction, including
 | |
|  * without limitation on the rights to use, copy, modify, merge,
 | |
|  * publish, distribute, sublicense, and/or sell copies of the Software,
 | |
|  * and to permit persons to whom the Software is furnished to do so,
 | |
|  * subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice (including the
 | |
|  * next paragraph) shall be included in all copies or substantial
 | |
|  * portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | |
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | |
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | |
|  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
 | |
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | |
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
|  * SOFTWARE.
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Authors:
 | |
|  *   Rickard E. (Rik) Faith <faith@redhat.com>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| /** \file
 | |
|  *
 | |
|  * This file provides support routines and helper functions to be used
 | |
|  * by the DMX configuration file parser.
 | |
|  *
 | |
|  * Because the DMX configuration file parsing should be capable of being
 | |
|  * used in a stand-alone fashion (i.e., independent from the DMX server
 | |
|  * source tree), no dependencies on other DMX routines are made. */
 | |
| 
 | |
| #ifdef HAVE_DMX_CONFIG_H
 | |
| #include <dmx-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <stdarg.h>
 | |
| #include "dmxparse.h"
 | |
| 
 | |
| /** A general error logging routine that does not depend on the dmxLog
 | |
|  * functions. */
 | |
| void
 | |
| dmxConfigLog(const char *format, ...)
 | |
| {
 | |
|     va_list args;
 | |
| 
 | |
|     va_start(args, format);
 | |
|     vprintf(format, args);      /* RATS: All calls to dmxConfigLog from
 | |
|                                  * dmxparse.c and dmxprint.c use a
 | |
|                                  * trusted format. */
 | |
|     va_end(args);
 | |
| }
 | |
| 
 | |
| void *
 | |
| dmxConfigAlloc(unsigned long bytes)
 | |
| {
 | |
|     void *area = calloc(1, bytes);
 | |
| 
 | |
|     if (!area) {
 | |
|         dmxConfigLog("dmxConfigAlloc: out of memory\n");
 | |
|         return NULL;
 | |
|     }
 | |
|     return area;
 | |
| }
 | |
| 
 | |
| void *
 | |
| dmxConfigRealloc(void *orig, unsigned long orig_bytes, unsigned long bytes)
 | |
| {
 | |
|     unsigned char *area = realloc(orig, bytes);
 | |
| 
 | |
|     if (!area) {
 | |
|         dmxConfigLog("dmxConfigRealloc: out of memory\n");
 | |
|         return NULL;
 | |
|     }
 | |
|     memset(area + orig_bytes, 0, bytes - orig_bytes);
 | |
|     return area;
 | |
| }
 | |
| 
 | |
| const char *
 | |
| dmxConfigCopyString(const char *string, int length)
 | |
| {
 | |
|     char *copy;
 | |
| 
 | |
|     if (!length)
 | |
|         length = strlen(string);
 | |
|     copy = dmxConfigAlloc(length + 1);
 | |
|     if (length)
 | |
|         strncpy(copy, string, length);
 | |
|     copy[length] = '\0';
 | |
|     return copy;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFree(void *area)
 | |
| {
 | |
|     free(area);
 | |
| }
 | |
| 
 | |
| DMXConfigTokenPtr
 | |
| dmxConfigCreateToken(int token, int line, const char *comment)
 | |
| {
 | |
|     DMXConfigTokenPtr pToken = dmxConfigAlloc(sizeof(*pToken));
 | |
| 
 | |
|     pToken->token = token;
 | |
|     pToken->line = line;
 | |
|     pToken->comment = comment;
 | |
|     return pToken;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeToken(DMXConfigTokenPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFree((void *) p->comment);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigStringPtr
 | |
| dmxConfigCreateString(int token, int line,
 | |
|                       const char *comment, const char *string)
 | |
| {
 | |
|     DMXConfigStringPtr pString = dmxConfigAlloc(sizeof(*pString));
 | |
| 
 | |
|     pString->token = token;
 | |
|     pString->line = line;
 | |
|     pString->comment = comment;
 | |
|     pString->string = string;
 | |
|     return pString;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeString(DMXConfigStringPtr p)
 | |
| {
 | |
|     DMXConfigStringPtr next;
 | |
| 
 | |
|     if (!p)
 | |
|         return;
 | |
|     do {
 | |
|         next = p->next;
 | |
|         dmxConfigFree((void *) p->comment);
 | |
|         dmxConfigFree((void *) p->string);
 | |
|         dmxConfigFree(p);
 | |
|     } while ((p = next));
 | |
| }
 | |
| 
 | |
| DMXConfigNumberPtr
 | |
| dmxConfigCreateNumber(int token, int line, const char *comment, int number)
 | |
| {
 | |
|     DMXConfigNumberPtr pNumber = dmxConfigAlloc(sizeof(*pNumber));
 | |
| 
 | |
|     pNumber->token = token;
 | |
|     pNumber->line = line;
 | |
|     pNumber->comment = comment;
 | |
|     pNumber->number = number;
 | |
|     return pNumber;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeNumber(DMXConfigNumberPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFree((void *) p->comment);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigPairPtr
 | |
| dmxConfigCreatePair(int token, int line,
 | |
|                     const char *comment, int x, int y, int xsign, int ysign)
 | |
| {
 | |
|     DMXConfigPairPtr pPair = dmxConfigAlloc(sizeof(*pPair));
 | |
| 
 | |
|     pPair->token = token;
 | |
|     pPair->line = line;
 | |
|     pPair->comment = comment;
 | |
|     pPair->x = x;
 | |
|     pPair->y = y;
 | |
|     pPair->xsign = (xsign < 0) ? -1 : 1;
 | |
|     pPair->ysign = (ysign < 0) ? -1 : 1;
 | |
|     return pPair;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreePair(DMXConfigPairPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFree((void *) p->comment);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigCommentPtr
 | |
| dmxConfigCreateComment(int token, int line, const char *comment)
 | |
| {
 | |
|     DMXConfigCommentPtr pComment = dmxConfigAlloc(sizeof(*pComment));
 | |
| 
 | |
|     pComment->token = token;
 | |
|     pComment->line = line;
 | |
|     pComment->comment = comment;
 | |
|     return pComment;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeComment(DMXConfigCommentPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFree((void *) p->comment);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigPartDimPtr
 | |
| dmxConfigCreatePartDim(DMXConfigPairPtr pDim, DMXConfigPairPtr pOffset)
 | |
| {
 | |
|     DMXConfigPartDimPtr pPart = dmxConfigAlloc(sizeof(*pPart));
 | |
| 
 | |
|     pPart->dim = pDim;
 | |
|     pPart->offset = pOffset;
 | |
|     return pPart;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreePartDim(DMXConfigPartDimPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFreePair(p->dim);
 | |
|     dmxConfigFreePair(p->offset);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigFullDimPtr
 | |
| dmxConfigCreateFullDim(DMXConfigPartDimPtr pScrn, DMXConfigPartDimPtr pRoot)
 | |
| {
 | |
|     DMXConfigFullDimPtr pFull = dmxConfigAlloc(sizeof(*pFull));
 | |
| 
 | |
|     pFull->scrn = pScrn;
 | |
|     pFull->root = pRoot;
 | |
|     return pFull;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeFullDim(DMXConfigFullDimPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFreePartDim(p->scrn);
 | |
|     dmxConfigFreePartDim(p->root);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigDisplayPtr
 | |
| dmxConfigCreateDisplay(DMXConfigTokenPtr pStart,
 | |
|                        DMXConfigStringPtr pName,
 | |
|                        DMXConfigFullDimPtr pDim,
 | |
|                        DMXConfigPairPtr pOrigin, DMXConfigTokenPtr pEnd)
 | |
| {
 | |
|     DMXConfigDisplayPtr pDisplay = dmxConfigAlloc(sizeof(*pDisplay));
 | |
| 
 | |
|     pDisplay->start = pStart;
 | |
|     pDisplay->dname = pName;
 | |
|     pDisplay->dim = pDim;
 | |
|     pDisplay->origin = pOrigin;
 | |
|     pDisplay->end = pEnd;
 | |
| 
 | |
|     pDisplay->name = pName ? pName->string : NULL;
 | |
|     pDisplay->rootXOrigin = pOrigin ? pOrigin->x : 0;
 | |
|     pDisplay->rootYOrigin = pOrigin ? pOrigin->y : 0;
 | |
| 
 | |
|     if (pDim && pDim->scrn && pDim->scrn->dim) {
 | |
|         pDisplay->scrnWidth = pDim->scrn->dim->x;
 | |
|         pDisplay->scrnHeight = pDim->scrn->dim->y;
 | |
|     }
 | |
|     if (pDim && pDim->scrn && pDim->scrn->offset) {
 | |
|         pDisplay->scrnX = pDim->scrn->offset->x;
 | |
|         pDisplay->scrnY = pDim->scrn->offset->y;
 | |
|         pDisplay->scrnXSign = pDim->scrn->offset->xsign;
 | |
|         pDisplay->scrnYSign = pDim->scrn->offset->ysign;
 | |
|     }
 | |
| 
 | |
|     if (pDim && pDim->root) {
 | |
|         if (pDim->root->dim) {
 | |
|             pDisplay->rootWidth = pDim->root->dim->x;
 | |
|             pDisplay->rootHeight = pDim->root->dim->y;
 | |
|         }
 | |
|         if (pDim->root->offset) {
 | |
|             pDisplay->rootX = pDim->root->offset->x;
 | |
|             pDisplay->rootY = pDim->root->offset->y;
 | |
|             pDisplay->rootXSign = pDim->root->offset->xsign;
 | |
|             pDisplay->rootYSign = pDim->root->offset->ysign;
 | |
|         }
 | |
|     }
 | |
|     else {                      /* If no root specification, copy width
 | |
|                                  * and height from scrn -- leave offset
 | |
|                                  * as zero, since it is relative to
 | |
|                                  * scrn. */
 | |
|         pDisplay->rootWidth = pDisplay->scrnWidth;
 | |
|         pDisplay->rootHeight = pDisplay->scrnHeight;
 | |
|     }
 | |
| 
 | |
|     return pDisplay;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeDisplay(DMXConfigDisplayPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFreeToken(p->start);
 | |
|     dmxConfigFreeString(p->dname);
 | |
|     dmxConfigFreeFullDim(p->dim);
 | |
|     dmxConfigFreeToken(p->end);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigWallPtr
 | |
| dmxConfigCreateWall(DMXConfigTokenPtr pStart,
 | |
|                     DMXConfigPairPtr pWallDim,
 | |
|                     DMXConfigPairPtr pDisplayDim,
 | |
|                     DMXConfigStringPtr pNameList, DMXConfigTokenPtr pEnd)
 | |
| {
 | |
|     DMXConfigWallPtr pWall = dmxConfigAlloc(sizeof(*pWall));
 | |
| 
 | |
|     pWall->start = pStart;
 | |
|     pWall->wallDim = pWallDim;
 | |
|     pWall->displayDim = pDisplayDim;
 | |
|     pWall->nameList = pNameList;
 | |
|     pWall->end = pEnd;
 | |
| 
 | |
|     pWall->width = pDisplayDim ? pDisplayDim->x : 0;
 | |
|     pWall->height = pDisplayDim ? pDisplayDim->y : 0;
 | |
|     pWall->xwall = pWallDim ? pWallDim->x : 0;
 | |
|     pWall->ywall = pWallDim ? pWallDim->y : 0;
 | |
| 
 | |
|     return pWall;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeWall(DMXConfigWallPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     dmxConfigFreeToken(p->start);
 | |
|     dmxConfigFreePair(p->wallDim);
 | |
|     dmxConfigFreePair(p->displayDim);
 | |
|     dmxConfigFreeString(p->nameList);
 | |
|     dmxConfigFreeToken(p->end);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| DMXConfigOptionPtr
 | |
| dmxConfigCreateOption(DMXConfigTokenPtr pStart,
 | |
|                       DMXConfigStringPtr pOption, DMXConfigTokenPtr pEnd)
 | |
| {
 | |
|     int length = 0;
 | |
|     int offset = 0;
 | |
|     DMXConfigStringPtr p;
 | |
|     DMXConfigOptionPtr option = dmxConfigAlloc(sizeof(*option));
 | |
| 
 | |
|     for (p = pOption; p; p = p->next) {
 | |
|         if (p->string)
 | |
|             length += strlen(p->string) + 1;
 | |
|     }
 | |
| 
 | |
|     option->string = dmxConfigAlloc(length + 1);
 | |
| 
 | |
|     for (p = pOption; p; p = p->next) {
 | |
|         if (p->string) {
 | |
|             int len = strlen(p->string);
 | |
| 
 | |
|             memcpy(option->string + offset, p->string, len);
 | |
|             offset += len;
 | |
|             if (p->next)
 | |
|                 option->string[offset++] = ' ';
 | |
|         }
 | |
|     }
 | |
|     option->string[offset] = '\0';
 | |
| 
 | |
|     option->start = pStart;
 | |
|     option->option = pOption;
 | |
|     option->end = pEnd;
 | |
| 
 | |
|     return option;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeOption(DMXConfigOptionPtr p)
 | |
| {
 | |
|     if (!p)
 | |
|         return;
 | |
|     free(p->string);
 | |
|     dmxConfigFreeToken(p->start);
 | |
|     dmxConfigFreeString(p->option);
 | |
|     dmxConfigFreeToken(p->end);
 | |
|     dmxConfigFree(p);
 | |
| }
 | |
| 
 | |
| const char **
 | |
| dmxConfigLookupParam(DMXConfigParamPtr p, const char *key, int *argc)
 | |
| {
 | |
|     DMXConfigParamPtr pt;
 | |
| 
 | |
|     for (pt = p; pt; pt = pt->next) {
 | |
|         if (pt->argv && !strcasecmp(pt->argv[0], key)) {
 | |
|             *argc = pt->argc;
 | |
|             return pt->argv;
 | |
|         }
 | |
|     }
 | |
|     *argc = 0;
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| DMXConfigParamPtr
 | |
| dmxConfigCreateParam(DMXConfigTokenPtr pStart,
 | |
|                      DMXConfigTokenPtr pOpen,
 | |
|                      DMXConfigStringPtr pParam,
 | |
|                      DMXConfigTokenPtr pClose, DMXConfigTokenPtr pEnd)
 | |
| {
 | |
|     DMXConfigParamPtr param = dmxConfigAlloc(sizeof(*param));
 | |
|     DMXConfigStringPtr pt;
 | |
| 
 | |
|     param->argc = 0;
 | |
|     param->argv = NULL;
 | |
|     for (pt = pParam; pt; pt = pt->next) {
 | |
|         if (pt->string) {
 | |
|             param->argv = realloc(param->argv,
 | |
|                                   (param->argc + 2) * sizeof(*param->argv));
 | |
|             param->argv[param->argc] = pt->string;
 | |
|             ++param->argc;
 | |
|         }
 | |
|     }
 | |
|     if (param->argv)
 | |
|         param->argv[param->argc] = NULL;
 | |
| 
 | |
|     param->start = pStart;
 | |
|     param->open = pOpen;
 | |
|     param->param = pParam;
 | |
|     param->close = pClose;
 | |
|     param->end = pEnd;
 | |
| 
 | |
|     return param;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeParam(DMXConfigParamPtr p)
 | |
| {
 | |
|     DMXConfigParamPtr next;
 | |
| 
 | |
|     if (!p)
 | |
|         return;
 | |
|     do {
 | |
|         next = p->next;
 | |
|         dmxConfigFreeToken(p->start);
 | |
|         dmxConfigFreeToken(p->open);
 | |
|         dmxConfigFreeString(p->param);
 | |
|         dmxConfigFreeToken(p->close);
 | |
|         dmxConfigFreeToken(p->end);
 | |
|         dmxConfigFree(p->argv);
 | |
|         dmxConfigFree(p);
 | |
|     } while ((p = next));
 | |
| }
 | |
| 
 | |
| DMXConfigSubPtr
 | |
| dmxConfigCreateSub(DMXConfigType type,
 | |
|                    DMXConfigCommentPtr comment,
 | |
|                    DMXConfigDisplayPtr display,
 | |
|                    DMXConfigWallPtr wall,
 | |
|                    DMXConfigOptionPtr option, DMXConfigParamPtr param)
 | |
| {
 | |
|     DMXConfigSubPtr pSub = dmxConfigAlloc(sizeof(*pSub));
 | |
| 
 | |
|     pSub->type = type;
 | |
|     switch (type) {
 | |
|     case dmxConfigComment:
 | |
|         pSub->comment = comment;
 | |
|         break;
 | |
|     case dmxConfigDisplay:
 | |
|         pSub->display = display;
 | |
|         break;
 | |
|     case dmxConfigWall:
 | |
|         pSub->wall = wall;
 | |
|         break;
 | |
|     case dmxConfigOption:
 | |
|         pSub->option = option;
 | |
|         break;
 | |
|     case dmxConfigParam:
 | |
|         pSub->param = param;
 | |
|         break;
 | |
|     default:
 | |
|         dmxConfigLog("Type %d not supported in subentry\n", type);
 | |
|         break;
 | |
|     }
 | |
|     return pSub;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeSub(DMXConfigSubPtr sub)
 | |
| {
 | |
|     DMXConfigSubPtr pt;
 | |
| 
 | |
|     for (pt = sub; pt; pt = pt->next) {
 | |
|         switch (pt->type) {
 | |
|         case dmxConfigComment:
 | |
|             dmxConfigFreeComment(pt->comment);
 | |
|             break;
 | |
|         case dmxConfigDisplay:
 | |
|             dmxConfigFreeDisplay(pt->display);
 | |
|             break;
 | |
|         case dmxConfigWall:
 | |
|             dmxConfigFreeWall(pt->wall);
 | |
|             break;
 | |
|         case dmxConfigOption:
 | |
|             dmxConfigFreeOption(pt->option);
 | |
|             break;
 | |
|         case dmxConfigParam:
 | |
|             dmxConfigFreeParam(pt->param);
 | |
|             break;
 | |
|         default:
 | |
|             dmxConfigLog("Type %d not supported in subentry\n", pt->type);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     dmxConfigFree(sub);
 | |
| }
 | |
| 
 | |
| DMXConfigSubPtr
 | |
| dmxConfigSubComment(DMXConfigCommentPtr comment)
 | |
| {
 | |
|     return dmxConfigCreateSub(dmxConfigComment, comment, NULL, NULL, NULL,
 | |
|                               NULL);
 | |
| }
 | |
| 
 | |
| DMXConfigSubPtr
 | |
| dmxConfigSubDisplay(DMXConfigDisplayPtr display)
 | |
| {
 | |
|     return dmxConfigCreateSub(dmxConfigDisplay, NULL, display, NULL, NULL,
 | |
|                               NULL);
 | |
| }
 | |
| 
 | |
| DMXConfigSubPtr
 | |
| dmxConfigSubWall(DMXConfigWallPtr wall)
 | |
| {
 | |
|     return dmxConfigCreateSub(dmxConfigWall, NULL, NULL, wall, NULL, NULL);
 | |
| }
 | |
| 
 | |
| DMXConfigSubPtr
 | |
| dmxConfigSubOption(DMXConfigOptionPtr option)
 | |
| {
 | |
|     return dmxConfigCreateSub(dmxConfigOption, NULL, NULL, NULL, option, NULL);
 | |
| }
 | |
| 
 | |
| DMXConfigSubPtr
 | |
| dmxConfigSubParam(DMXConfigParamPtr param)
 | |
| {
 | |
|     return dmxConfigCreateSub(dmxConfigParam, NULL, NULL, NULL, NULL, param);
 | |
| }
 | |
| 
 | |
| extern DMXConfigSubPtr
 | |
| dmxConfigAddSub(DMXConfigSubPtr head, DMXConfigSubPtr sub)
 | |
| {
 | |
|     DMXConfigSubPtr pt;
 | |
| 
 | |
|     if (!head)
 | |
|         return sub;
 | |
|     for (pt = head; pt->next; pt = pt->next);
 | |
|     pt->next = sub;
 | |
|     return head;
 | |
| }
 | |
| 
 | |
| DMXConfigVirtualPtr
 | |
| dmxConfigCreateVirtual(DMXConfigTokenPtr pStart,
 | |
|                        DMXConfigStringPtr pName,
 | |
|                        DMXConfigPairPtr pDim,
 | |
|                        DMXConfigTokenPtr pOpen,
 | |
|                        DMXConfigSubPtr pSubentry, DMXConfigTokenPtr pClose)
 | |
| {
 | |
|     DMXConfigVirtualPtr pVirtual = dmxConfigAlloc(sizeof(*pVirtual));
 | |
| 
 | |
|     pVirtual->start = pStart;
 | |
|     pVirtual->vname = pName;
 | |
|     pVirtual->dim = pDim;
 | |
|     pVirtual->open = pOpen;
 | |
|     pVirtual->subentry = pSubentry;
 | |
|     pVirtual->close = pClose;
 | |
| 
 | |
|     pVirtual->name = pName ? pName->string : NULL;
 | |
|     pVirtual->width = pDim ? pDim->x : 0;
 | |
|     pVirtual->height = pDim ? pDim->y : 0;
 | |
| 
 | |
|     return pVirtual;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeVirtual(DMXConfigVirtualPtr virtual)
 | |
| {
 | |
|     dmxConfigFreeToken(virtual->start);
 | |
|     dmxConfigFreeString(virtual->vname);
 | |
|     dmxConfigFreePair(virtual->dim);
 | |
|     dmxConfigFreeToken(virtual->open);
 | |
|     dmxConfigFreeSub(virtual->subentry);
 | |
|     dmxConfigFreeToken(virtual->close);
 | |
|     dmxConfigFree(virtual);
 | |
| }
 | |
| 
 | |
| DMXConfigEntryPtr
 | |
| dmxConfigCreateEntry(DMXConfigType type,
 | |
|                      DMXConfigCommentPtr comment, DMXConfigVirtualPtr virtual)
 | |
| {
 | |
|     DMXConfigEntryPtr pEntry = dmxConfigAlloc(sizeof(*pEntry));
 | |
| 
 | |
|     pEntry->type = type;
 | |
|     switch (type) {
 | |
|     case dmxConfigComment:
 | |
|         pEntry->comment = comment;
 | |
|         break;
 | |
|     case dmxConfigVirtual:
 | |
|         pEntry->virtual = virtual;
 | |
|         break;
 | |
|     default:
 | |
|         dmxConfigLog("Type %d not supported in entry\n", type);
 | |
|         break;
 | |
|     }
 | |
|     return pEntry;
 | |
| }
 | |
| 
 | |
| void
 | |
| dmxConfigFreeEntry(DMXConfigEntryPtr entry)
 | |
| {
 | |
|     DMXConfigEntryPtr pt;
 | |
| 
 | |
|     for (pt = entry; pt; pt = pt->next) {
 | |
|         switch (pt->type) {
 | |
|         case dmxConfigComment:
 | |
|             dmxConfigFreeComment(pt->comment);
 | |
|             break;
 | |
|         case dmxConfigVirtual:
 | |
|             dmxConfigFreeVirtual(pt->virtual);
 | |
|             break;
 | |
|         default:
 | |
|             dmxConfigLog("Type %d not supported in entry\n", pt->type);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     dmxConfigFree(entry);
 | |
| }
 | |
| 
 | |
| DMXConfigEntryPtr
 | |
| dmxConfigAddEntry(DMXConfigEntryPtr head,
 | |
|                   DMXConfigType type,
 | |
|                   DMXConfigCommentPtr comment, DMXConfigVirtualPtr virtual)
 | |
| {
 | |
|     DMXConfigEntryPtr child = dmxConfigCreateEntry(type, comment, virtual);
 | |
|     DMXConfigEntryPtr pt;
 | |
| 
 | |
|     if (!head)
 | |
|         return child;
 | |
| 
 | |
|     for (pt = head; pt->next; pt = pt->next);
 | |
|     pt->next = child;
 | |
| 
 | |
|     return head;
 | |
| }
 | |
| 
 | |
| DMXConfigEntryPtr
 | |
| dmxConfigEntryComment(DMXConfigCommentPtr comment)
 | |
| {
 | |
|     return dmxConfigCreateEntry(dmxConfigComment, comment, NULL);
 | |
| }
 | |
| 
 | |
| DMXConfigEntryPtr
 | |
| dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual)
 | |
| {
 | |
|     return dmxConfigCreateEntry(dmxConfigVirtual, NULL, virtual);
 | |
| }
 |