First import
[xorg_rtime.git] / xorg-server-1.4 / hw / dmx / config / dmxprint.c
blob599ebf5dff451d620e4afde5d2ef67ea02a9a9ed
1 /*
2 * Copyright 2002 Red Hat Inc., Durham, North Carolina.
4 * All Rights Reserved.
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
25 * SOFTWARE.
29 * Authors:
30 * Rickard E. (Rik) Faith <faith@redhat.com>
34 /** \file
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>
45 #endif
47 #include "dmxconfig.h"
48 #include "dmxparse.h"
49 #include "dmxprint.h"
50 #include "parser.h"
51 #include <stdio.h>
52 #include <stdarg.h>
53 #include <ctype.h>
55 static FILE *str = NULL;
56 static int indent = 0;
57 static int pos = 0;
59 /** Stack of indentation information used for pretty-printing
60 * configuration information. */
61 static struct stack {
62 int base;
63 int comment;
64 int step;
65 struct stack *next;
66 } *stack, initialStack = { 0, 0, 4, NULL };
68 static void dmxConfigIndent(void)
70 int i;
71 if (indent < 0) indent = 0;
72 if (indent > 40) indent = 40;
73 for (i = 0; i < indent; i++) fprintf(str, " ");
76 static void dmxConfigNewline(void)
78 if (pos) fprintf(str, "\n");
79 pos = 0;
82 static void dmxConfigPushState(int base, int comment, int step)
84 struct stack *new = dmxConfigAlloc(sizeof(*new));
85 new->base = base;
86 new->comment = comment;
87 new->step = step;
88 new->next = stack;
89 stack = new;
90 indent = base;
91 dmxConfigNewline();
94 static void dmxConfigPushComment(void)
96 if (stack) indent = stack->comment;
99 static void dmxConfigPushStep(void)
101 if (stack) indent = stack->step;
104 static void dmxConfigPopState(void)
106 struct stack *old = stack;
108 if (!stack) return;
109 indent = old->base;
110 stack = old->next;
111 if (!stack) dmxConfigLog("Stack underflow\n");
112 dmxConfigFree(old);
113 dmxConfigNewline();
116 static void dmxConfigOutput(int addSpace, int doNewline, const char *comment,
117 const char *format, ...)
119 va_list args;
121 if (!pos) dmxConfigIndent();
122 else if (addSpace) fprintf(str, " ");
124 if (format) {
125 va_start(args, format);
126 /* RATS: This hasn't been audited -- it
127 * could probably result in a buffer
128 * overflow. */
129 pos += vfprintf(str, format, args); /* assumes no newlines! */
130 va_end(args);
133 if (comment) {
134 if (pos) fprintf(str, " ");
135 pos += fprintf(str, "#%s", comment);
136 dmxConfigNewline();
137 dmxConfigPushComment();
138 } else if (doNewline) dmxConfigNewline();
141 static void dmxConfigPrintComment(DMXConfigCommentPtr p)
143 dmxConfigOutput(1, 1, p->comment, NULL);
146 static void dmxConfigPrintTokenFlag(DMXConfigTokenPtr p, int flag)
148 if (!p) return;
149 switch (p->token) {
150 case T_VIRTUAL:
151 dmxConfigPushState(0, 4, 4);
152 dmxConfigOutput(0, 0, p->comment, "virtual");
153 break;
154 case T_DISPLAY:
155 dmxConfigPushState(4, 12, 16);
156 dmxConfigOutput(0, 0, p->comment, "display");
157 break;
158 case T_WALL:
159 dmxConfigPushState(4, 12, 16);
160 dmxConfigOutput(0, 0, p->comment, "wall");
161 break;
162 case T_OPTION:
163 dmxConfigPushState(4, 12, 16);
164 dmxConfigOutput(0, 0, p->comment, "option");
165 break;
166 case T_PARAM:
167 dmxConfigPushState(4, 8, 12);
168 dmxConfigOutput(0, 0, p->comment, "param");
169 break;
170 case ';':
171 dmxConfigOutput(0, 1, p->comment, ";");
172 if (flag) dmxConfigPopState();
173 break;
174 case '{':
175 dmxConfigOutput(1, 1, p->comment, "{");
176 dmxConfigPushStep();
177 break;
178 case '}':
179 if (flag) dmxConfigPopState();
180 dmxConfigOutput(0, 1, p->comment, "}");
181 break;
182 case '/':
183 dmxConfigOutput(1, 0, NULL, "/");
184 break;
185 default:
186 dmxConfigLog("unknown token %d on line %d\n", p->token, p->line);
190 static void dmxConfigPrintToken(DMXConfigTokenPtr p)
192 dmxConfigPrintTokenFlag(p, 1);
195 static void dmxConfigPrintTokenNopop(DMXConfigTokenPtr p)
197 dmxConfigPrintTokenFlag(p, 0);
200 static int dmxConfigPrintQuotedString(const char *s)
202 const char *pt;
204 if (!s || !s[0]) return 1; /* Quote empty string */
205 for (pt = s; *pt; ++pt) if (isspace(*pt)) return 1;
206 return 0;
209 static void dmxConfigPrintString(DMXConfigStringPtr p, int quote)
211 DMXConfigStringPtr pt;
213 if (!p) return;
214 for (pt = p; pt; pt = pt->next) {
215 if (quote && dmxConfigPrintQuotedString(pt->string)) {
216 dmxConfigOutput(1, 0, pt->comment, "\"%s\"",
217 pt->string ? pt->string : "");
218 } else
219 dmxConfigOutput(1, 0, pt->comment, "%s",
220 pt->string ? pt->string : "");
224 static int dmxConfigPrintPair(DMXConfigPairPtr p, int addSpace)
226 const char *format = NULL;
228 if (!p) return 0;
229 switch (p->token) {
230 case T_ORIGIN: format = "@%dx%d"; break;
231 case T_DIMENSION: format = "%dx%d"; break;
232 case T_OFFSET: format = "%c%d%c%d"; break;
234 if (p->token == T_OFFSET) {
235 if (!p->comment && !p->x && !p->y && p->xsign >= 0 && p->ysign >= 0)
236 return 0;
237 dmxConfigOutput(addSpace, 0, p->comment, format,
238 p->xsign < 0 ? '-' : '+', p->x,
239 p->ysign < 0 ? '-' : '+', p->y);
240 } else {
241 if (!p->comment && !p->x && !p->y) return 0;
242 dmxConfigOutput(addSpace, 0, p->comment, format, p->x, p->y);
244 return 1;
247 static void dmxConfigPrintDisplay(DMXConfigDisplayPtr p)
249 DMXConfigToken dummyStart = { T_DISPLAY, 0, NULL };
250 DMXConfigToken dummyEnd = { ';', 0, NULL };
251 DMXConfigToken dummySep = { '/', 0, NULL };
252 DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL };
253 DMXConfigPair dummySDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 };
254 DMXConfigPair dummySOffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 };
255 DMXConfigPair dummyRDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 };
256 DMXConfigPair dummyROffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 };
257 DMXConfigPair dummyOrigin = { T_ORIGIN, 0, NULL, 0, 0, 0, 0 };
258 int output;
260 if (p->dname) p->dname->string = p->name;
261 else dummyName.string = p->name;
263 if (p->dim && p->dim->scrn && p->dim->scrn->dim) {
264 p->dim->scrn->dim->x = p->scrnWidth;
265 p->dim->scrn->dim->y = p->scrnHeight;
266 } else {
267 dummySDim.x = p->scrnWidth;
268 dummySDim.y = p->scrnHeight;
271 if (p->dim && p->dim->scrn && p->dim->scrn->offset) {
272 p->dim->scrn->offset->x = p->scrnX;
273 p->dim->scrn->offset->y = p->scrnY;
274 } else {
275 dummySOffset.x = p->scrnX;
276 dummySOffset.y = p->scrnY;
279 if (p->dim && p->dim->root && p->dim->root->dim) {
280 p->dim->root->dim->x = p->rootWidth;
281 p->dim->root->dim->y = p->rootHeight;
282 } else {
283 dummyRDim.x = p->rootWidth;
284 dummyRDim.y = p->rootHeight;
287 if (p->dim && p->dim->root && p->dim->root->offset) {
288 p->dim->root->offset->x = p->rootX;
289 p->dim->root->offset->y = p->rootY;
290 } else {
291 dummyROffset.x = p->rootX;
292 dummyROffset.y = p->rootY;
295 if (p->origin) {
296 p->origin->x = p->rootXOrigin, p->origin->y = p->rootYOrigin;
297 p->origin->xsign = p->rootXSign, p->origin->ysign = p->rootYSign;
298 } else {
299 dummyOrigin.x = p->rootXOrigin, dummyOrigin.y = p->rootYOrigin;
300 dummyOrigin.xsign = p->rootXSign, dummyOrigin.ysign = p->rootYSign;
303 dmxConfigPrintToken(p->start ? p->start : &dummyStart);
304 dmxConfigPrintString(p->dname ? p->dname : &dummyName, 1);
306 if (p->dim && p->dim->scrn && p->dim->scrn->dim)
307 output = dmxConfigPrintPair(p->dim->scrn->dim, 1);
308 else
309 output = dmxConfigPrintPair(&dummySDim, 1);
310 if (p->dim && p->dim->scrn && p->dim->scrn->offset)
311 dmxConfigPrintPair(p->dim->scrn->offset, !output);
312 else
313 dmxConfigPrintPair(&dummySOffset, !output);
315 if (p->scrnWidth != p->rootWidth
316 || p->scrnHeight != p->rootHeight
317 || p->rootX
318 || p->rootY) {
319 dmxConfigPrintToken(&dummySep);
320 if (p->dim && p->dim->root && p->dim->root->dim)
321 output = dmxConfigPrintPair(p->dim->root->dim, 1);
322 else
323 output = dmxConfigPrintPair(&dummyRDim, 1);
324 if (p->dim && p->dim->root && p->dim->root->offset)
325 dmxConfigPrintPair(p->dim->root->offset, !output);
326 else
327 dmxConfigPrintPair(&dummyROffset, !output);
330 dmxConfigPrintPair(p->origin ? p->origin : &dummyOrigin, 1);
331 dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
334 static void dmxConfigPrintWall(DMXConfigWallPtr p)
336 dmxConfigPrintToken(p->start);
337 dmxConfigPrintPair(p->wallDim, 1);
338 dmxConfigPrintPair(p->displayDim, 1);
339 dmxConfigPrintString(p->nameList, 1);
340 dmxConfigPrintToken(p->end);
343 static void dmxConfigPrintOption(DMXConfigOptionPtr p)
345 DMXConfigToken dummyStart = { T_OPTION, 0, NULL };
346 DMXConfigString dummyOption = { T_STRING, 0, NULL, NULL, NULL };
347 DMXConfigToken dummyEnd = { ';', 0, NULL };
349 dummyOption.string = p->string;
351 dmxConfigPrintToken(p->start ? p->start : &dummyStart);
352 dmxConfigPrintString(&dummyOption, 0);
353 dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
356 static void dmxConfigPrintParam(DMXConfigParamPtr p)
358 if (!p) return;
359 if (p->start) {
360 if (p->open && p->close) {
361 dmxConfigPrintToken(p->start);
362 dmxConfigPrintToken(p->open);
363 dmxConfigPrintParam(p->next);
364 dmxConfigPrintToken(p->close);
365 } else if (p->end && p->param) {
366 dmxConfigPrintToken(p->start);
367 dmxConfigPrintString(p->param, 1);
368 dmxConfigPrintToken(p->end);
369 } else
370 dmxConfigLog("dmxConfigPrintParam: cannot handle format (a)\n");
371 } else if (p->end && p->param) {
372 dmxConfigPrintString(p->param, 1);
373 dmxConfigPrintTokenNopop(p->end);
374 dmxConfigPrintParam(p->next);
375 } else
376 dmxConfigLog("dmxConfigPrintParam: cannot handle format (b)\n");
379 static void dmxConfigPrintSub(DMXConfigSubPtr p)
381 DMXConfigSubPtr pt;
383 if (!p) return;
384 for (pt = p; pt; pt = pt->next) {
385 switch (pt->type) {
386 case dmxConfigComment: dmxConfigPrintComment(pt->comment); break;
387 case dmxConfigDisplay: dmxConfigPrintDisplay(pt->display); break;
388 case dmxConfigWall: dmxConfigPrintWall(pt->wall); break;
389 case dmxConfigOption: dmxConfigPrintOption(pt->option); break;
390 case dmxConfigParam: dmxConfigPrintParam(pt->param); break;
391 default:
392 dmxConfigLog("dmxConfigPrintSub:"
393 " cannot handle type %d in subentry\n", pt->type);
398 static void dmxConfigPrintVirtual(DMXConfigVirtualPtr p)
400 DMXConfigToken dummyStart = { T_VIRTUAL, 0, NULL };
401 DMXConfigToken dummyOpen = { '{', 0, NULL };
402 DMXConfigToken dummyClose = { '}', 0, NULL };
403 DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL };
404 DMXConfigPair dummyDim = { T_DIMENSION, 0, NULL, 0, 0 };
406 if (p->vname) p->vname->string = p->name;
407 else dummyName.string = p->name;
409 if (p->dim) p->dim->x = p->width, p->dim->y = p->height;
410 else dummyDim.x = p->width, dummyDim.y = p->height;
413 dmxConfigPrintToken(p->start ? p->start : &dummyStart);
414 dmxConfigPrintString(p->vname ? p->vname : &dummyName, 1);
415 dmxConfigPrintPair(p->dim ? p->dim : &dummyDim, 1);
416 dmxConfigPrintToken(p->open ? p->open : &dummyOpen);
417 dmxConfigPrintSub(p->subentry);
418 dmxConfigPrintToken(p->close ? p->close : &dummyClose);
421 /** The configuration information in \a entry will be pretty-printed to
422 * the \a stream. If \a stream is NULL, then stdout will be used. */
423 void dmxConfigPrint(FILE *stream, DMXConfigEntryPtr entry)
425 DMXConfigEntryPtr pt;
427 if (!stream) str = stdout;
428 else str = stream;
430 stack = &initialStack;
432 for (pt = entry; pt; pt = pt->next) {
433 switch (pt->type) {
434 case dmxConfigComment: dmxConfigPrintComment(pt->comment); break;
435 case dmxConfigVirtual: dmxConfigPrintVirtual(pt->virtual); break;
436 default:
437 dmxConfigLog("dmxConfigPrint: cannot handle type %d in entry\n",
438 pt->type);
441 if (pos) dmxConfigNewline();
444 /** The configuration information in \a p will be pretty-printed to the
445 * \a stream. If \a stream is NULL, then stdout will be used. */
446 void dmxConfigVirtualPrint(FILE *stream, DMXConfigVirtualPtr p)
448 if (!stream) str = stdout;
449 else str = stream;
451 stack = &initialStack;
453 dmxConfigPrintVirtual(p);
454 if (pos) dmxConfigNewline();