~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/dmx/config/dmxprint.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86$ */
 
2
/*
 
3
 * Copyright 2002 Red Hat Inc., Durham, North Carolina.
 
4
 *
 
5
 * All Rights Reserved.
 
6
 *
 
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:
 
14
 *
 
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.
 
18
 *
 
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
 
26
 * SOFTWARE.
 
27
 */
 
28
 
 
29
/*
 
30
 * Authors:
 
31
 *   Rickard E. (Rik) Faith <faith@redhat.com>
 
32
 *
 
33
 */
 
34
 
 
35
/** \file
 
36
 *
 
37
 * This file provides support routines and helper functions to be used
 
38
 * to pretty-print DMX configurations.
 
39
 * 
 
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. */
 
43
 
 
44
#ifdef HAVE_DMX_CONFIG_H
 
45
#include <dmx-config.h>
 
46
#endif
 
47
 
 
48
#include "dmxconfig.h"
 
49
#include "dmxparse.h"
 
50
#include "dmxprint.h"
 
51
#include "parser.h"
 
52
#include <stdio.h>
 
53
#include <stdarg.h>
 
54
#include <ctype.h>
 
55
 
 
56
static FILE *str   = NULL;
 
57
static int  indent = 0;
 
58
static int  pos    = 0;
 
59
 
 
60
/** Stack of indentation information used for pretty-printing
 
61
 * configuration information. */
 
62
static struct stack {
 
63
    int          base;
 
64
    int          comment;
 
65
    int          step;
 
66
    struct stack *next;
 
67
} *stack, initialStack = { 0, 0, 4, NULL };
 
68
 
 
69
static void dmxConfigIndent(void)
 
70
{
 
71
    int i;
 
72
    if (indent < 0)  indent = 0;
 
73
    if (indent > 40) indent = 40;
 
74
    for (i = 0; i < indent; i++) fprintf(str, " ");
 
75
}
 
76
 
 
77
static void dmxConfigNewline(void)
 
78
{
 
79
    if (pos) fprintf(str, "\n");
 
80
    pos = 0;
 
81
}
 
82
 
 
83
static void dmxConfigPushState(int base, int comment, int step)
 
84
{
 
85
    struct stack *new = dmxConfigAlloc(sizeof(*new));
 
86
    new->base    = base;
 
87
    new->comment = comment;
 
88
    new->step    = step;
 
89
    new->next    = stack;
 
90
    stack        = new;
 
91
    indent       = base;
 
92
    dmxConfigNewline();
 
93
}
 
94
 
 
95
static void dmxConfigPushComment(void)
 
96
{
 
97
    if (stack) indent = stack->comment;
 
98
}
 
99
 
 
100
static void dmxConfigPushStep(void)
 
101
{
 
102
    if (stack) indent = stack->step;
 
103
}
 
104
 
 
105
static void dmxConfigPopState(void)
 
106
{
 
107
    struct stack *old = stack;
 
108
 
 
109
    if (!stack) return;
 
110
    indent = old->base;
 
111
    stack  = old->next;
 
112
    if (!stack) dmxConfigLog("Stack underflow\n");
 
113
    dmxConfigFree(old);
 
114
    dmxConfigNewline();
 
115
}
 
116
 
 
117
static void dmxConfigOutput(int addSpace, int doNewline, const char *comment,
 
118
                            const char *format, ...)
 
119
{
 
120
    va_list args;
 
121
 
 
122
    if (!pos) dmxConfigIndent();
 
123
    else if (addSpace) fprintf(str, " ");
 
124
 
 
125
    if (format) {
 
126
        va_start(args, format);
 
127
                                /* RATS: This hasn't been audited -- it
 
128
                                 * could probably result in a buffer
 
129
                                 * overflow. */
 
130
        pos += vfprintf(str, format, args); /* assumes no newlines! */
 
131
        va_end(args);
 
132
    }
 
133
 
 
134
    if (comment) {
 
135
        if (pos) fprintf(str, " ");
 
136
        pos += fprintf(str, "#%s", comment);
 
137
        dmxConfigNewline();
 
138
        dmxConfigPushComment();
 
139
    } else if (doNewline) dmxConfigNewline();
 
140
}
 
141
 
 
142
static void dmxConfigPrintComment(DMXConfigCommentPtr p)
 
143
{
 
144
    dmxConfigOutput(1, 1, p->comment, NULL);
 
145
}
 
146
 
 
147
static void dmxConfigPrintTokenFlag(DMXConfigTokenPtr p, int flag)
 
