Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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