1706f2543Smrg/* 2706f2543Smrg * Copyright 2002 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Authors: 30706f2543Smrg * Rickard E. (Rik) Faith <faith@redhat.com> 31706f2543Smrg * 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg/** \file 35706f2543Smrg * 36706f2543Smrg * This file provides support routines and helper functions to be used 37706f2543Smrg * to pretty-print DMX configurations. 38706f2543Smrg * 39706f2543Smrg * Because the DMX configuration file parsing should be capable of being 40706f2543Smrg * used in a stand-alone fashion (i.e., independent from the DMX server 41706f2543Smrg * source tree), no dependencies on other DMX routines are made. */ 42706f2543Smrg 43706f2543Smrg#ifdef HAVE_DMX_CONFIG_H 44706f2543Smrg#include <dmx-config.h> 45706f2543Smrg#endif 46706f2543Smrg 47706f2543Smrg#include "dmxconfig.h" 48706f2543Smrg#include "dmxparse.h" 49706f2543Smrg#include "dmxprint.h" 50706f2543Smrg#include "parser.h" 51706f2543Smrg#include <stdio.h> 52706f2543Smrg#include <stdarg.h> 53706f2543Smrg#include <ctype.h> 54706f2543Smrg 55706f2543Smrgstatic FILE *str = NULL; 56706f2543Smrgstatic int indent = 0; 57706f2543Smrgstatic int pos = 0; 58706f2543Smrg 59706f2543Smrg/** Stack of indentation information used for pretty-printing 60706f2543Smrg * configuration information. */ 61706f2543Smrgstatic struct stack { 62706f2543Smrg int base; 63706f2543Smrg int comment; 64706f2543Smrg int step; 65706f2543Smrg struct stack *next; 66706f2543Smrg} *stack, initialStack = { 0, 0, 4, NULL }; 67706f2543Smrg 68706f2543Smrgstatic void dmxConfigIndent(void) 69706f2543Smrg{ 70706f2543Smrg int i; 71706f2543Smrg if (indent < 0) indent = 0; 72706f2543Smrg if (indent > 40) indent = 40; 73706f2543Smrg for (i = 0; i < indent; i++) fprintf(str, " "); 74706f2543Smrg} 75706f2543Smrg 76706f2543Smrgstatic void dmxConfigNewline(void) 77706f2543Smrg{ 78706f2543Smrg if (pos) fprintf(str, "\n"); 79706f2543Smrg pos = 0; 80706f2543Smrg} 81706f2543Smrg 82706f2543Smrgstatic void dmxConfigPushState(int base, int comment, int step) 83706f2543Smrg{ 84706f2543Smrg struct stack *new = dmxConfigAlloc(sizeof(*new)); 85706f2543Smrg new->base = base; 86706f2543Smrg new->comment = comment; 87706f2543Smrg new->step = step; 88706f2543Smrg new->next = stack; 89706f2543Smrg stack = new; 90706f2543Smrg indent = base; 91706f2543Smrg dmxConfigNewline(); 92706f2543Smrg} 93706f2543Smrg 94706f2543Smrgstatic void dmxConfigPushComment(void) 95706f2543Smrg{ 96706f2543Smrg if (stack) indent = stack->comment; 97706f2543Smrg} 98706f2543Smrg 99706f2543Smrgstatic void dmxConfigPushStep(void) 100706f2543Smrg{ 101706f2543Smrg if (stack) indent = stack->step; 102706f2543Smrg} 103706f2543Smrg 104706f2543Smrgstatic void dmxConfigPopState(void) 105706f2543Smrg{ 106706f2543Smrg struct stack *old = stack; 107706f2543Smrg 108706f2543Smrg if (!stack) return; 109706f2543Smrg indent = old->base; 110706f2543Smrg stack = old->next; 111706f2543Smrg if (!stack) dmxConfigLog("Stack underflow\n"); 112706f2543Smrg dmxConfigFree(old); 113706f2543Smrg dmxConfigNewline(); 114706f2543Smrg} 115706f2543Smrg 116706f2543Smrgstatic void dmxConfigOutput(int addSpace, int doNewline, const char *comment, 117706f2543Smrg const char *format, ...) 118706f2543Smrg{ 119706f2543Smrg va_list args; 120706f2543Smrg 121706f2543Smrg if (!pos) dmxConfigIndent(); 122706f2543Smrg else if (addSpace) fprintf(str, " "); 123706f2543Smrg 124706f2543Smrg if (format) { 125706f2543Smrg va_start(args, format); 126706f2543Smrg /* RATS: This hasn't been audited -- it 127706f2543Smrg * could probably result in a buffer 128706f2543Smrg * overflow. */ 129706f2543Smrg pos += vfprintf(str, format, args); /* assumes no newlines! */ 130706f2543Smrg va_end(args); 131706f2543Smrg } 132706f2543Smrg 133706f2543Smrg if (comment) { 134706f2543Smrg if (pos) fprintf(str, " "); 135706f2543Smrg pos += fprintf(str, "#%s", comment); 136706f2543Smrg dmxConfigNewline(); 137706f2543Smrg dmxConfigPushComment(); 138706f2543Smrg } else if (doNewline) dmxConfigNewline(); 139706f2543Smrg} 140706f2543Smrg 141706f2543Smrgstatic void dmxConfigPrintComment(DMXConfigCommentPtr p) 142706f2543Smrg{ 143706f2543Smrg dmxConfigOutput(1, 1, p->comment, NULL); 144706f2543Smrg} 145706f2543Smrg 146706f2543Smrgstatic void dmxConfigPrintTokenFlag(DMXConfigTokenPtr p, int flag) 147706f2543Smrg{ 148706f2543Smrg if (!p) return; 149706f2543Smrg switch (p->token) { 150706f2543Smrg case T_VIRTUAL: 151706f2543Smrg dmxConfigPushState(0, 4, 4); 152706f2543Smrg dmxConfigOutput(0, 0, p->comment, "virtual"); 153706f2543Smrg break; 154706f2543Smrg case T_DISPLAY: 155706f2543Smrg dmxConfigPushState(4, 12, 16); 156706f2543Smrg dmxConfigOutput(0, 0, p->comment, "display"); 157706f2543Smrg break; 158706f2543Smrg case T_WALL: 159706f2543Smrg dmxConfigPushState(4, 12, 16); 160706f2543Smrg dmxConfigOutput(0, 0, p->comment, "wall"); 161706f2543Smrg break; 162706f2543Smrg case T_OPTION: 163706f2543Smrg dmxConfigPushState(4, 12, 16); 164706f2543Smrg dmxConfigOutput(0, 0, p->comment, "option"); 165706f2543Smrg break; 166706f2543Smrg case T_PARAM: 167706f2543Smrg dmxConfigPushState(4, 8, 12); 168706f2543Smrg dmxConfigOutput(0, 0, p->comment, "param"); 169706f2543Smrg break; 170706f2543Smrg case ';': 171706f2543Smrg dmxConfigOutput(0, 1, p->comment, ";"); 172706f2543Smrg if (flag) dmxConfigPopState(); 173706f2543Smrg break; 174706f2543Smrg case '{': 175706f2543Smrg dmxConfigOutput(1, 1, p->comment, "{"); 176706f2543Smrg dmxConfigPushStep(); 177706f2543Smrg break; 178706f2543Smrg case '}': 179706f2543Smrg if (flag) dmxConfigPopState(); 180706f2543Smrg dmxConfigOutput(0, 1, p->comment, "}"); 181706f2543Smrg break; 182706f2543Smrg case '/': 183706f2543Smrg dmxConfigOutput(1, 0, NULL, "/"); 184706f2543Smrg break; 185706f2543Smrg default: 186706f2543Smrg dmxConfigLog("unknown token %d on line %d\n", p->token, p->line); 187706f2543Smrg } 188706f2543Smrg} 189706f2543Smrg 190706f2543Smrgstatic void dmxConfigPrintToken(DMXConfigTokenPtr p) 191706f2543Smrg{ 192706f2543Smrg dmxConfigPrintTokenFlag(p, 1); 193706f2543Smrg} 194706f2543Smrg 195706f2543Smrgstatic void dmxConfigPrintTokenNopop(DMXConfigTokenPtr p) 196706f2543Smrg{ 197706f2543Smrg dmxConfigPrintTokenFlag(p, 0); 198706f2543Smrg} 199706f2543Smrg 200706f2543Smrgstatic int dmxConfigPrintQuotedString(const char *s) 201706f2543Smrg{ 202706f2543Smrg const char *pt; 203706f2543Smrg 204706f2543Smrg if (!s || !s[0]) return 1; /* Quote empty string */ 205706f2543Smrg for (pt = s; *pt; ++pt) if (isspace(*pt)) return 1; 206706f2543Smrg return 0; 207706f2543Smrg} 208706f2543Smrg 209706f2543Smrgstatic void dmxConfigPrintString(DMXConfigStringPtr p, int quote) 210706f2543Smrg{ 211706f2543Smrg DMXConfigStringPtr pt; 212706f2543Smrg 213706f2543Smrg if (!p) return; 214706f2543Smrg for (pt = p; pt; pt = pt->next) { 215706f2543Smrg if (quote && dmxConfigPrintQuotedString(pt->string)) { 216706f2543Smrg dmxConfigOutput(1, 0, pt->comment, "\"%s\"", 217706f2543Smrg pt->string ? pt->string : ""); 218706f2543Smrg } else 219706f2543Smrg dmxConfigOutput(1, 0, pt->comment, "%s", 220706f2543Smrg pt->string ? pt->string : ""); 221706f2543Smrg } 222706f2543Smrg} 223706f2543Smrg 224706f2543Smrgstatic int dmxConfigPrintPair(DMXConfigPairPtr p, int addSpace) 225706f2543Smrg{ 226706f2543Smrg const char *format = NULL; 227706f2543Smrg 228706f2543Smrg if (!p) return 0; 229706f2543Smrg switch (p->token) { 230706f2543Smrg case T_ORIGIN: format = "@%dx%d"; break; 231706f2543Smrg case T_DIMENSION: format = "%dx%d"; break; 232706f2543Smrg case T_OFFSET: format = "%c%d%c%d"; break; 233706f2543Smrg } 234706f2543Smrg if (p->token == T_OFFSET) { 235706f2543Smrg if (!p->comment && !p->x && !p->y && p->xsign >= 0 && p->ysign >= 0) 236706f2543Smrg return 0; 237706f2543Smrg dmxConfigOutput(addSpace, 0, p->comment, format, 238706f2543Smrg p->xsign < 0 ? '-' : '+', p->x, 239706f2543Smrg p->ysign < 0 ? '-' : '+', p->y); 240706f2543Smrg } else { 241706f2543Smrg if (!p->comment && !p->x && !p->y) return 0; 242706f2543Smrg dmxConfigOutput(addSpace, 0, p->comment, format, p->x, p->y); 243706f2543Smrg } 244706f2543Smrg return 1; 245706f2543Smrg} 246706f2543Smrg 247706f2543Smrgstatic void dmxConfigPrintDisplay(DMXConfigDisplayPtr p) 248706f2543Smrg{ 249706f2543Smrg DMXConfigToken dummyStart = { T_DISPLAY, 0, NULL }; 250706f2543Smrg DMXConfigToken dummyEnd = { ';', 0, NULL }; 251706f2543Smrg DMXConfigToken dummySep = { '/', 0, NULL }; 252706f2543Smrg DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL }; 253706f2543Smrg DMXConfigPair dummySDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 }; 254706f2543Smrg DMXConfigPair dummySOffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 }; 255706f2543Smrg DMXConfigPair dummyRDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 }; 256706f2543Smrg DMXConfigPair dummyROffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 }; 257706f2543Smrg DMXConfigPair dummyOrigin = { T_ORIGIN, 0, NULL, 0, 0, 0, 0 }; 258706f2543Smrg int output; 259706f2543Smrg 260706f2543Smrg if (p->dname) p->dname->string = p->name; 261706f2543Smrg else dummyName.string = p->name; 262706f2543Smrg 263706f2543Smrg if (p->dim && p->dim->scrn && p->dim->scrn->dim) { 264706f2543Smrg p->dim->scrn->dim->x = p->scrnWidth; 265706f2543Smrg p->dim->scrn->dim->y = p->scrnHeight; 266706f2543Smrg } else { 267706f2543Smrg dummySDim.x = p->scrnWidth; 268706f2543Smrg dummySDim.y = p->scrnHeight; 269706f2543Smrg } 270706f2543Smrg 271706f2543Smrg if (p->dim && p->dim->scrn && p->dim->scrn->offset) { 272706f2543Smrg p->dim->scrn->offset->x = p->scrnX; 273706f2543Smrg p->dim->scrn->offset->y = p->scrnY; 274706f2543Smrg } else { 275706f2543Smrg dummySOffset.x = p->scrnX; 276706f2543Smrg dummySOffset.y = p->scrnY; 277706f2543Smrg } 278706f2543Smrg 279706f2543Smrg if (p->dim && p->dim->root && p->dim->root->dim) { 280706f2543Smrg p->dim->root->dim->x = p->rootWidth; 281706f2543Smrg p->dim->root->dim->y = p->rootHeight; 282706f2543Smrg } else { 283706f2543Smrg dummyRDim.x = p->rootWidth; 284706f2543Smrg dummyRDim.y = p->rootHeight; 285706f2543Smrg } 286706f2543Smrg 287706f2543Smrg if (p->dim && p->dim->root && p->dim->root->offset) { 288706f2543Smrg p->dim->root->offset->x = p->rootX; 289706f2543Smrg p->dim->root->offset->y = p->rootY; 290706f2543Smrg } else { 291706f2543Smrg dummyROffset.x = p->rootX; 292706f2543Smrg dummyROffset.y = p->rootY; 293706f2543Smrg } 294706f2543Smrg 295706f2543Smrg if (p->origin) { 296706f2543Smrg p->origin->x = p->rootXOrigin, p->origin->y = p->rootYOrigin; 297706f2543Smrg p->origin->xsign = p->rootXSign, p->origin->ysign = p->rootYSign; 298706f2543Smrg } else { 299706f2543Smrg dummyOrigin.x = p->rootXOrigin, dummyOrigin.y = p->rootYOrigin; 300706f2543Smrg dummyOrigin.xsign = p->rootXSign, dummyOrigin.ysign = p->rootYSign; 301706f2543Smrg } 302706f2543Smrg 303706f2543Smrg dmxConfigPrintToken(p->start ? p->start : &dummyStart); 304706f2543Smrg dmxConfigPrintString(p->dname ? p->dname : &dummyName, 1); 305706f2543Smrg 306706f2543Smrg if (p->dim && p->dim->scrn && p->dim->scrn->dim) 307706f2543Smrg output = dmxConfigPrintPair(p->dim->scrn->dim, 1); 308706f2543Smrg else 309706f2543Smrg output = dmxConfigPrintPair(&dummySDim, 1); 310706f2543Smrg if (p->dim && p->dim->scrn && p->dim->scrn->offset) 311706f2543Smrg dmxConfigPrintPair(p->dim->scrn->offset, !output); 312706f2543Smrg else 313706f2543Smrg dmxConfigPrintPair(&dummySOffset, !output); 314706f2543Smrg 315706f2543Smrg if (p->scrnWidth != p->rootWidth 316706f2543Smrg || p->scrnHeight != p->rootHeight 317706f2543Smrg || p->rootX 318706f2543Smrg || p->rootY) { 319706f2543Smrg dmxConfigPrintToken(&dummySep); 320706f2543Smrg if (p->dim && p->dim->root && p->dim->root->dim) 321706f2543Smrg output = dmxConfigPrintPair(p->dim->root->dim, 1); 322706f2543Smrg else 323706f2543Smrg output = dmxConfigPrintPair(&dummyRDim, 1); 324706f2543Smrg if (p->dim && p->dim->root && p->dim->root->offset) 325706f2543Smrg dmxConfigPrintPair(p->dim->root->offset, !output); 326706f2543Smrg else 327706f2543Smrg dmxConfigPrintPair(&dummyROffset, !output); 328706f2543Smrg } 329706f2543Smrg 330706f2543Smrg dmxConfigPrintPair(p->origin ? p->origin : &dummyOrigin, 1); 331706f2543Smrg dmxConfigPrintToken(p->end ? p->end : &dummyEnd); 332706f2543Smrg} 333706f2543Smrg 334706f2543Smrgstatic void dmxConfigPrintWall(DMXConfigWallPtr p) 335706f2543Smrg{ 336706f2543Smrg dmxConfigPrintToken(p->start); 337706f2543Smrg dmxConfigPrintPair(p->wallDim, 1); 338706f2543Smrg dmxConfigPrintPair(p->displayDim, 1); 339706f2543Smrg dmxConfigPrintString(p->nameList, 1); 340706f2543Smrg dmxConfigPrintToken(p->end); 341706f2543Smrg} 342706f2543Smrg 343706f2543Smrgstatic void dmxConfigPrintOption(DMXConfigOptionPtr p) 344706f2543Smrg{ 345706f2543Smrg DMXConfigToken dummyStart = { T_OPTION, 0, NULL }; 346706f2543Smrg DMXConfigString dummyOption = { T_STRING, 0, NULL, NULL, NULL }; 347706f2543Smrg DMXConfigToken dummyEnd = { ';', 0, NULL }; 348706f2543Smrg 349706f2543Smrg dummyOption.string = p->string; 350706f2543Smrg 351706f2543Smrg dmxConfigPrintToken(p->start ? p->start : &dummyStart); 352706f2543Smrg dmxConfigPrintString(&dummyOption, 0); 353706f2543Smrg dmxConfigPrintToken(p->end ? p->end : &dummyEnd); 354706f2543Smrg} 355706f2543Smrg 356706f2543Smrgstatic void dmxConfigPrintParam(DMXConfigParamPtr p) 357706f2543Smrg{ 358706f2543Smrg if (!p) return; 359706f2543Smrg if (p->start) { 360706f2543Smrg if (p->open && p->close) { 361706f2543Smrg dmxConfigPrintToken(p->start); 362706f2543Smrg dmxConfigPrintToken(p->open); 363706f2543Smrg dmxConfigPrintParam(p->next); 364706f2543Smrg dmxConfigPrintToken(p->close); 365706f2543Smrg } else if (p->end && p->param) { 366706f2543Smrg dmxConfigPrintToken(p->start); 367706f2543Smrg dmxConfigPrintString(p->param, 1); 368706f2543Smrg dmxConfigPrintToken(p->end); 369706f2543Smrg } else 370706f2543Smrg dmxConfigLog("dmxConfigPrintParam: cannot handle format (a)\n"); 371706f2543Smrg } else if (p->end && p->param) { 372706f2543Smrg dmxConfigPrintString(p->param, 1); 373706f2543Smrg dmxConfigPrintTokenNopop(p->end); 374706f2543Smrg dmxConfigPrintParam(p->next); 375706f2543Smrg } else 376706f2543Smrg dmxConfigLog("dmxConfigPrintParam: cannot handle format (b)\n"); 377706f2543Smrg} 378706f2543Smrg 379706f2543Smrgstatic void dmxConfigPrintSub(DMXConfigSubPtr p) 380706f2543Smrg{ 381706f2543Smrg DMXConfigSubPtr pt; 382706f2543Smrg 383706f2543Smrg if (!p) return; 384706f2543Smrg for (pt = p; pt; pt = pt->next) { 385706f2543Smrg switch (pt->type) { 386706f2543Smrg case dmxConfigComment: dmxConfigPrintComment(pt->comment); break; 387706f2543Smrg case dmxConfigDisplay: dmxConfigPrintDisplay(pt->display); break; 388706f2543Smrg case dmxConfigWall: dmxConfigPrintWall(pt->wall); break; 389706f2543Smrg case dmxConfigOption: dmxConfigPrintOption(pt->option); break; 390706f2543Smrg case dmxConfigParam: dmxConfigPrintParam(pt->param); break; 391706f2543Smrg default: 392706f2543Smrg dmxConfigLog("dmxConfigPrintSub:" 393706f2543Smrg " cannot handle type %d in subentry\n", pt->type); 394706f2543Smrg } 395706f2543Smrg } 396706f2543Smrg} 397706f2543Smrg 398706f2543Smrgstatic void dmxConfigPrintVirtual(DMXConfigVirtualPtr p) 399706f2543Smrg{ 400706f2543Smrg DMXConfigToken dummyStart = { T_VIRTUAL, 0, NULL }; 401706f2543Smrg DMXConfigToken dummyOpen = { '{', 0, NULL }; 402706f2543Smrg DMXConfigToken dummyClose = { '}', 0, NULL }; 403706f2543Smrg DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL }; 404706f2543Smrg DMXConfigPair dummyDim = { T_DIMENSION, 0, NULL, 0, 0 }; 405706f2543Smrg 406706f2543Smrg if (p->vname) p->vname->string = p->name; 407706f2543Smrg else dummyName.string = p->name; 408706f2543Smrg 409706f2543Smrg if (p->dim) p->dim->x = p->width, p->dim->y = p->height; 410706f2543Smrg else dummyDim.x = p->width, dummyDim.y = p->height; 411706f2543Smrg 412706f2543Smrg 413706f2543Smrg dmxConfigPrintToken(p->start ? p->start : &dummyStart); 414706f2543Smrg dmxConfigPrintString(p->vname ? p->vname : &dummyName, 1); 415706f2543Smrg dmxConfigPrintPair(p->dim ? p->dim : &dummyDim, 1); 416706f2543Smrg dmxConfigPrintToken(p->open ? p->open : &dummyOpen); 417706f2543Smrg dmxConfigPrintSub(p->subentry); 418706f2543Smrg dmxConfigPrintToken(p->close ? p->close : &dummyClose); 419706f2543Smrg} 420706f2543Smrg 421706f2543Smrg/** The configuration information in \a entry will be pretty-printed to 422706f2543Smrg * the \a stream. If \a stream is NULL, then stdout will be used. */ 423706f2543Smrgvoid dmxConfigPrint(FILE *stream, DMXConfigEntryPtr entry) 424706f2543Smrg{ 425706f2543Smrg DMXConfigEntryPtr pt; 426706f2543Smrg 427706f2543Smrg if (!stream) str = stdout; 428706f2543Smrg else str = stream; 429706f2543Smrg 430706f2543Smrg stack = &initialStack; 431706f2543Smrg 432706f2543Smrg for (pt = entry; pt; pt = pt->next) { 433706f2543Smrg switch (pt->type) { 434706f2543Smrg case dmxConfigComment: dmxConfigPrintComment(pt->comment); break; 435706f2543Smrg case dmxConfigVirtual: dmxConfigPrintVirtual(pt->virtual); break; 436706f2543Smrg default: 437706f2543Smrg dmxConfigLog("dmxConfigPrint: cannot handle type %d in entry\n", 438706f2543Smrg pt->type); 439706f2543Smrg } 440706f2543Smrg } 441706f2543Smrg if (pos) dmxConfigNewline(); 442706f2543Smrg} 443706f2543Smrg 444706f2543Smrg/** The configuration information in \a p will be pretty-printed to the 445706f2543Smrg * \a stream. If \a stream is NULL, then stdout will be used. */ 446706f2543Smrgvoid dmxConfigVirtualPrint(FILE *stream, DMXConfigVirtualPtr p) 447706f2543Smrg{ 448706f2543Smrg if (!stream) str = stdout; 449706f2543Smrg else str = stream; 450706f2543Smrg 451706f2543Smrg stack = &initialStack; 452706f2543Smrg 453706f2543Smrg dmxConfigPrintVirtual(p); 454706f2543Smrg if (pos) dmxConfigNewline(); 455706f2543Smrg} 456