148
{
 
149
    if (!p) return;
 
150
    switch (p->token) {
 
151
    case T_VIRTUAL:
 
152
        dmxConfigPushState(0, 4, 4);
 
153
        dmxConfigOutput(0, 0, p->comment, "virtual");
 
154
        break;
 
155
    case T_DISPLAY:
 
156
        dmxConfigPushState(4, 12, 16);
 
157
        dmxConfigOutput(0, 0, p->comment, "display");
 
158
        break;
 
159
    case T_WALL:
 
160
        dmxConfigPushState(4, 12, 16);
 
161
        dmxConfigOutput(0, 0, p->comment, "wall");
 
162
        break;
 
163
    case T_OPTION:
 
164
        dmxConfigPushState(4, 12, 16);
 
165
        dmxConfigOutput(0, 0, p->comment, "option");
 
166
        break;
 
167
    case T_PARAM:
 
168
        dmxConfigPushState(4, 8, 12);
 
169
        dmxConfigOutput(0, 0, p->comment, "param");
 
170
        break;
 
171
    case ';':
 
172
        dmxConfigOutput(0, 1, p->comment, ";");
 
173
        if (flag) dmxConfigPopState();
 
174
        break;
 
175
    case '{':
 
176
        dmxConfigOutput(1, 1, p->comment, "{");
 
177
        dmxConfigPushStep();
 
178
        break;
 
179
    case '}':
 
180
        if (flag) dmxConfigPopState();
 
181
        dmxConfigOutput(0, 1, p->comment, "}");
 
182
        break;
 
183
    case '/':
 
184
        dmxConfigOutput(1, 0, NULL, "/");
 
185
        break;
 
186
    default:
 
187
        dmxConfigLog("unknown token %d on line %d\n", p->token, p->line);
 
188
    }
 
189
}
 
190
 
 
191
static void dmxConfigPrintToken(DMXConfigTokenPtr p)
 
192
{
 
193
    dmxConfigPrintTokenFlag(p, 1);
 
194
}
 
195
 
 
196
static void dmxConfigPrintTokenNopop(DMXConfigTokenPtr p)
 
197
{
 
198
    dmxConfigPrintTokenFlag(p, 0);
 
199
}
 
200
 
 
201
static int dmxConfigPrintQuotedString(const char *s)
 
202
{
 
203
    const char *pt;
 
204
 
 
205
    if (!s || !s[0]) return 1;  /* Quote empty string */
 
206
    for (pt = s; *pt; ++pt) if (isspace(*pt)) return 1;
 
207
    return 0;
 
208
}
 
209
 
 
210
static void dmxConfigPrintString(DMXConfigStringPtr p, int quote)
 
211
{
 
212
    DMXConfigStringPtr pt;
 
213
    
 
214
    if (!p) return;
 
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 : "");
 
219
            } else
 
220
            dmxConfigOutput(1, 0, pt->comment, "%s",
 
221
                            pt->string ? pt->string : "");
 
222
    }
 
223
}
 
224
 
 
225
static int dmxConfigPrintPair(DMXConfigPairPtr p, int addSpace)
 
226
{
 
227
    const char *format = NULL;
 
228
    
 
229
    if (!p) return 0;
 
230
    switch (p->token) {
 
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;
 
234
    }
 
235
    if (p->token == T_OFFSET) {
 
236
        if (!p->comment && !p->x && !p->y && p->xsign >= 0 && p->ysign >= 0)
 
237
            return 0;
 
238
        dmxConfigOutput(addSpace, 0, p->comment, format,
 
239
                        p->xsign < 0 ? '-' : '+', p->x,
 
240
                        p->ysign < 0 ? '-' : '+', p->y);
 
241
    } else {
 
242
        if (!p->comment && !p->x && !p->y) return 0;
 
243
        dmxConfigOutput(addSpace, 0, p->comment, format, p->x, p->y);
 
244
    }
 
245
    return 1;
 
246
}
 
247
 
 
248
static void dmxConfigPrintDisplay(DMXConfigDisplayPtr p)
 
249
{
 
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 };
 
259
    int             output;
 
260
 
 
261
    if (p->dname) p->dname->string = p->name;
 
262
    else          dummyName.string = p->name;
 
263
    
 
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;
 
267
    } else {
 
268
        dummySDim.x             = p->scrnWidth;
 
269
        dummySDim.y             = p->scrnHeight;
 
270
    }
 
271
 
 
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;
 
275
    } else {
 
276
        dummySOffset.x          = p->scrnX;
 
277
        dummySOffset.y          = p->scrnY;
 
278
    }
 
279
    
 
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;
 
283
    } else {
 
284
        dummyRDim.x             = p->rootWidth;
 
285
        dummyRDim.y             = p->rootHeight;
 
286
    }
 
287
 
 
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;
 
291
    } else {
 
292
        dummyROffset.x          = p->rootX;
 
293
        dummyROffset.y          = p->rootY;
 
294
    }
 
295
 
 
296
    if (p->origin) {
 
297
        p->origin->x     = p->rootXOrigin, p->origin->y     = p->rootYOrigin;
 
298
        p->origin->xsign = p->rootXSign,   p->origin->ysign = p->rootYSign;
 
299
    } else {
 
300
        dummyOrigin.x     = p->rootXOrigin, dummyOrigin.y     = p->rootYOrigin;
 
301
        dummyOrigin.xsign = p->rootXSign,   dummyOrigin.ysign = p->rootYSign;
 
302
    }
 
303
    
 
304
    dmxConfigPrintToken(p->start ? p->start : &dummyStart);
 
305
    dmxConfigPrintString(p->dname ? p->dname : &dummyName, 1);
 
