3
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
7
* Permission is hereby granted, free of charge, to any person obtaining
8
* a copy of this software and associated documentation files (the
9
* "Software"), to deal in the Software without restriction, including
10
* without limitation on the rights to use, copy, modify, merge,
11
* publish, distribute, sublicense, and/or sell copies of the Software,
12
* and to permit persons to whom the Software is furnished to do so,
13
* subject to the following conditions:
15
* The above copyright notice and this permission notice (including the
16
* next paragraph) shall be included in all copies or substantial
17
* portions of the Software.
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
23
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
* Rickard E. (Rik) Faith <faith@redhat.com>
37
* This file provides support routines and helper functions to be used
38
* to pretty-print DMX configurations.
40
* Because the DMX configuration file parsing should be capable of being
41
* used in a stand-alone fashion (i.e., independent from the DMX server
42
* source tree), no dependencies on other DMX routines are made. */
44
#ifdef HAVE_DMX_CONFIG_H
45
#include <dmx-config.h>
48
#include "dmxconfig.h"
56
static FILE *str = NULL;
57
static int indent = 0;
60
/** Stack of indentation information used for pretty-printing
61
* configuration information. */
67
} *stack, initialStack = { 0, 0, 4, NULL };
69
static void dmxConfigIndent(void)
72
if (indent < 0) indent = 0;
73
if (indent > 40) indent = 40;
74
for (i = 0; i < indent; i++) fprintf(str, " ");
77
static void dmxConfigNewline(void)
79
if (pos) fprintf(str, "\n");
83
static void dmxConfigPushState(int base, int comment, int step)
85
struct stack *new = dmxConfigAlloc(sizeof(*new));
87
new->comment = comment;
95
static void dmxConfigPushComment(void)
97
if (stack) indent = stack->comment;
100
static void dmxConfigPushStep(void)
102
if (stack) indent = stack->step;
105
static void dmxConfigPopState(void)
107
struct stack *old = stack;
112
if (!stack) dmxConfigLog("Stack underflow\n");
117
static void dmxConfigOutput(int addSpace, int doNewline, const char *comment,
118
const char *format, ...)
122
if (!pos) dmxConfigIndent();
123
else if (addSpace) fprintf(str, " ");
126
va_start(args, format);
127
/* RATS: This hasn't been audited -- it
128
* could probably result in a buffer
130
pos += vfprintf(str, format, args); /* assumes no newlines! */
135
if (pos) fprintf(str, " ");
136
pos += fprintf(str, "#%s", comment);
138
dmxConfigPushComment();
139
} else if (doNewline) dmxConfigNewline();
142
static void dmxConfigPrintComment(DMXConfigCommentPtr p)
144
dmxConfigOutput(1, 1, p->comment, NULL);
147
static void dmxConfigPrintTokenFlag(DMXConfigTokenPtr p, int flag)
152
dmxConfigPushState(0, 4, 4);
153
dmxConfigOutput(0, 0, p->comment, "virtual");
156
dmxConfigPushState(4, 12, 16);
157
dmxConfigOutput(0, 0, p->comment, "display");
160
dmxConfigPushState(4, 12, 16);
161
dmxConfigOutput(0, 0, p->comment, "wall");
164
dmxConfigPushState(4, 12, 16);
165
dmxConfigOutput(0, 0, p->comment, "option");
168
dmxConfigPushState(4, 8, 12);
169
dmxConfigOutput(0, 0, p->comment, "param");
172
dmxConfigOutput(0, 1, p->comment, ";");
173
if (flag) dmxConfigPopState();
176
dmxConfigOutput(1, 1, p->comment, "{");
180
if (flag) dmxConfigPopState();
181
dmxConfigOutput(0, 1, p->comment, "}");
184
dmxConfigOutput(1, 0, NULL, "/");
187
dmxConfigLog("unknown token %d on line %d\n", p->token, p->line);
191
static void dmxConfigPrintToken(DMXConfigTokenPtr p)
193
dmxConfigPrintTokenFlag(p, 1);
196
static void dmxConfigPrintTokenNopop(DMXConfigTokenPtr p)
198
dmxConfigPrintTokenFlag(p, 0);
201
static int dmxConfigPrintQuotedString(const char *s)
205
if (!s || !s[0]) return 1; /* Quote empty string */
206
for (pt = s; *pt; ++pt) if (isspace(*pt)) return 1;
210
static void dmxConfigPrintString(DMXConfigStringPtr p, int quote)
212
DMXConfigStringPtr pt;
215
for (pt = p; pt; pt = pt->next) {
216
if (quote && dmxConfigPrintQuotedString(pt->string)) {
217
dmxConfigOutput(1, 0, pt->comment, "\"%s\"",
218
pt->string ? pt->string : "");
220
dmxConfigOutput(1, 0, pt->comment, "%s",
221
pt->string ? pt->string : "");
225
static int dmxConfigPrintPair(DMXConfigPairPtr p, int addSpace)
227
const char *format = NULL;
231
case T_ORIGIN: format = "@%dx%d"; break;
232
case T_DIMENSION: format = "%dx%d"; break;
233
case T_OFFSET: format = "%c%d%c%d"; break;
235
if (p->token == T_OFFSET) {
236
if (!p->comment && !p->x && !p->y && p->xsign >= 0 && p->ysign >= 0)
238
dmxConfigOutput(addSpace, 0, p->comment, format,
239
p->xsign < 0 ? '-' : '+', p->x,
240
p->ysign < 0 ? '-' : '+', p->y);
242
if (!p->comment && !p->x && !p->y) return 0;
243
dmxConfigOutput(addSpace, 0, p->comment, format, p->x, p->y);
248
static void dmxConfigPrintDisplay(DMXConfigDisplayPtr p)
250
DMXConfigToken dummyStart = { T_DISPLAY, 0, NULL };
251
DMXConfigToken dummyEnd = { ';', 0, NULL };
252
DMXConfigToken dummySep = { '/', 0, NULL };
253
DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL };
254
DMXConfigPair dummySDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 };
255
DMXConfigPair dummySOffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 };
256
DMXConfigPair dummyRDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 };
257
DMXConfigPair dummyROffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 };
258
DMXConfigPair dummyOrigin = { T_ORIGIN, 0, NULL, 0, 0, 0, 0 };
261
if (p->dname) p->dname->string = p->name;
262
else dummyName.string = p->name;
264
if (p->dim && p->dim->scrn && p->dim->scrn->dim) {
265
p->dim->scrn->dim->x = p->scrnWidth;
266
p->dim->scrn->dim->y = p->scrnHeight;
268
dummySDim.x = p->scrnWidth;
269
dummySDim.y = p->scrnHeight;
272
if (p->dim && p->dim->scrn && p->dim->scrn->offset) {
273
p->dim->scrn->offset->x = p->scrnX;
274
p->dim->scrn->offset->y = p->scrnY;
276
dummySOffset.x = p->scrnX;
277
dummySOffset.y = p->scrnY;
280
if (p->dim && p->dim->root && p->dim->root->dim) {
281
p->dim->root->dim->x = p->rootWidth;
282
p->dim->root->dim->y = p->rootHeight;
284
dummyRDim.x = p->rootWidth;
285
dummyRDim.y = p->rootHeight;
288
if (p->dim && p->dim->root && p->dim->root->offset) {
289
p->dim->root->offset->x = p->rootX;
290
p->dim->root->offset->y = p->rootY;
292
dummyROffset.x = p->rootX;
293
dummyROffset.y = p->rootY;
297
p->origin->x = p->rootXOrigin, p->origin->y = p->rootYOrigin;
298
p->origin->xsign = p->rootXSign, p->origin->ysign = p->rootYSign;
300
dummyOrigin.x = p->rootXOrigin, dummyOrigin.y = p->rootYOrigin;
301
dummyOrigin.xsign = p->rootXSign, dummyOrigin.ysign = p->rootYSign;
304
dmxConfigPrintToken(p->start ? p->start : &dummyStart);
305
dmxConfigPrintString(p->dname ? p->dname : &dummyName, 1);
307
if (p->dim && p->dim->scrn && p->dim->scrn->dim)
308
output = dmxConfigPrintPair(p->dim->scrn->dim, 1);
310
output = dmxConfigPrintPair(&dummySDim, 1);
311
if (p->dim && p->dim->scrn && p->dim->scrn->offset)
312
dmxConfigPrintPair(p->dim->scrn->offset, !output);
314
dmxConfigPrintPair(&dummySOffset, !output);
316
if (p->scrnWidth != p->rootWidth
317
|| p->scrnHeight != p->rootHeight
320
dmxConfigPrintToken(&dummySep);
321
if (p->dim && p->dim->root && p->dim->root->dim)
322
output = dmxConfigPrintPair(p->dim->root->dim, 1);
324
output = dmxConfigPrintPair(&dummyRDim, 1);
325
if (p->dim && p->dim->root && p->dim->root->offset)
326
dmxConfigPrintPair(p->dim->root->offset, !output);
328
dmxConfigPrintPair(&dummyROffset, !output);
331
dmxConfigPrintPair(p->origin ? p->origin : &dummyOrigin, 1);
332
dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
335
static void dmxConfigPrintWall(DMXConfigWallPtr p)
337
dmxConfigPrintToken(p->start);
338
dmxConfigPrintPair(p->wallDim, 1);
339
dmxConfigPrintPair(p->displayDim, 1);
340
dmxConfigPrintString(p->nameList, 1);
341
dmxConfigPrintToken(p->end);
344
static void dmxConfigPrintOption(DMXConfigOptionPtr p)
346
DMXConfigToken dummyStart = { T_OPTION, 0, NULL };
347
DMXConfigString dummyOption = { T_STRING, 0, NULL, NULL, NULL };
348
DMXConfigToken dummyEnd = { ';', 0, NULL };
350
dummyOption.string = p->string;
352
dmxConfigPrintToken(p->start ? p->start : &dummyStart);
353
dmxConfigPrintString(&dummyOption, 0);
354
dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
357
static void dmxConfigPrintParam(DMXConfigParamPtr p)
361
if (p->open && p->close) {
362
dmxConfigPrintToken(p->start);
363
dmxConfigPrintToken(p->open);
364
dmxConfigPrintParam(p->next);
365
dmxConfigPrintToken(p->close);
366
} else if (p->end && p->param) {
367
dmxConfigPrintToken(p->start);
368
dmxConfigPrintString(p->param, 1);
369
dmxConfigPrintToken(p->end);
371
dmxConfigLog("dmxConfigPrintParam: cannot handle format (a)\n");
372
} else if (p->end && p->param) {
373
dmxConfigPrintString(p->param, 1);
374
dmxConfigPrintTokenNopop(p->end);
375
dmxConfigPrintParam(p->next);
377
dmxConfigLog("dmxConfigPrintParam: cannot handle format (b)\n");
380
static void dmxConfigPrintSub(DMXConfigSubPtr p)
385
for (pt = p; pt; pt = pt->next) {
387
case dmxConfigComment: dmxConfigPrintComment(pt->comment); break;
388
case dmxConfigDisplay: dmxConfigPrintDisplay(pt->display); break;
389
case dmxConfigWall: dmxConfigPrintWall(pt->wall); break;
390
case dmxConfigOption: dmxConfigPrintOption(pt->option); break;
391
case dmxConfigParam: dmxConfigPrintParam(pt->param); break;
393
dmxConfigLog("dmxConfigPrintSub:"
394
" cannot handle type %d in subentry\n", pt->type);
399
static void dmxConfigPrintVirtual(DMXConfigVirtualPtr p)
401
DMXConfigToken dummyStart = { T_VIRTUAL, 0, NULL };
402
DMXConfigToken dummyOpen = { '{', 0, NULL };
403
DMXConfigToken dummyClose = { '}', 0, NULL };
404
DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL };
405
DMXConfigPair dummyDim = { T_DIMENSION, 0, NULL, 0, 0 };
407
if (p->vname) p->vname->string = p->name;
408
else dummyName.string = p->name;
410
if (p->dim) p->dim->x = p->width, p->dim->y = p->height;
411
else dummyDim.x = p->width, dummyDim.y = p->height;
414
dmxConfigPrintToken(p->start ? p->start : &dummyStart);
415
dmxConfigPrintString(p->vname ? p->vname : &dummyName, 1);
416
dmxConfigPrintPair(p->dim ? p->dim : &dummyDim, 1);
417
dmxConfigPrintToken(p->open ? p->open : &dummyOpen);
418
dmxConfigPrintSub(p->subentry);
419
dmxConfigPrintToken(p->close ? p->close : &dummyClose);
422
/** The configuration information in \a entry will be pretty-printed to
423
* the \a stream. If \a stream is NULL, then stdout will be used. */
424
void dmxConfigPrint(FILE *stream, DMXConfigEntryPtr entry)
426
DMXConfigEntryPtr pt;
428
if (!stream) str = stdout;
431
stack = &initialStack;
433
for (pt = entry; pt; pt = pt->next) {
435
case dmxConfigComment: dmxConfigPrintComment(pt->comment); break;
436
case dmxConfigVirtual: dmxConfigPrintVirtual(pt->virtual); break;
438
dmxConfigLog("dmxConfigPrint: cannot handle type %d in entry\n",
442
if (pos) dmxConfigNewline();
445
/** The configuration information in \a p will be pretty-printed to the
446
* \a stream. If \a stream is NULL, then stdout will be used. */
447
void dmxConfigVirtualPrint(FILE *stream, DMXConfigVirtualPtr p)
449
if (!stream) str = stdout;
452
stack = &initialStack;
454
dmxConfigPrintVirtual(p);
455
if (pos) dmxConfigNewline();