aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/dmx/config/dmxparse.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2012-03-26 14:23:28 +0200
committermarha <marha@users.sourceforge.net>2012-03-26 14:23:28 +0200
commit76bcc36ed305418a3ddc5752d287ede894243e1b (patch)
treebacb320c825768471ce56f058f17ce863d592376 /xorg-server/hw/dmx/config/dmxparse.c
parent7d894e32566b710952c44cbc71939ad1d9e2fa8d (diff)
parent0f834b91a4768673833ab4917e87d86c237bb1a6 (diff)
downloadvcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.gz
vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.bz2
vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.zip
Merge remote-tracking branch 'origin/released'
Conflicts: pixman/pixman/pixman-mmx.c xorg-server/Xext/shm.c xorg-server/Xext/syncsrv.h xorg-server/Xext/xvmain.c xorg-server/Xi/exevents.c xorg-server/Xi/opendev.c xorg-server/composite/compalloc.c xorg-server/composite/compoverlay.c xorg-server/dix/colormap.c xorg-server/dix/devices.c xorg-server/dix/dispatch.c xorg-server/dix/dixfonts.c xorg-server/dix/eventconvert.c xorg-server/dix/events.c xorg-server/dix/gc.c xorg-server/dix/getevents.c xorg-server/dix/main.c xorg-server/dix/privates.c xorg-server/dix/registry.c xorg-server/dix/resource.c xorg-server/exa/exa_accel.c xorg-server/exa/exa_migration_classic.c xorg-server/exa/exa_unaccel.c xorg-server/fb/fb.h xorg-server/fb/fbcopy.c xorg-server/fb/fbpixmap.c xorg-server/glx/dispatch.h xorg-server/glx/glapi.h xorg-server/glx/glapi_gentable.c xorg-server/glx/glapitable.h xorg-server/glx/glprocs.h xorg-server/glx/glxcmds.c xorg-server/glx/glxcmdsswap.c xorg-server/glx/glxdricommon.c xorg-server/glx/glxdriswrast.c xorg-server/glx/glxext.c xorg-server/glx/indirect_dispatch.c xorg-server/glx/indirect_dispatch.h xorg-server/glx/indirect_dispatch_swap.c xorg-server/glx/indirect_size.h xorg-server/glx/indirect_size_get.h xorg-server/glx/indirect_table.c xorg-server/glx/indirect_util.c xorg-server/glx/rensize.c xorg-server/glx/single2swap.c xorg-server/glx/singlepix.c xorg-server/glx/singlepixswap.c xorg-server/glx/singlesize.c xorg-server/hw/dmx/dmxinit.c xorg-server/hw/kdrive/ephyr/ephyr.c xorg-server/hw/kdrive/ephyr/hostx.c xorg-server/hw/kdrive/ephyr/hostx.h xorg-server/hw/kdrive/src/kinput.c xorg-server/hw/xfree86/common/compiler.h xorg-server/hw/xwin/InitInput.c xorg-server/hw/xwin/InitOutput.c xorg-server/hw/xwin/ddraw.h xorg-server/hw/xwin/glx/glwrap.c xorg-server/hw/xwin/glx/indirect.c xorg-server/hw/xwin/glx/wgl_ext_api.h xorg-server/hw/xwin/glx/winpriv.c xorg-server/hw/xwin/win.h xorg-server/hw/xwin/winallpriv.c xorg-server/hw/xwin/winauth.c xorg-server/hw/xwin/winclipboard.h xorg-server/hw/xwin/winclipboardinit.c xorg-server/hw/xwin/winclipboardthread.c xorg-server/hw/xwin/winclipboardunicode.c xorg-server/hw/xwin/winclipboardwndproc.c xorg-server/hw/xwin/winclipboardwrappers.c xorg-server/hw/xwin/winclipboardxevents.c xorg-server/hw/xwin/wincmap.c xorg-server/hw/xwin/winconfig.c xorg-server/hw/xwin/wincreatewnd.c xorg-server/hw/xwin/wincursor.c xorg-server/hw/xwin/windialogs.c xorg-server/hw/xwin/winengine.c xorg-server/hw/xwin/winerror.c xorg-server/hw/xwin/wingc.c xorg-server/hw/xwin/wingetsp.c xorg-server/hw/xwin/winkeybd.c xorg-server/hw/xwin/winkeybd.h xorg-server/hw/xwin/winlayouts.h xorg-server/hw/xwin/winmisc.c xorg-server/hw/xwin/winmonitors.c xorg-server/hw/xwin/winmouse.c xorg-server/hw/xwin/winmsg.c xorg-server/hw/xwin/winmsg.h xorg-server/hw/xwin/winmultiwindowclass.c xorg-server/hw/xwin/winmultiwindowicons.c xorg-server/hw/xwin/winmultiwindowshape.c xorg-server/hw/xwin/winmultiwindowwindow.c xorg-server/hw/xwin/winmultiwindowwm.c xorg-server/hw/xwin/winmultiwindowwndproc.c xorg-server/hw/xwin/winnativegdi.c xorg-server/hw/xwin/winpfbdd.c xorg-server/hw/xwin/winpixmap.c xorg-server/hw/xwin/winpolyline.c xorg-server/hw/xwin/winprefs.c xorg-server/hw/xwin/winprocarg.c xorg-server/hw/xwin/winregistry.c xorg-server/hw/xwin/winscrinit.c xorg-server/hw/xwin/winsetsp.c xorg-server/hw/xwin/winshaddd.c xorg-server/hw/xwin/winshadddnl.c xorg-server/hw/xwin/winshadgdi.c xorg-server/hw/xwin/wintrayicon.c xorg-server/hw/xwin/winwin32rootless.c xorg-server/hw/xwin/winwin32rootlesswindow.c xorg-server/hw/xwin/winwin32rootlesswndproc.c xorg-server/hw/xwin/winwindow.c xorg-server/hw/xwin/winwindow.h xorg-server/hw/xwin/winwindowswm.c xorg-server/hw/xwin/winwndproc.c xorg-server/include/callback.h xorg-server/include/dixstruct.h xorg-server/include/misc.h xorg-server/include/os.h xorg-server/include/scrnintstr.h xorg-server/mi/micmap.c xorg-server/mi/miinitext.c xorg-server/mi/mioverlay.c xorg-server/mi/misprite.c xorg-server/mi/mivaltree.c xorg-server/mi/miwindow.c xorg-server/miext/damage/damage.c xorg-server/miext/rootless/rootlessGC.c xorg-server/miext/rootless/rootlessWindow.c xorg-server/os/WaitFor.c xorg-server/os/access.c xorg-server/os/connection.c xorg-server/os/io.c xorg-server/os/log.c xorg-server/os/osinit.c xorg-server/os/utils.c xorg-server/os/xdmcp.c xorg-server/os/xprintf.c xorg-server/os/xstrans.c xorg-server/render/mipict.c xorg-server/xkb/xkbActions.c xorg-server/xkb/xkbInit.c xorg-server/xkeyboard-config/compat/default.in
Diffstat (limited to 'xorg-server/hw/dmx/config/dmxparse.c')
-rw-r--r--xorg-server/hw/dmx/config/dmxparse.c1295
1 files changed, 688 insertions, 607 deletions
diff --git a/xorg-server/hw/dmx/config/dmxparse.c b/xorg-server/hw/dmx/config/dmxparse.c
index f75151eac..cf510844d 100644
--- a/xorg-server/hw/dmx/config/dmxparse.c
+++ b/xorg-server/hw/dmx/config/dmxparse.c
@@ -1,607 +1,688 @@
-/*
- * 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);
- strncpy(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);
-}
+/*
+ * 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);
+
+ strncpy(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);
+}