306
 
 
307
    if (p->dim && p->dim->scrn && p->dim->scrn->dim)
 
308
        output = dmxConfigPrintPair(p->dim->scrn->dim, 1);
 
309
    else
 
310
        output = dmxConfigPrintPair(&dummySDim, 1);
 
311
    if (p->dim && p->dim->scrn && p->dim->scrn->offset)
 
312
        dmxConfigPrintPair(p->dim->scrn->offset, !output);
 
313
    else
 
314
        dmxConfigPrintPair(&dummySOffset, !output);
 
315
 
 
316
    if (p->scrnWidth != p->rootWidth
 
317
        || p->scrnHeight != p->rootHeight
 
318
        || p->rootX
 
319
        || p->rootY) {
 
320
        dmxConfigPrintToken(&dummySep);
 
321
        if (p->dim && p->dim->root && p->dim->root->dim)
 
322
            output = dmxConfigPrintPair(p->dim->root->dim, 1);
 
323
        else
 
324
            output = dmxConfigPrintPair(&dummyRDim, 1);
 
325
        if (p->dim && p->dim->root && p->dim->root->offset)
 
326
            dmxConfigPrintPair(p->dim->root->offset, !output);
 
327
        else
 
328
            dmxConfigPrintPair(&dummyROffset, !output);
 
329
    }
 
330
 
 
331
    dmxConfigPrintPair(p->origin ? p->origin : &dummyOrigin, 1);
 
332
    dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
 
333
}
 
334
 
 
335
static void dmxConfigPrintWall(DMXConfigWallPtr p)
 
336
{
 
337
    dmxConfigPrintToken(p->start);
 
338
    dmxConfigPrintPair(p->wallDim, 1);
 
339
    dmxConfigPrintPair(p->displayDim, 1);
 
340
    dmxConfigPrintString(p->nameList, 1);
 
341
    dmxConfigPrintToken(p->end);
 
342
}
 
343
 
 
344
static void dmxConfigPrintOption(DMXConfigOptionPtr p)
 
345
{
 
346
    DMXConfigToken  dummyStart  = { T_OPTION, 0, NULL };
 
347
    DMXConfigString dummyOption = { T_STRING, 0, NULL, NULL, NULL };
 
348
    DMXConfigToken  dummyEnd    = { ';', 0, NULL };
 
349
 
 
350
    dummyOption.string = p->string;
 
351
 
 
352
    dmxConfigPrintToken(p->start ? p->start : &dummyStart);
 
353
    dmxConfigPrintString(&dummyOption, 0);
 
354
    dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
 
355
}
 
356
 
 
357
static void dmxConfigPrintParam(DMXConfigParamPtr p)
 
358
{
 
359
    if (!p) return;
 
360
    if (p->start) {
 
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);
 
370
        } else
 
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);
 
376
    } else
 
377
        dmxConfigLog("dmxConfigPrintParam: cannot handle format (b)\n");
 
378
}
 
379
 
 
380
static void dmxConfigPrintSub(DMXConfigSubPtr p)
 
381
{
 
382
    DMXConfigSubPtr pt;
 
383
 
 
384
    if (!p) return;
 
385
    for (pt = p; pt; pt = pt->next) {
 
386
        switch (pt->type) {
 
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;
 
392
        default:
 
393
            dmxConfigLog("dmxConfigPrintSub:"
 
394
                         " cannot handle type %d in subentry\n", pt->type);
 
395
        }
 
396
    }
 
397
}
 
398
 
 
399
static void dmxConfigPrintVirtual(DMXConfigVirtualPtr p)
 
400
{
 
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 };
 
406
 
 
407
    if (p->vname) p->vname->string = p->name;
 
408
    else          dummyName.string = p->name;
 
409
 
 
410
    if (p->dim) p->dim->x  = p->width, p->dim->y  = p->height;
 
411
    else        dummyDim.x = p->width, dummyDim.y = p->height;
 
412
    
 
413
 
 
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);
 
420
}
 
421
 
 
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)
 
425
{
 
426
    DMXConfigEntryPtr pt;
 
427
 
 
428
    if (!stream) str = stdout;
 
429
    else         str = stream;
 
430
    
 
431
    stack = &initialStack;
 
432
    
 
433
    for (pt = entry; pt; pt = pt->next) {
 
434
        switch (pt->type) {
 
435
        case dmxConfigComment: dmxConfigPrintComment(pt->comment); break;
 
436
        case dmxConfigVirtual: dmxConfigPrintVirtual(pt->virtual); break;
 
437
        default:
 
438
            dmxConfigLog("dmxConfigPrint: cannot handle type %d in entry\n",
 
439
                         pt->type);
 
440
        }
 
441
    }
 
442
    if (pos) dmxConfigNewline();
 
443
}
 
444
 
 
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)
 
448
{
 
449
    if (!stream) str = stdout;
 
450
    else         str = stream;
 
451
 
 
452
    stack = &initialStack;
 
453
    
 
454
    dmxConfigPrintVirtual(p);
 
455
    if (pos) dmxConfigNewline();
 
456
}