Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/algol60/src/tools/disp/pretty.c – Rev 7

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "types.h"
63
#include "ascii.h"
64
#include "file.h"
7 7u83 65
#include "pretty.h"
2 7u83 66
#include "tree.h"
67
 
68
 
69
/*
70
    FORWARD DECLARATIONS
71
*/
72
 
7 7u83 73
static void display(int);
74
static void expression(word *, int, int, int, int, int);
2 7u83 75
 
76
 
77
/*
78
    FLAGS SET BY EXTERNAL OPTIONS
79
 
80
    Various flags may be given on the command line with affect the form
81
    of the output.  These are documented elsewhere.
82
*/
83
 
7 7u83 84
int helpflag = 1;
85
int dflag = 1;
86
int progress = 0;
87
int quickflag = 0;
2 7u83 88
 
89
 
90
/*
91
    VARIABLES USED IN PRINTING ROUTINE
92
 
93
    The variable maxcol is used to specify the maximum number of columns
94
    into which the output should be fitted.  maxtab gives the current
95
    indentation.  dot_spacing is used to indicate the distance between
96
    the vertical alignment lines when helpflag is true.
97
*/
98
 
7 7u83 99
int maxcol = 80;
100
static int maxtab;
101
static int dot_spacing;
2 7u83 102
 
103
 
104
/*
105
    CHOICE TABLE
106
 
107
    This table is used to decide the maximum suitable indentation.  For
108
    example the entry { a, b, c } means, try printing with an indentation
109
    of a.  If this fits into the required number of columns, try with
110
    the (larger) indentation c.  Otherwise try with the (smaller)
111
    indentation b.
112
*/
113
 
114
#define M 100
115
 
7 7u83 116
static int dec[7][3] = {
2 7u83 117
    { 4, 2, 8 },
118
    { 2, 1, 3 },
119
    { 8, 6, M },
120
    { 1, 0, 1 },
121
    { 3, 2, 3 },
122
    { 6, 4, 6 },
123
    { M, 8, M }
7 7u83 124
};
2 7u83 125
 
126
 
127
/*
128
    PRINT THE TDF TREE
129
 
130
    This routine has overall control of the printing of the tree.  It
131
    determines the most suitable indentation by means of trial runs,
132
    and then prints the tree with that indentation.
133
*/
134
 
7 7u83 135
void
136
pretty_tree(void)
2 7u83 137
{
7 7u83 138
    int i, j;
139
    int maximum0;
2 7u83 140
 
7 7u83 141
    initialize_tree();
2 7u83 142
 
143
    /* Do some trial runs to try to fit into right number of columns... */
7 7u83 144
    printflag = 0;
2 7u83 145
 
146
    /* With a maximum identation of 0... */
7 7u83 147
    maxtab = 0;
148
    display(0);
149
    maximum0 = maximum;
2 7u83 150
 
151
    /* Try some larger/smaller values */
7 7u83 152
    if (!quickflag && maximum < maxcol) {
153
	maxtab = 4;
154
	for (i = 0; i < 3; i++) {
155
	    display(1);
156
	    j = -1;
157
	    while (dec[++j][0]!= maxtab);
158
	    maxtab = dec[j][maximum < maxcol ? 2 : 1];
2 7u83 159
	}
160
    }
161
 
162
    /* Work out dot spacing */
7 7u83 163
    dot_spacing = 8;
164
    if (maxtab != 100) dot_spacing = 2 *(maxtab + 1);
165
    if (maxtab == 0) {
166
	if (maximum0 > maxcol)maxcol = maximum0;
167
	dot_spacing = 4;
2 7u83 168
    }
7 7u83 169
    init_spaces(dot_spacing);
2 7u83 170
 
171
    /* Actually do the printing */
7 7u83 172
    printflag = 1;
173
    display(0);
174
    if (progress) {
175
	IGNORE fprintf(stderr, "Printed in %d columns.\n", maximum);
2 7u83 176
    }
7 7u83 177
    return;
2 7u83 178
}
179
 
