2 * Copyright 2002 Red Hat Inc., Durham, North Carolina.
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:
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.
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
30 * Rickard E. (Rik) Faith <faith@redhat.com>
36 * This file provides support routines and helper functions to be used
37 * to pretty-print DMX configurations.
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. */
43 #ifdef HAVE_DMX_CONFIG_H
44 #include <dmx-config.h>
47 #include "dmxconfig.h"
55 static FILE *str
= NULL
;
56 static int indent
= 0;
59 /** Stack of indentation information used for pretty-printing
60 * configuration information. */
66 } *stack
, initialStack
= {
78 for (i
= 0; i
< indent
; i
++)
83 dmxConfigNewline(void)
91 dmxConfigPushState(int base
, int comment
, int step
)
93 struct stack
*new = dmxConfigAlloc(sizeof(*new));
96 new->comment
= comment
;
105 dmxConfigPushComment(void)
108 indent
= stack
->comment
;
112 dmxConfigPushStep(void)
115 indent
= stack
->step
;
119 dmxConfigPopState(void)
121 struct stack
*old
= stack
;
128 dmxConfigLog("Stack underflow\n");
134 dmxConfigOutput(int addSpace
, int doNewline
, const char *comment
,
135 const char *format
, ...)
145 va_start(args
, format
);
146 /* RATS: This hasn't been audited -- it
147 * could probably result in a buffer
149 pos
+= vfprintf(str
, format
, args
); /* assumes no newlines! */
156 pos
+= fprintf(str
, "#%s", comment
);
158 dmxConfigPushComment();
165 dmxConfigPrintComment(DMXConfigCommentPtr p
)
167 dmxConfigOutput(1, 1, p
->comment
, NULL
);
171 dmxConfigPrintTokenFlag(DMXConfigTokenPtr p
, int flag
)
177 dmxConfigPushState(0, 4, 4);
178 dmxConfigOutput(0, 0, p
->comment
, "virtual");
181 dmxConfigPushState(4, 12, 16);
182 dmxConfigOutput(0, 0, p
->comment
, "display");
185 dmxConfigPushState(4, 12, 16);
186 dmxConfigOutput(0, 0, p
->comment
, "wall");
189 dmxConfigPushState(4, 12, 16);
190 dmxConfigOutput(0, 0, p
->comment
, "option");
193 dmxConfigPushState(4, 8, 12);
194 dmxConfigOutput(0, 0, p
->comment
, "param");
197 dmxConfigOutput(0, 1, p
->comment
, ";");
202 dmxConfigOutput(1, 1, p
->comment
, "{");
208 dmxConfigOutput(0, 1, p
->comment
, "}");
211 dmxConfigOutput(1, 0, NULL
, "/");
214 dmxConfigLog("unknown token %d on line %d\n", p
->token
, p
->line
);
219 dmxConfigPrintToken(DMXConfigTokenPtr p
)
221 dmxConfigPrintTokenFlag(p
, 1);
225 dmxConfigPrintTokenNopop(DMXConfigTokenPtr p
)
227 dmxConfigPrintTokenFlag(p
, 0);
231 dmxConfigPrintQuotedString(const char *s
)
236 return 1; /* Quote empty string */
237 for (pt
= s
; *pt
; ++pt
)
244 dmxConfigPrintString(DMXConfigStringPtr p
, int quote
)
246 DMXConfigStringPtr pt
;
250 for (pt
= p
; pt
; pt
= pt
->next
) {
251 if (quote
&& dmxConfigPrintQuotedString(pt
->string
)) {
252 dmxConfigOutput(1, 0, pt
->comment
, "\"%s\"",
253 pt
->string
? pt
->string
: "");
256 dmxConfigOutput(1, 0, pt
->comment
, "%s",
257 pt
->string
? pt
->string
: "");
262 dmxConfigPrintPair(DMXConfigPairPtr p
, int addSpace
)
264 const char *format
= NULL
;
279 if (p
->token
== T_OFFSET
) {
280 if (!p
->comment
&& !p
->x
&& !p
->y
&& p
->xsign
>= 0 && p
->ysign
>= 0)
282 dmxConfigOutput(addSpace
, 0, p
->comment
, format
,
283 p
->xsign
< 0 ? '-' : '+', p
->x
,
284 p
->ysign
< 0 ? '-' : '+', p
->y
);
287 if (!p
->comment
&& !p
->x
&& !p
->y
)
289 dmxConfigOutput(addSpace
, 0, p
->comment
, format
, p
->x
, p
->y
);
295 dmxConfigPrintDisplay(DMXConfigDisplayPtr p
)
297 DMXConfigToken dummyStart
= { T_DISPLAY
, 0, NULL
};
298 DMXConfigToken dummyEnd
= { ';', 0, NULL
};
299 DMXConfigToken dummySep
= { '/', 0, NULL
};
300 DMXConfigString dummyName
= { T_STRING
, 0, NULL
, NULL
, NULL
};
301 DMXConfigPair dummySDim
= { T_DIMENSION
, 0, NULL
, 0, 0, 0, 0 };
302 DMXConfigPair dummySOffset
= { T_OFFSET
, 0, NULL
, 0, 0, 0, 0 };
303 DMXConfigPair dummyRDim
= { T_DIMENSION
, 0, NULL
, 0, 0, 0, 0 };
304 DMXConfigPair dummyROffset
= { T_OFFSET
, 0, NULL
, 0, 0, 0, 0 };
305 DMXConfigPair dummyOrigin
= { T_ORIGIN
, 0, NULL
, 0, 0, 0, 0 };
309 p
->dname
->string
= p
->name
;
311 dummyName
.string
= p
->name
;
313 if (p
->dim
&& p
->dim
->scrn
&& p
->dim
->scrn
->dim
) {
314 p
->dim
->scrn
->dim
->x
= p
->scrnWidth
;
315 p
->dim
->scrn
->dim
->y
= p
->scrnHeight
;
318 dummySDim
.x
= p
->scrnWidth
;
319 dummySDim
.y
= p
->scrnHeight
;
322 if (p
->dim
&& p
->dim
->scrn
&& p
->dim
->scrn
->offset
) {
323 p
->dim
->scrn
->offset
->x
= p
->scrnX
;
324 p
->dim
->scrn
->offset
->y
= p
->scrnY
;
327 dummySOffset
.x
= p
->scrnX
;
328 dummySOffset
.y
= p
->scrnY
;
331 if (p
->dim
&& p
->dim
->root
&& p
->dim
->root
->dim
) {
332 p
->dim
->root
->dim
->x
= p
->rootWidth
;
333 p
->dim
->root
->dim
->y
= p
->rootHeight
;
336 dummyRDim
.x
= p
->rootWidth
;
337 dummyRDim
.y
= p
->rootHeight
;
340 if (p
->dim
&& p
->dim
->root
&& p
->dim
->root
->offset
) {
341 p
->dim
->root
->offset
->x
= p
->rootX
;
342 p
->dim
->root
->offset
->y
= p
->rootY
;
345 dummyROffset
.x
= p
->rootX
;
346 dummyROffset
.y
= p
->rootY
;
350 p
->origin
->x
= p
->rootXOrigin
, p
->origin
->y
= p
->rootYOrigin
;
351 p
->origin
->xsign
= p
->rootXSign
, p
->origin
->ysign
= p
->rootYSign
;
354 dummyOrigin
.x
= p
->rootXOrigin
, dummyOrigin
.y
= p
->rootYOrigin
;
355 dummyOrigin
.xsign
= p
->rootXSign
, dummyOrigin
.ysign
= p
->rootYSign
;
358 dmxConfigPrintToken(p
->start
? p
->start
: &dummyStart
);
359 dmxConfigPrintString(p
->dname
? p
->dname
: &dummyName
, 1);
361 if (p
->dim
&& p
->dim
->scrn
&& p
->dim
->scrn
->dim
)
362 output
= dmxConfigPrintPair(p
->dim
->scrn
->dim
, 1);
364 output
= dmxConfigPrintPair(&dummySDim
, 1);
365 if (p
->dim
&& p
->dim
->scrn
&& p
->dim
->scrn
->offset
)
366 dmxConfigPrintPair(p
->dim
->scrn
->offset
, !output
);
368 dmxConfigPrintPair(&dummySOffset
, !output
);
370 if (p
->scrnWidth
!= p
->rootWidth
371 || p
->scrnHeight
!= p
->rootHeight
|| p
->rootX
|| p
->rootY
) {
372 dmxConfigPrintToken(&dummySep
);
373 if (p
->dim
&& p
->dim
->root
&& p
->dim
->root
->dim
)
374 output
= dmxConfigPrintPair(p
->dim
->root
->dim
, 1);
376 output
= dmxConfigPrintPair(&dummyRDim
, 1);
377 if (p
->dim
&& p
->dim
->root
&& p
->dim
->root
->offset
)
378 dmxConfigPrintPair(p
->dim
->root
->offset
, !output
);
380 dmxConfigPrintPair(&dummyROffset
, !output
);
383 dmxConfigPrintPair(p
->origin
? p
->origin
: &dummyOrigin
, 1);
384 dmxConfigPrintToken(p
->end
? p
->end
: &dummyEnd
);
388 dmxConfigPrintWall(DMXConfigWallPtr p
)
390 dmxConfigPrintToken(p
->start
);
391 dmxConfigPrintPair(p
->wallDim
, 1);
392 dmxConfigPrintPair(p
->displayDim
, 1);
393 dmxConfigPrintString(p
->nameList
, 1);
394 dmxConfigPrintToken(p
->end
);
398 dmxConfigPrintOption(DMXConfigOptionPtr p
)
400 DMXConfigToken dummyStart
= { T_OPTION
, 0, NULL
};
401 DMXConfigString dummyOption
= { T_STRING
, 0, NULL
, NULL
, NULL
};
402 DMXConfigToken dummyEnd
= { ';', 0, NULL
};
404 dummyOption
.string
= p
->string
;
406 dmxConfigPrintToken(p
->start
? p
->start
: &dummyStart
);
407 dmxConfigPrintString(&dummyOption
, 0);
408 dmxConfigPrintToken(p
->end
? p
->end
: &dummyEnd
);
412 dmxConfigPrintParam(DMXConfigParamPtr p
)
417 if (p
->open
&& p
->close
) {
418 dmxConfigPrintToken(p
->start
);
419 dmxConfigPrintToken(p
->open
);
420 dmxConfigPrintParam(p
->next
);
421 dmxConfigPrintToken(p
->close
);
423 else if (p
->end
&& p
->param
) {
424 dmxConfigPrintToken(p
->start
);
425 dmxConfigPrintString(p
->param
, 1);
426 dmxConfigPrintToken(p
->end
);
429 dmxConfigLog("dmxConfigPrintParam: cannot handle format (a)\n");
431 else if (p
->end
&& p
->param
) {
432 dmxConfigPrintString(p
->param
, 1);
433 dmxConfigPrintTokenNopop(p
->end
);
434 dmxConfigPrintParam(p
->next
);
437 dmxConfigLog("dmxConfigPrintParam: cannot handle format (b)\n");
441 dmxConfigPrintSub(DMXConfigSubPtr p
)
447 for (pt
= p
; pt
; pt
= pt
->next
) {
449 case dmxConfigComment
:
450 dmxConfigPrintComment(pt
->comment
);
452 case dmxConfigDisplay
:
453 dmxConfigPrintDisplay(pt
->display
);
456 dmxConfigPrintWall(pt
->wall
);
458 case dmxConfigOption
:
459 dmxConfigPrintOption(pt
->option
);
462 dmxConfigPrintParam(pt
->param
);
465 dmxConfigLog("dmxConfigPrintSub:"
466 " cannot handle type %d in subentry\n", pt
->type
);
472 dmxConfigPrintVirtual(DMXConfigVirtualPtr p
)
474 DMXConfigToken dummyStart
= { T_VIRTUAL
, 0, NULL
};
475 DMXConfigToken dummyOpen
= { '{', 0, NULL
};
476 DMXConfigToken dummyClose
= { '}', 0, NULL
};
477 DMXConfigString dummyName
= { T_STRING
, 0, NULL
, NULL
, NULL
};
478 DMXConfigPair dummyDim
= { T_DIMENSION
, 0, NULL
, 0, 0 };
481 p
->vname
->string
= p
->name
;
483 dummyName
.string
= p
->name
;
486 p
->dim
->x
= p
->width
, p
->dim
->y
= p
->height
;
488 dummyDim
.x
= p
->width
, dummyDim
.y
= p
->height
;
490 dmxConfigPrintToken(p
->start
? p
->start
: &dummyStart
);
491 dmxConfigPrintString(p
->vname
? p
->vname
: &dummyName
, 1);
492 dmxConfigPrintPair(p
->dim
? p
->dim
: &dummyDim
, 1);
493 dmxConfigPrintToken(p
->open
? p
->open
: &dummyOpen
);
494 dmxConfigPrintSub(p
->subentry
);
495 dmxConfigPrintToken(p
->close
? p
->close
: &dummyClose
);
498 /** The configuration information in \a entry will be pretty-printed to
499 * the \a stream. If \a stream is NULL, then stdout will be used. */
501 dmxConfigPrint(FILE * stream
, DMXConfigEntryPtr entry
)
503 DMXConfigEntryPtr pt
;
510 stack
= &initialStack
;
512 for (pt
= entry
; pt
; pt
= pt
->next
) {
514 case dmxConfigComment
:
515 dmxConfigPrintComment(pt
->comment
);
517 case dmxConfigVirtual
:
518 dmxConfigPrintVirtual(pt
->virtual);
521 dmxConfigLog("dmxConfigPrint: cannot handle type %d in entry\n",
529 /** The configuration information in \a p will be pretty-printed to the
530 * \a stream. If \a stream is NULL, then stdout will be used. */
532 dmxConfigVirtualPrint(FILE * stream
, DMXConfigVirtualPtr p
)
539 stack
= &initialStack
;
541 dmxConfigPrintVirtual(p
);