180
 
181
/*
182
    TRY TO PRETTY-PRINT THE TDF TREE
183
 
184
    This routine actually outputs the tree.  If test is true, then this
185
    is only a trial run, and may be aborted if the output exceeds the
186
    required number of columns.
187
*/
188
 
7 7u83 189
static void
190
display(int test)
2 7u83 191
{
7 7u83 192
    word *ptr;
193
    maximum = 0;
194
    for (ptr = word1.bro; ptr; ptr = ptr->bro) {
195
	column = 0;
196
	expression(ptr, 0, 0, 0, 1, 0);
197
	if (test && (maximum > maxcol)) return;
2 7u83 198
    }
7 7u83 199
    return;
2 7u83 200
}
201
 
202
 
203
/*
204
    OUTPUT A CHARACTER
205
 
206
    This routine outputs a single character into the output file.
207
*/
208
 
7 7u83 209
#define put_out(c)						\
2 7u83 210
    {								\
7 7u83 211
	if (c) {						\
212
	    if (printflag)IGNORE fputc((c), pp_file); \
213
	    column++; \
214
	    lastc = (c);					\
2 7u83 215
	}							\
216
    }
217
 
218
 
219
/*
220
    OUTPUT A NEWLINE
221
 
222
    This routine outputs a newline character into the output file.
223
    It also causes column to be compared against maximum.
224
*/
225
 
226
#define new_line()						\
227
    {								\
7 7u83 228
	if (column > maximum)maximum = column; \
229
	if (printflag)IGNORE fputc(NEWLINE, pp_file); \
230
	column = 0; \
231
	lastc = NEWLINE; \
2 7u83 232
    }
233
 
234
 
235
/*
236
    OUTPUT A TDF EXPRESSION
237
 
238
    This routine is called recursively to print the tree.  ptr gives
239
    the current position within the tree.  col gives the column
240
    where printing should start.  flag is true to indicate that a
241
    newline should be output at the end.  pending gives the number
242
    of trailing close brackets which are pending.  first gives a
243
    character which needs to be output before the current
244
    expression, and last gives one which should be output after it.
245
*/
246
 
7 7u83 247
static void
248
expression(word *ptr, int col, int first, int last, int flag, int pending)
2 7u83 249
{
7 7u83 250
    word *p;
251
    char bar = '|';
252
    char open = '(';
253
    char close = ')';
2 7u83 254
    char comma = ',';
7 7u83 255
    int more, pends;
256
    char sort, opener, sep;
257
    int len, visible, horiz;
258
    int mflag, new_col, temp_col, temp_max;
2 7u83 259
 
260
    /* print initial spaces */
7 7u83 261
    if (column == 0)spaces(col);
2 7u83 262
 
263
    /* output first character */
7 7u83 264
    put_out(first);
2 7u83 265
 
266
    /* copy out initial text */
7 7u83 267
    col = column;
268
    len = (int)ptr->length;
269
    sort = ptr->type;
270
    if (printflag)IGNORE fputs(ptr->text, pp_file);
271
    column += len;
2 7u83 272
 
273
    /* if we have parameters, we need to decode them */
7 7u83 274
    if (sort != SIMPLE) {
2 7u83 275
 
276
	/* are the brackets visible or not? */
7 7u83 277
	visible = ((sort == HORIZ_NONE || sort == VERT_NONE)? 0 : 1);
278
	if (!visible) {
279
	    open = close = bar = 0;
280
	    comma = ' ';
2 7u83 281
	}
282
 
283
	/* are we printing horizontally or vertically? */
7 7u83 284
	horiz = (sort == HORIZ_BRACKETS || sort == HORIZ_NONE);
2 7u83 285
 
286
	/* does the maximum tab come into effect? */
7 7u83 287
	mflag = (!horiz && (len > maxtab));
288
	new_col = col + (mflag ? maxtab : len) + 1;
2 7u83 289
 
7 7u83 290
	if (sort == VERT_BRACKETS) {
2 7u83 291
	    /* try to print things with only one parameter horizontally */
7 7u83 292
	    p = ptr->son;
293
	    if (p == null) {
294
		horiz = 1;
2 7u83 295
	    } else {
7 7u83 296
		if (p->son == null && p->bro == null)horiz = 1;
2 7u83 297
	    }
298
	}
299
 
300
	/* have a test run, if printing horizontally */
7 7u83 301
	if (horiz && printflag) {
302
	    horiz = 1;
2 7u83 303
	    /* save old values */
7 7u83 304
	    temp_col = column;
305
	    temp_max = maximum;
306
	    printflag = 0;
307
	    maximum = column;
2 7u83 308
	    /* open bracket */
7 7u83 309
	    put_out(open);
310
	    sep = comma;
311
	    pends = 0;
2 7u83 312
	    /* print parameters */
7 7u83 313
	    for (p = ptr->son; p; p = p->bro) {
314
		if (p->bro == null) {
2 7u83 315
		    /* for last, take trailing brackets into account */
7 7u83 316
		    sep = close;
317
		    pends = pending + visible;
2 7u83 318
		}
319
		/* print this parameter */
7 7u83 320
		expression(p, column, 0, sep, 0, pends);
2 7u83 321
	    }
322
	    /* close bracket */
7 7u83 323
	    put_out(last);
2 7u83 324
	    /* if this doesn't fit in, try vertically */
7 7u83 325
	    if (maximum >= maxcol || column + pending >= maxcol) {
326
		horiz = 0;
327
		mflag = (len > maxtab);
328
		new_col = col + (mflag ? maxtab : len) + 1;
2 7u83 329
	    }
330
	    /* restore old values */
7 7u83 331
	    column = temp_col;
332
	    maximum = temp_max;
333
	    printflag = 1;
2 7u83 334
	}
335
 
7 7u83 336
	if (horiz && printflag) {
2 7u83 337
	    /* do horizontal printing of parameters */
338
	    /* open bracket */
7 7u83 339
	    put_out(open);
340
	    sep = comma;
341
	    pends = 0;
2 7u83 342
	    /* print parameters */
7 7u83 343
	    for (p = ptr->son; p; p = p->bro) {
2 7u83 344
		/* for last, take trailing brackets into account */
7 7u83 345
		if (p->bro == null) {
346
		    sep = close;
347
		    pends = pending + visible;
2 7u83 348
		}
349
		/* print this parameter */
7 7u83 350
		expression(p, column, 0, sep, 0, pends);
2 7u83 351
	    }
352
	} else {
353
	    /* do vertical printing of parameters */
7 7u83 354
	    put_out(open);
355
	    opener = bar;
356
	    if (mflag) {
357
		new_line();
358
		spaces(new_col - 1);
2 7u83 359
	    }
7 7u83 360
	    sep = comma;
361
	    more = 1;
362
	    pends = 0;
363
	    new_col = column;
364
	    if (!mflag) {
365
		new_col--;
366
		opener = 0;
2 7u83 367
	    }
368
	    /* print parameters */
7 7u83 369
	    for (p = ptr->son; p; p = p->bro) {
370
		if (p->bro == null) {
2 7u83 371
		    /* last requires special treatment */
7 7u83 372
		    sep = 0;
373
		    more = 0;
374
		    pends = pending + visible;
2 7u83 375
		}
376
		/* print this parameter */
7 7u83 377
		expression(p, new_col, opener, sep, more, pends);
378
		opener = bar;
2 7u83 379
	    }
7 7u83 380
	    if (visible)put_out(close);
2 7u83 381
	}
382
    }
383
 
384
    /* output last character */
7 7u83 385
    if (last != ',' || (lastc != '.' && lastc != ':'))put_out(last);
2 7u83 386
 
387
    /* and a newline if required */
7 7u83 388
    if (flag)new_line();
389
    return;
2 7u83 390
}