Bug Summary

File:src/linear.c
Warning:line 201, column 2
Value stored to 'cc' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name linear.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/kfp/aldor/aldor/aldor/src -fcoverage-compilation-dir=/home/kfp/aldor/aldor/aldor/src -resource-dir /usr/local/lib/clang/18 -D PACKAGE_NAME="aldor" -D PACKAGE_TARNAME="aldor" -D PACKAGE_VERSION="1.4.0" -D PACKAGE_STRING="aldor 1.4.0" -D PACKAGE_BUGREPORT="aldor@xinutec.org" -D PACKAGE_URL="" -D PACKAGE="aldor" -D VERSION="1.4.0" -D YYTEXT_POINTER=1 -D HAVE_STDIO_H=1 -D HAVE_STDLIB_H=1 -D HAVE_STRING_H=1 -D HAVE_INTTYPES_H=1 -D HAVE_STDINT_H=1 -D HAVE_STRINGS_H=1 -D HAVE_SYS_STAT_H=1 -D HAVE_SYS_TYPES_H=1 -D HAVE_UNISTD_H=1 -D STDC_HEADERS=1 -D HAVE_LIBREADLINE=1 -D HAVE_READLINE_READLINE_H=1 -D HAVE_READLINE_HISTORY=1 -D HAVE_READLINE_HISTORY_H=1 -D USE_GLOOP_SHELL=1 -D GENERATOR_COROUTINES=0 -D HAVE_DLFCN_H=1 -D LT_OBJDIR=".libs/" -I . -D VCSVERSION="2c53e759f1e00e345f8b172e7139debda72fda13" -internal-isystem /usr/local/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-empty-body -Wno-enum-compare -Wno-missing-field-initializers -Wno-unused -Wno-unused-parameter -Wno-error=format -Wno-error=type-limits -Wno-error=strict-aliasing -Wno-sign-compare -Wno-error=shift-negative-value -Wno-error=clobbered -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2026-01-15-223856-845667-1 -x c linear.c
1/*****************************************************************************
2 *
3 * linear.c: Bracketing of piles.
4 *
5 * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org).
6 *
7 ****************************************************************************/
8
9/*
10 * Convert newline and indentation information into bracketing.
11 * The NewLine tokens are removed and SetTab, BackSet and BackTabs are added.
12 *
13 * The original list of tokens is modified.
14 *
15 * Note that most of the function header comments in this file were added
16 * post-facto and may be incorrect.
17 */
18
19#include "debug.h"
20#include "format.h"
21#include "linear.h"
22#include "store.h"
23#include "fint.h"
24#include "comsg.h"
25#include "util.h"
26
27Bool linDebug = false((int) 0);
28#define linDEBUGif (!linDebug) { } else afprintf DEBUG_IF(lin)if (!linDebug) { } else afprintf
29
30/****************************************************************************
31 *
32 * :: Forward decls
33 *
34 ****************************************************************************/
35
36localstatic Token linKeyword (Token, TokenTag);
37
38localstatic int linIndentation (TokenList);
39localstatic TokenList linUseNeededSep (TokenList);
40localstatic TokenList linXTokens (TokenList, TokenTag);
41localstatic TokenList linXBlankLines (TokenList);
42localstatic TokenList linCheckBalance (TokenList);
43localstatic TokenList linISepAfterDontPiles (TokenList);
44localstatic TokenList linXSep (TokenList);
45
46# define linXComments(tl)linXTokens((tl), TK_Comment) linXTokens((tl), TK_Comment)
47# define linXNewLines(tl)linXTokens((tl), KW_NewLine) linXTokens((tl), KW_NewLine)
48# define tokIsNonStarter(t)(((tokInfoTable[((t)->tag)-TK_START]).isFollower) || ((tokInfoTable
[((t)->tag)-TK_START]).isCloser))
(tokIsFollower(t)((tokInfoTable[((t)->tag)-TK_START]).isFollower) || tokIsCloser(t)((tokInfoTable[((t)->tag)-TK_START]).isCloser))
49
50# define MootIndentation(-1) (-1)
51
52# define DoPileStartKW_StartPile KW_StartPile /* #pile */
53# define DoPileEndKW_EndPile KW_EndPile /* #endpile */
54
55# define DontPileStartKW_OCurly KW_OCurly /* { */
56# define DontPileSepKW_Semicolon KW_Semicolon /* ; */
57# define DontPileEndKW_CCurly KW_CCurly /* } */
58
59
60/****************************************************************************
61 *
62 * :: LNodeTree data structure.
63 *
64 ****************************************************************************/
65
66/*
67 * The LNodeTree structure represents in tree form the information
68 * about whether to pile and, if so, line boundaries.
69 *
70 * The input
71 *
72 * {|
73 * a
74 * b
75 * c
76 * d { e
77 * h } i
78 * l {
79 * n
80 * o {| p
81 * q
82 * r |}
83 * t
84 * u }
85 * v
86 * w z
87 * |}
88 *
89 * becomes
90 *
91 * {| <a> <b> <c> <d { e h } i> <l { n o {| <p> <q> <r> |} t u }> <v> <w z> |}
92 *
93 * Note that since piling brackets {| and |} have been replaced by #pile
94 * and #endpile, the example above is overly complicated and could not be
95 * represented in Aldor. Also note that this structure assumes that most
96 * programs will be piled whereas now they are normally non-piled. The
97 * two forms do not normally appear together in the same source file.
98 */
99
100
101/* Note that LN_1Tok and LN_NTok could be merged */
102enum lnodeKind {
103 LN_1Tok, /* a */
104 LN_NTok, /* <w z> -- Has any NewLine token. */
105 LN_NNodes, /* <d { e h } i> -- Has any NewLine token. */
106 LN_DoPile /* {| <p> <q> <r> |} -- Has {| |} tokens. */
107};
108
109typedef Enum(lnodeKind)enum lnodeKind LNodeKind;
110typedef struct lnode *LNodeTree;
111
112union lnodeArg {
113 Token tok;
114 LNodeTree lnode;
115};
116
117struct lnode {
118 LNodeKind kind;
119 ULong has;
120 Length indent;
121 Length argc;
122 union lnodeArg argv[NARY10];
123};
124
125#define HAS_NonCom(1<<0) (1<<0)
126#define HAS_NonBlank(1<<1) (1<<1)
127
128#define linIsBlank(lnt)(!((lnt)->has & (1<<1))) (!((lnt)->has & HAS_NonBlank(1<<1)))
129#define linIsCom(lnt)(!((lnt)->has & (1<<0))) (!((lnt)->has & HAS_NonCom(1<<0)))
130
131
132DECLARE_LIST(LNodeTree)typedef struct LNodeTreeListCons { LNodeTree first; struct LNodeTreeListCons
*rest; } *LNodeTreeList; struct LNodeTree_listOpsStruct { LNodeTreeList
(*Cons) (LNodeTree, LNodeTreeList); LNodeTreeList (*Singleton
) (LNodeTree); LNodeTreeList (*List) (int n, ...); LNodeTreeList
(*Listv) (va_list argp); LNodeTreeList (*ListNull) (LNodeTree
, ...); Bool (*Equal) (LNodeTreeList, LNodeTreeList, Bool (*f
) (LNodeTree, LNodeTree)); LNodeTree (*Find) (LNodeTreeList, LNodeTree
, Bool(*eq)(LNodeTree,LNodeTree) , int *); LNodeTree (*Match)
(LNodeTreeList, void *, Bool(*match)(LNodeTree, void *), int
*); LNodeTreeList (*MatchAll) (LNodeTreeList, void *, Bool(*
match)(LNodeTree, void *)); LNodeTreeList (*FreeCons) (LNodeTreeList
); void (*Free) (LNodeTreeList); LNodeTreeList (*FreeTo) (LNodeTreeList
, LNodeTreeList); void (*FreeDeeply) (LNodeTreeList, void (*f
)(LNodeTree)); LNodeTreeList (*FreeDeeplyTo) (LNodeTreeList, LNodeTreeList
, void (*f) (LNodeTree) ); LNodeTreeList (*FreeIfSat) (LNodeTreeList
, void (*f)(LNodeTree), Bool (*s)(LNodeTree)); LNodeTree (*Elt
) (LNodeTreeList, Length); LNodeTreeList (*Drop) (LNodeTreeList
, Length); LNodeTreeList (*LastCons) (LNodeTreeList); Length (
*_Length) (LNodeTreeList); Bool (*IsLength) (LNodeTreeList, Length
); Bool (*IsShorter) (LNodeTreeList, Length); Bool (*IsLonger
) (LNodeTreeList, Length); LNodeTreeList (*Copy) (LNodeTreeList
); LNodeTreeList (*CopyTo) (LNodeTreeList, LNodeTreeList); LNodeTreeList
(*CopyDeeply) (LNodeTreeList, LNodeTree (*)(LNodeTree)); LNodeTreeList
(*CopyDeeplyTo) (LNodeTreeList, LNodeTreeList, LNodeTree (*)
(LNodeTree)); LNodeTreeList (*Map) (LNodeTree (*f)(LNodeTree)
, LNodeTreeList); LNodeTreeList (*NMap) (LNodeTree (*f)(LNodeTree
), LNodeTreeList); LNodeTreeList (*Reverse) (LNodeTreeList); LNodeTreeList
(*NReverse) (LNodeTreeList); LNodeTreeList (*Concat) (LNodeTreeList
, LNodeTreeList); LNodeTreeList (*NConcat) (LNodeTreeList, LNodeTreeList
); Bool (*Memq) (LNodeTreeList, LNodeTree); Bool (*Member) (LNodeTreeList
, LNodeTree, Bool(*eq)(LNodeTree,LNodeTree) ); Bool (*ContainsAllq
) (LNodeTreeList, LNodeTreeList); Bool (*ContainsAnyq) (LNodeTreeList
, LNodeTreeList); Bool (*ContainsAll) (LNodeTreeList, LNodeTreeList
, Bool (*eq)(LNodeTree, LNodeTree)); Bool (*ContainsAny) (LNodeTreeList
, LNodeTreeList, Bool (*eq)(LNodeTree, LNodeTree)); int (*Posq
) (LNodeTreeList, LNodeTree); int (*Position) (LNodeTreeList,
LNodeTree, Bool(*eq)(LNodeTree,LNodeTree) ); LNodeTreeList (
*NRemove) (LNodeTreeList, LNodeTree, Bool(*eq)(LNodeTree,LNodeTree
) ); void (*FillVector) (LNodeTree *, LNodeTreeList); int (*Print
) (FILE *, LNodeTreeList, int (*pr)(FILE *, LNodeTree) ); int
(*GPrint) (FILE *, LNodeTreeList, int (*pr)(FILE *, LNodeTree
), char *l,char *m,char *r); int (*Format) (OStream, CString,
LNodeTreeList); }; extern struct LNodeTree_listOpsStruct const
*LNodeTree_listPointer
;
133CREATE_LIST (LNodeTree)struct LNodeTree_listOpsStruct const *LNodeTree_listPointer =
(struct LNodeTree_listOpsStruct const *) &ptrlistOps
;
134
135localstatic LNodeTree lntNewEmpty (LNodeKind, Length);
136localstatic void lntFree (LNodeTree);
137localstatic void lntFreeNode (LNodeTree);
138
139localstatic ULong lntTokHas (TokenTag);
140localstatic Token lntFirstTok (LNodeTree);
141localstatic Token lntLastTok (LNodeTree);
142localstatic Token lntLastTokLessNL(LNodeTree);
143
144localstatic LNodeTree lntTok (Token);
145localstatic LNodeTree lntConcat (LNodeTree, LNodeTree);
146localstatic LNodeTree lntSeparate (LNodeTree, TokenTag, LNodeTree);
147localstatic LNodeTree lntWrap (TokenTag, LNodeTree, TokenTag);
148
149localstatic TokenList lntToTokenList (LNodeTree);
150localstatic TokenList lntToTokenList0 (LNodeTree, TokenList);
151localstatic TokenList lntConsNL (TokenList);
152localstatic LNodeTree lntFrTokenList (TokenList);
153
154localstatic LNodeTree lin2DRules (LNodeTree);
155
156
157
158localstatic LNodeTree
159lntNewEmpty(LNodeKind kind, Length argc)
160{
161 LNodeTree lnt;
162
163 lnt = (LNodeTree) stoAlloc(OB_Other0,
164 fullsizeof(struct lnode,(sizeof(struct lnode) + (argc) * sizeof(union lnodeArg) - 10 *
sizeof(union lnodeArg))
165 argc, union lnodeArg)(sizeof(struct lnode) + (argc) * sizeof(union lnodeArg) - 10 *
sizeof(union lnodeArg))
);
166 lnt->kind = kind;
167 lnt->has = 0;
168 lnt->indent = -1;
169 lnt->argc = argc;
170 return lnt;
171}
172
173localstatic void
174lntFree(LNodeTree lnt)
175{
176 if (!lnt) return;
177
178 if (lnt->kind != LN_1Tok && lnt->kind != LN_NTok) {
179 int i;
180 for (i = 0; i < lnt->argc; i++) lntFree(lnt->argv[i].lnode);
181 }
182 lntFreeNode(lnt);
183}
184
185localstatic void
186lntFreeNode(LNodeTree lnt)
187{
188 stoFree((Pointer) lnt);
189}
190
191
192localstatic int
193lntPrint(FILE *fout, LNodeTree lnt)
194{
195 int cc, i, n;
196 static int d = 0;
197
198 if (!lnt) return fprintf(fout, "|0|");
199
200 n = lnt->argc;
201 cc = 0;
Value stored to 'cc' is never read
202
203 d++;
204 switch (lnt->kind) {
205 case LN_1Tok:
206 cc = fprintf(fout, "(: ");
207 cc += tokPrint(fout, lnt->argv[0].tok);
208 cc += fprintf(fout, " :)");
209 break;
210 case LN_NTok:
211 cc = fprintf(fout, "<: ");
212 for (i = 0; i < n; i++) {
213 cc += fprintf(fout, " ");
214 cc += tokPrint(fout, lnt->argv[i].tok);
215 }
216 cc += fprintf(fout, " :>");
217 break;
218 case LN_NNodes:
219 cc = fprintf(fout, "< %d: ", d);
220 for (i = 0; i < n; i++)
221 cc += lntPrint(fout, lnt->argv[i].lnode);
222 cc += fprintf(fout, " :%d >", d);
223 break;
224 case LN_DoPile:
225 cc = fprintf(fout, "{ %d: ", d);
226 for (i = 0; i < n; i++)
227 cc += lntPrint(fout, lnt->argv[i].lnode);
228 cc += fprintf(fout, " :%d }", d);
229 break;
230 }
231 d--;
232 cc += fprintf(fout, "%lx", lnt->has);
233
234 return cc;
235}
236
237/*****************************************************************************
238 *
239 * :: LNodeTree utilities
240 *
241 ****************************************************************************/
242
243localstatic LNodeTree
244lntTok(Token tok)
245{
246 LNodeTree lnt = lntNewEmpty(LN_1Tok, 1);
247 lnt->argv[0].tok= tok;
248 lnt->has = lntTokHas(tokTag(tok)((TokenTag) (tok)->tag));
249 lnt->indent = sposChar(tok->pos);
250 return lnt;
251}
252
253localstatic LNodeTree
254lntConcat(LNodeTree lnt, LNodeTree rnt)
255{
256 LNodeTree tnt;
257
258 if (! lnt)
259 tnt = rnt;
260 else if (! rnt)
261 tnt = lnt;
262 else {
263 tnt = lntNewEmpty(LN_NNodes, 2);
264 tnt->indent = lnt->indent;
265 tnt->has = lnt->has | rnt->has;
266 tnt->argv[0].lnode = lnt;
267 tnt->argv[1].lnode = rnt;
268 }
269 return tnt;
270}
271
272localstatic LNodeTree
273lntSeparate(LNodeTree lnt, TokenTag sep, LNodeTree rnt)
274{
275 LNodeTree tnt;
276 Token tok = lntLastTok(lnt);
277
278 tnt = lntNewEmpty(LN_NNodes, 3);
279 tnt->indent = lnt->indent;
280 tnt->has = lnt->has | lntTokHas(sep) | rnt->has;
281 tnt->argv[0].lnode = lnt;
282 tnt->argv[1].lnode = lntTok(linKeyword(tok, sep));
283 tnt->argv[2].lnode = rnt;
284
285 return tnt;
286}
287
288localstatic LNodeTree
289lntWrap(TokenTag open, LNodeTree lnt, TokenTag close)
290{
291 LNodeTree tnt;
292
293 Token otok = lntFirstTok(lnt);
294 Token ctok = lntLastTok(lnt);
295
296 tnt = lntNewEmpty(LN_NNodes, 3);
297 tnt->indent = lnt->indent;
298 tnt->has = lntTokHas(open) | lnt->has | lntTokHas(close);
299 tnt->argv[0].lnode = lntTok(linKeyword(otok, open));
300 tnt->argv[1].lnode = lnt;
301 tnt->argv[2].lnode = lntTok(linKeyword(ctok, close));
302
303 return tnt;
304}
305
306localstatic ULong
307lntTokHas(TokenTag tt)
308{
309 switch (tt) {
310 case KW_NewLine: case TK_Comment: return 0;
311 case TK_PostDoc: case TK_PreDoc: return HAS_NonBlank(1<<1);
312 default: return HAS_NonBlank(1<<1) | HAS_NonCom(1<<0);
313 }
314}
315
316localstatic Token
317lntFirstTok(LNodeTree lnt)
318{
319 if (!lnt) return 0;
320
321 for (;;) {
322 if (lnt->argc == 0) return 0;
323
324 switch (lnt->kind) {
325 case LN_1Tok:
326 case LN_NTok:
327 return lnt->argv[0].tok;
328 case LN_NNodes:
329 case LN_DoPile:
330 lnt = lnt->argv[0].lnode;
331 }
332 }
333}
334
335localstatic Token
336lntLastTok(LNodeTree lnt)
337{
338 if (!lnt) return 0;
339
340 for (;;) {
341 int n = lnt->argc;
342
343 if (n == 0) return 0;
344
345 switch (lnt->kind) {
346 case LN_1Tok:
347 return lnt->argv[0].tok;
348 case LN_NTok:
349 return lnt->argv[n-1].tok;
350 case LN_NNodes:
351 case LN_DoPile:
352 lnt = lnt->argv[n-1].lnode;
353 }
354 }
355}
356
357localstatic Token
358lntLastTokLessNL(LNodeTree lnt)
359{
360 int n;
361 Token tok;
362
363 if (!lnt) return 0;
364
365 switch (lnt->kind) {
366 case LN_1Tok:
367 case LN_NTok:
368 for (n = lnt->argc; n > 0; n--) {
369 tok = lnt->argv[n-1].tok;
370 if (!tokIs(tok, KW_NewLine)((tok)->tag == (KW_NewLine))) return tok;
371 }
372 return 0;
373 case LN_NNodes:
374 case LN_DoPile:
375 for (n = lnt->argc; n > 0; n--) {
376 tok = lntLastTokLessNL(lnt->argv[n-1].lnode);
377 if (tok && !tokIs(tok, KW_NewLine)((tok)->tag == (KW_NewLine))) return tok;
378 }
379 return 0;
380 default:
381 NotReached(return 0){(void)bug("Not supposed to reach line %d in file: %s\n",381,
"linear.c");}
;
382 }
383}
384
385/*****************************************************************************
386 *
387 * :: Convert LNodeTree -> TokenList
388 *
389 ****************************************************************************/
390
391localstatic TokenList
392lntToTokenList(LNodeTree lnt)
393{
394 return listNReverse(Token)(Token_listPointer->NReverse)(lntToTokenList0(lnt, NULL((void*)0)));
395}
396
397localstatic TokenList
398lntToTokenList0(LNodeTree lnt, TokenList rsofar)
399{
400 int i, n;
401
402 if (!lnt) return rsofar;
403
404 n = lnt->argc;
405
406 switch (lnt->kind) {
407 case LN_1Tok:
408 rsofar = listCons(Token)(Token_listPointer->Cons)(lnt->argv[0].tok, rsofar);
409 break;
410 case LN_NTok:
411 for (i = 0; i < n; i++)
412 rsofar = listCons(Token)(Token_listPointer->Cons)(lnt->argv[i].tok, rsofar);
413 break;
414 case LN_NNodes:
415 for (i = 0; i < n; i++)
416 rsofar = lntToTokenList0(lnt->argv[i].lnode, rsofar);
417 break;
418 case LN_DoPile:
419 /* Insert newlines between each pair of args. */
420 rsofar = lntToTokenList0(lnt->argv[0].lnode, rsofar);
421 rsofar = lntConsNL(rsofar);
422 for (i = 1; i < n-1; i++) {
423 rsofar = lntToTokenList0(lnt->argv[i].lnode, rsofar);
424 rsofar = lntConsNL(rsofar);
425 }
426 rsofar = lntToTokenList0(lnt->argv[n-1].lnode, rsofar);
427 break;
428 }
429
430 return rsofar;
431}
432
433localstatic TokenList
434lntConsNL(TokenList tl)
435{
436 Token nl = linKeyword(tl ? car(tl)((tl)->first) : 0, KW_NewLine);
437
438 return listCons(Token)(Token_listPointer->Cons)(nl, tl);
439}
440
441/*****************************************************************************
442 *
443 * :: Convert TokenList -> LNodeTree
444 *
445 ****************************************************************************/
446
447/*
448 * Use a recursive descent parser to convert from lists to trees.
449 */
450localstatic LNodeTree lntFrTL_DoPile (TokenList *);
451localstatic LNodeTree lntFrTL_DoLine (TokenList *);
452localstatic LNodeTree lntFrTL_DontPile (TokenList *);
453localstatic LNodeTree lntFrTL_DontLine (TokenList *, Bool isStacking);
454localstatic LNodeTree lntFrTL_1Tok (TokenList *);
455localstatic LNodeTree lntFrTL_MakeLine (LNodeTreeList,int,Length,Length);
456
457localstatic int depthDoPileNo;
458localstatic int depthDontPileNo;
459
460/* Top-level entry-point for converting token lists into lnode trees */
461localstatic LNodeTree
462lntFrTokenList(TokenList tl)
463{
464 depthDoPileNo = 0;
465 depthDontPileNo = 0;
466
467 return lntFrTL_DontLine(&tl, false((int) 0));
468}
469
470/*
471 * Convert a list of tokens for a piled section of code into a tree. If
472 * the end of the stream is reached without finding a closing #endpile
473 * then one is automatically added. The first child of the result tree
474 * is the #pile token and the last is a #endpile token. The other nodes
475 * correspond to complete lines from source code or embedded piled or
476 * non-piled sections blocks.
477 */
478localstatic LNodeTree
479lntFrTL_DoPile(TokenList *ptl)
480{
481 TokenList tl0 = *ptl;
482 LNodeTreeList ll, l;
483 LNodeTree lnt;
484 Token tk;
485 int i, n, in0;
486 Bool has;
487
488 assert(tl0)do { if (!(tl0)) _do_assert(("tl0"),"linear.c",488); } while (
0)
;
489 assert(tokTag(car(tl0)) == DoPileStart)do { if (!(((TokenTag) (((tl0)->first))->tag) == KW_StartPile
)) _do_assert(("tokTag(car(tl0)) == DoPileStart"),"linear.c",
489); } while (0)
;
490
491 depthDoPileNo += 1;
492 in0 = linIndentation(tl0);
493 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lntFrTL_1Tok(&tl0), NULL((void*)0));
494 n = 1;
495
496 while (tl0 && tokTag(car(tl0))((TokenTag) (((tl0)->first))->tag) != DoPileEndKW_EndPile) {
497 lnt = lntFrTL_DoLine(&tl0);
498 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt, ll);
499 n++;
500 }
501 if (tl0 && tokTag(car(tl0))((TokenTag) (((tl0)->first))->tag) == DoPileEndKW_EndPile) {
502 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lntFrTL_1Tok(&tl0), ll);
503 n++;
504 }
505 /* Insert extra #endpile if needed. */
506 else if (!tl0) {
507 tk = tokKeyword(sposNone, sposNone, DoPileEnd)tokNew(sposNone, sposNone, KW_EndPile);
508 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lntTok(tk), ll);
509 n++;
510 }
511
512 lnt = lntNewEmpty(LN_DoPile, n);
513 has = 0;
514 for (i = n-1, l = ll; i >= 0 ; i--, l = cdr(l)((l)->rest)) {
515 lnt->argv[i].lnode = car(l)((l)->first);
516 has |= car(l)((l)->first)->has;
517 }
518 lnt->indent = in0;
519 lnt->has = has;
520
521 *ptl = tl0;
522 listFree(LNodeTree)(LNodeTree_listPointer->Free)(ll);
523 depthDoPileNo -= 1;
524 return lnt;
525}
526
527
528/*
529 * Convert a list of tokens for a single line of code into a tree. If a
530 * #pile token is found then the embedded piled section is converted into
531 * a single tree node; likewise for embedded non-piled sections. All
532 * other tokens are added to the result tree as leaves. Processing stops
533 * when a newline token is found, the end of the token stream is reached,
534 * or when a #endpile or } token is found without a matching #pile or {.
535 */
536localstatic LNodeTree
537lntFrTL_DoLine(TokenList *ptl)
538{
539 TokenList tl0 = *ptl;
540 TokenTag tag;
541 LNodeTreeList ll;
542 LNodeTree lnt;
543 int n, ntoks, in0;
544
545 if (!tl0) {
546 lnt = lntNewEmpty(LN_NTok, int0((int) 0));
547 lnt->indent = 0;
548 lnt->has = 0;
549 return lnt;
550 }
551
552 in0 = linIndentation(tl0);
553 ll = 0;
554 n = 0;
555 ntoks = 0;
556
557 /* This test always succeeds and is therefore redundant */
558 if (tl0) do {
559 tag = tokTag(car(tl0))((TokenTag) (((tl0)->first))->tag);
560
561 switch (tag) {
562 case DoPileStartKW_StartPile:
563 lnt = lntFrTL_DoPile(&tl0);
564 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt, ll);
565 n++;
566 break;
567 case DontPileStartKW_OCurly:
568 lnt = lntFrTL_DontPile(&tl0);
569 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt, ll);
570 n++;
571 break;
572 case DoPileEndKW_EndPile:
573 case DontPileEndKW_CCurly:
574 if (tag == DoPileEndKW_EndPile)
575#if 1
576 break; /*XXXXXXX*/
577#else
578 if (depthDoPileNo)
579 break;
580 else if (depthDontPileNo)
581 break;
582#endif
583 /* Fall through */
584 default:
585 lnt = lntFrTL_1Tok(&tl0);
586 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt, ll);
587 n++;
588 ntoks++;
589 break;
590 }
591 } while (tag != KW_NewLine &&
592 (tag != DoPileEndKW_EndPile || depthDoPileNo == 0) &&
593 (tag != DontPileEndKW_CCurly || depthDontPileNo == 0) &&
594 tl0);
595
596 lnt = lntFrTL_MakeLine(ll, in0, n, ntoks);
597 *ptl = tl0;
598 listFree(LNodeTree)(LNodeTree_listPointer->Free)(ll);
599 return lnt;
600}
601
602/*
603 * Convert a list of tokens for a non-piled section into an lnode tree.
604 * For correctly balanced programs the result tree will have three child
605 * nodes: the first will be a { leaf and the third will be a } leaf. The
606 * second node will contain all tokens within the non-piled section with
607 * the nesting of non-piled sections removed. Piled sections will have
608 * their own tree nodes as normal.
609 */
610localstatic LNodeTree
611lntFrTL_DontPile(TokenList *ptl)
612{
613 TokenList tl0 = *ptl;
614 LNodeTreeList ll, l;
615 LNodeTree lnt;
616 int i, n, in0;
617 Bool has;
618
619 assert(tl0)do { if (!(tl0)) _do_assert(("tl0"),"linear.c",619); } while (
0)
;
620 assert(tokTag(car(tl0)) == DontPileStart)do { if (!(((TokenTag) (((tl0)->first))->tag) == KW_OCurly
)) _do_assert(("tokTag(car(tl0)) == DontPileStart"),"linear.c"
,620); } while (0)
;
621
622 depthDontPileNo += 1;
623 in0 = linIndentation(tl0);
624 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lntFrTL_1Tok(&tl0), NULL((void*)0));
625 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lntFrTL_DontLine(&tl0, true1), ll);
626 n = 2;
627 if (tl0 && tokTag(car(tl0))((TokenTag) (((tl0)->first))->tag) == DontPileEndKW_CCurly) {
628 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lntFrTL_1Tok(&tl0), ll);
629 n++;
630 }
631
632 lnt = lntNewEmpty(LN_NNodes, n);
633 has = 0;
634 for (i = n-1, l = ll; i >= 0 ; i--, l = cdr(l)((l)->rest)) {
635 lnt->argv[i].lnode = car(l)((l)->first);
636 has |= car(l)((l)->first)->has;
637 }
638 lnt->indent = in0;
639 lnt->has = has;
640
641 *ptl = tl0;
642 listFree(LNodeTree)(LNodeTree_listPointer->Free)(ll);
643 depthDontPileNo -= 1;
644 return lnt;
645}
646
647/*
648 * Convert a list of tokens in a non-piled section into a tree. If the
649 * isStacking flag is false then every token is placed in the resulting
650 * tree even if it is not correctly balanced. Otherwise only the tokens
651 * up to the end of the non-piled section are consumed taking into account
652 * the balancing of { } around non-piled sections.
653 */
654localstatic LNodeTree
655lntFrTL_DontLine(TokenList *ptl, Bool isStacking)
656{
657 TokenList tl0 = *ptl;
658 TokenTag tag;
659 LNodeTreeList ll;
660 LNodeTree lnt;
661 int n, ntoks, in0, depth;
662
663 if (!tl0) {
664 lnt = lntNewEmpty(LN_NTok, int0((int) 0));
665 lnt->indent = 0;
666 lnt->has = 0;
667 return lnt;
668 }
669
670 in0 = linIndentation(tl0);
671 depth = 0;
672 n = 0;
673 ntoks = 0;
674 ll = 0;
675
676 while (tl0) {
677 tag = tokTag(car(tl0))((TokenTag) (((tl0)->first))->tag);
678
679 if (tag == DoPileStartKW_StartPile) {
680 lnt = lntFrTL_DoPile(&tl0);
681 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt, ll);
682 n++;
683 }
684 else {
685 if (isStacking && tag == DontPileStartKW_OCurly) {
686 depth++;
687 }
688 if (isStacking && tag == DontPileEndKW_CCurly) {
689 depth--;
690 }
691 if (depth < 0) break;
692
693 lnt = lntFrTL_1Tok(&tl0);
694 ll = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt, ll);
695 n++;
696 ntoks++;
697 }
698 }
699
700 lnt = lntFrTL_MakeLine(ll, in0, n, ntoks);
701 *ptl = tl0;
702 listFree(LNodeTree)(LNodeTree_listPointer->Free)(ll);
703 return lnt;
704}
705
706
707/* Remove a token from the token list and convert into an lnode tree leaf */
708localstatic LNodeTree
709lntFrTL_1Tok(TokenList *ptl)
710{
711 LNodeTree lnt;
712
713 assert(*ptl)do { if (!(*ptl)) _do_assert(("*ptl"),"linear.c",713); } while
(0)
;
714
715 lnt = lntTok(car(*ptl)((*ptl)->first));
716 *ptl = cdr(*ptl)((*ptl)->rest);
717
718 return lnt;
719}
720
721/* Convert a list of tree nodes into a single n-ary tree node */
722localstatic LNodeTree
723lntFrTL_MakeLine(LNodeTreeList ll, int in0, Length n, Length ntoks)
724{
725 int i;
726 LNodeTreeList l;
727 LNodeTree lnt;
728 Bool has;
729
730 has = 0;
731 for (l = ll; l; l = cdr(l)((l)->rest))
732 has |= car(l)((l)->first)->has;
733
734 if (n == 1) {
735 lnt = car(ll)((ll)->first);
736 }
737 else if (n == ntoks) {
738 /*
739 * Compactify the case when all subtrees are tokens.
740 */
741 lnt = lntNewEmpty(LN_NTok, n);
742 lnt->indent = in0;
743 lnt->has = has;
744
745 for (i = n-1, l = ll; i >= 0; i--, l = cdr(l)((l)->rest)) {
746 lnt->argv[i].tok = car(l)((l)->first)->argv[0].tok;
747 lntFree(car(l)((l)->first));
748 }
749 }
750 else {
751 lnt = lntNewEmpty(LN_NNodes, n);
752 lnt->indent = in0;
753 lnt->has = has;
754
755 for (i = n-1, l = ll; i >= 0; i--, l = cdr(l)((l)->rest))
756 lnt->argv[i].lnode = car(l)((l)->first);
757 }
758
759 return lnt;
760}
761
762
763/****************************************************************************
764 *
765 * :: Verify balance of piling braces
766 *
767 ***************************************************************************/
768
769# define LIN_NOT_OK0 0
770# define LIN_OK1 1
771
772localstatic void
773serrorUnbalanced(Token tok,Bool errorIfTrue)
774{
775 SrcPos pos = tok->pos;
776 TokenTag tag = tokTag(tok)((TokenTag) (tok)->tag), mate = tokTag(tok)((TokenTag) (tok)->tag);
777
778 switch (tag) {
779 case DoPileStartKW_StartPile: mate = DoPileEndKW_EndPile; break;
780 case DoPileEndKW_EndPile: mate = DoPileStartKW_StartPile; break;
781 case DontPileStartKW_OCurly: mate = DontPileEndKW_CCurly; break;
782 case DontPileEndKW_CCurly: mate = DontPileStartKW_OCurly; break;
783 default: comsgFatal(abNewNothing(pos)abNew(AB_Nothing, pos,0 ), ALDOR_F_Bug365,
784 "unexpected unbalanced token");
785 }
786
787 if (errorIfTrue) {
788 comsgError(abNewNothing(pos)abNew(AB_Nothing, pos,0 ), ALDOR_E_LinUnbalanced70,
789 keyString(tag), keyString(mate));
790 }
791 else {
792 comsgWarning(abNewNothing(pos)abNew(AB_Nothing, pos,0 ), ALDOR_E_LinUnbalanced70,
793 keyString(tag), keyString(mate));
794 }
795}
796
797/*
798 * Look for unmatched {,},{|,|} and give error msg.
799 * It also sets tok->extra field for each token in the token list.
800 */
801localstatic void
802linCheckBalance0(TokenList *ptl, Token lastOpener, int depth)
803{
804 TokenTag tag;
805 Token tok;
806
807 linDEBUGif (!linDebug) { } else afprintf(dbOut, "->> linCheckPile0: %d--\n", tokTag(lastOpener)((TokenTag) (lastOpener)->tag));
808
809 lastOpener->extra = LIN_OK1;
810
811 while (*ptl) {
812 tok = car(*ptl)((*ptl)->first);
813 tag = tokTag(tok)((TokenTag) (tok)->tag);
814 *ptl = cdr(*ptl)((*ptl)->rest);
815
816 switch(tag) {
817 case DoPileStartKW_StartPile:
818 case DontPileStartKW_OCurly:
819 linCheckBalance0(ptl, tok, depth+1);
820 break;
821 case DoPileEndKW_EndPile:
822 if (tokTag(lastOpener)((TokenTag) (lastOpener)->tag) == DoPileStartKW_StartPile) {
823 tok->extra = LIN_OK1;
824 linDEBUGif (!linDebug) { } else afprintf(dbOut, "-<< linCheckPile0- |} --\n");
825 return;
826 }
827 else {
828 tok->extra = LIN_NOT_OK0;
829 serrorUnbalanced(tok,true1);
830 }
831 break;
832 case DontPileEndKW_CCurly:
833 if (tokTag(lastOpener)((TokenTag) (lastOpener)->tag) == DontPileStartKW_OCurly) {
834 tok->extra = LIN_NOT_OK0;
835 linDEBUGif (!linDebug) { } else afprintf(dbOut, "-<< linCheckPile0- } --\n");
836 return;
837 }
838 else {
839 tok->extra = LIN_NOT_OK0;
840 serrorUnbalanced(tok,true1);
841 }
842 break;
843 default:
844 break;
845 }
846 }
847
848 /* Detect unmatched opener, but allow missing #endpile at top level.*/
849 tag = tokTag(lastOpener)((TokenTag) (lastOpener)->tag);
850 if (tag != TK_Blank && tag != DoPileStartKW_StartPile ) {
851 lastOpener->extra = LIN_NOT_OK0;
852 serrorUnbalanced(lastOpener,true1);
853 }
854 if (tag != TK_Blank && depth > 1 ) {
855 lastOpener->extra = LIN_NOT_OK0;
856 serrorUnbalanced(lastOpener,false((int) 0));
857 }
858 linDEBUGif (!linDebug) { } else afprintf(dbOut, "-<< linCheckPile0-NULL--\n");
859}
860
861
862/*
863 * This function returns the original list but we should suppose that
864 * it could be different -- we may later insert correction tokens.
865 */
866localstatic TokenList
867linCheckBalance(TokenList tl0)
868{
869 TokenList tl = tl0;
870 Token tok;
871
872 /* Mark all nodes OK. */
873 for (tl = tl0; tl; tl = cdr(tl)((tl)->rest))
874 car(tl)((tl)->first)->extra = LIN_OK1;
875
876 /* Do the balancing act. */
877 tl = tl0;
878 tok = tokNew(sposNone, sposNone, TK_Blank, NULL((void*)0));
879 linCheckBalance0(&tl, tok, int0((int) 0));
880 tokFree(tok);
881
882 return tl0;
883}
884
885/*****************************************************************************
886 *
887 * :: Main entry point of linearizer
888 *
889 ****************************************************************************/
890
891TokenList
892linearize(TokenList tl)
893{
894 LNodeTree lnt;
895
896 if (DEBUG(lin)linDebug) {
897 fprintf(dbOut,"-------------- Starting with -------------\n");
898 toklistPrint(dbOut, tl);
899 fnewline(dbOut);
900 }
901
902 tl = linXComments(tl)linXTokens((tl), TK_Comment);
903 tl = linXBlankLines(tl);
904
905 /* Add a `#pile' if in interactive mode, so that the user can use
906 * TAB for an easier input.
907 */
908
909 if (fintMode == FINT_LOOP2) {
910 Token tok = tokNew(sposNone, sposNone, KW_StartPile, NULL((void*)0));
911 listPush(Token, tok, tl)(tl = (Token_listPointer->Cons)(tok, tl));
912 }
913
914 tl = linCheckBalance(tl);
915 lnt = lntFrTokenList(tl);
916 listFree(Token)(Token_listPointer->Free)(tl);
917 if (DEBUG(lin)linDebug) {
918 fprintf(dbOut,"-------------- Converted to --------------\n");
919 lntPrint(dbOut, lnt);
920 fnewline(dbOut);
921 }
922
923 lnt = lin2DRules(lnt);
924 if (DEBUG(lin)linDebug) {
925 fprintf(dbOut,"-------------- Converted to -------------\n");
926 lntPrint(dbOut, lnt);
927 fnewline(dbOut);
928 }
929
930 tl = lntToTokenList(lnt);
931 tl = linXNewLines(tl)linXTokens((tl), KW_NewLine);
932 lntFree(lnt);
933 if (DEBUG(lin)linDebug) {
934 fprintf(dbOut,"-------------- Ending with -------------\n");
935 toklistPrint(dbOut, tl);
936 fnewline(dbOut);
937 }
938
939 tl = linUseNeededSep(tl);
940
941 if (DEBUG(lin)linDebug) {
942 fprintf(dbOut,"-------------- Leaving with ------------\n");
943 toklistPrint(dbOut, tl);
944 fnewline(dbOut);
945 }
946
947 return tl;
948}
949
950/* This function inserts or deletes statement separators (;) as required */
951localstatic TokenList
952linUseNeededSep(TokenList tl)
953{
954 tl = linISepAfterDontPiles(tl);
955
956 if (DEBUG(lin)linDebug) {
957 fprintf(dbOut,"------- linUseNeededSep (mid) ----------\n");
958 toklistPrint(dbOut, tl);
959 fnewline(dbOut);
960 }
961
962 tl = linXSep(tl);
963
964 if (DEBUG(lin)linDebug) {
965 fprintf(dbOut,"------- linUseNeededSep (xit) ----------\n");
966 toklistPrint(dbOut, tl);
967 fnewline(dbOut);
968 }
969 return tl;
970}
971
972/*****************************************************************************
973 *
974 * :: TokenList Utilities
975 *
976 ****************************************************************************/
977
978localstatic Token
979linKeyword(Token org, TokenTag key)
980{
981 SrcPos spos = org ? org->pos : sposNone;
982 SrcPos epos = org ? org->end : sposNone;
983
984 return tokKeyword(spos, epos, key)tokNew(spos, epos, key);
985}
986
987/*
988 * Free the specified tokens. (Modifies the original list.)
989 */
990localstatic TokenList
991linXTokens(TokenList tl, TokenTag tag)
992{
993 struct TokenListCons head;
994 TokenList prev;
995
996 setcar(&head, NULL)((&head)->first = (((void*)0)));
997 setcdr(&head, tl)((&head)->rest = (tl));
998
999 for (prev = &head; cdr(prev)((prev)->rest); ) {
1000 TokenList curr = cdr(prev)((prev)->rest);
1001 Token tok = car(curr)((curr)->first);
1002
1003 if (tokTag(tok)((TokenTag) (tok)->tag) == tag) {
1004 setcdr(prev, cdr(curr))((prev)->rest = (((curr)->rest)));
1005 listFreeCons(Token)(Token_listPointer->FreeCons)(curr);
1006 tokFree(tok);
1007 }
1008 else
1009 prev = curr;
1010 }
1011 return cdr(&head)((&head)->rest);
1012}
1013
1014/*
1015 * Free leading newlines and all but the first of consecutive newlines.
1016 * (Modifies the original list.)
1017 */
1018localstatic TokenList
1019linXBlankLines0(TokenList tl)
1020{
1021 while (tl && tokTag(car(tl))((TokenTag) (((tl)->first))->tag) == KW_NewLine) {
1022 Token tk = car(tl)((tl)->first);
1023 TokenList rl = cdr(tl)((tl)->rest);
1024
1025 tokFree(tk);
1026 listFreeCons(Token)(Token_listPointer->FreeCons)(tl);
1027 tl = rl;
1028 }
1029 return tl;
1030}
1031
1032localstatic TokenList
1033linXBlankLines(TokenList tl0)
1034{
1035 TokenList tl;
1036
1037 tl0 = linXBlankLines0(tl0);
1038
1039 for (tl = tl0; tl; tl = cdr(tl)((tl)->rest)) {
1040 Token tok = car(tl)((tl)->first);
1041 TokenList rest = cdr(tl)((tl)->rest);
1042
1043 if (tokTag(tok)((TokenTag) (tok)->tag) == KW_NewLine || tokTag(tok)((TokenTag) (tok)->tag) == DoPileStartKW_StartPile) {
1044 /* !!!FIXME!!! Loop executes just once? */
1045 while (rest && tokTag(car(rest))((TokenTag) (((rest)->first))->tag) == KW_NewLine)
1046 rest = linXBlankLines0(rest);
1047 setcdr(tl, rest)((tl)->rest = (rest));
1048 }
1049 }
1050 return tl0;
1051}
1052
1053
1054/*
1055 * Insert ";" after all "}". (Modifies the original list.) This function
1056 * ought to be modified to use a two-token look-ahead. If the next token
1057 * is not DontPileSep and the one after is not a follower or a closer
1058 * then the insertion can take place. If this change is made then linXSep
1059 * is redundant and the compiler will make fewer strange parsing decisions.
1060 */
1061localstatic TokenList
1062linISepAfterDontPiles(TokenList tl)
1063{
1064 TokenList t;
1065 for (t = tl; t; t = cdr(t)((t)->rest)) {
1066 if (tokIs(car(t), DontPileEnd)((((t)->first))->tag == (KW_CCurly))) {
1067 TokenList trest = cdr(t)((t)->rest);
1068
1069 if (trest && !tokIs(car(trest), DontPileSep)((((trest)->first))->tag == (KW_Semicolon))) {
1070 Token tok = linKeyword(car(t)((t)->first),DontPileSepKW_Semicolon);
1071 trest = listCons(Token)(Token_listPointer->Cons)(tok, trest);
1072 setcdr(t, trest)((t)->rest = (trest));
1073 }
1074 }
1075 }
1076
1077 return tl;
1078}
1079
1080/*
1081 * Delete ";" before non-starters. This function would be redundant if
1082 * linISepAfterDontPiles() used a two-token look-ahead.
1083 */
1084localstatic TokenList
1085linXSep(TokenList tl)
1086{
1087 TokenList t;
1088
1089 /* Delete leading string ";". */
1090 while (tl && tokIs(car(tl), DontPileSep)((((tl)->first))->tag == (KW_Semicolon)))
1091 tl = listFreeDeeplyTo(Token)(Token_listPointer->FreeDeeplyTo)(tl,cdr(tl)((tl)->rest),tokFree);
1092
1093 /* Delete ";" before non-starters. */
1094 for (t = tl; t; t = cdr(t)((t)->rest)) {
1095 TokenList tcdr, tcddr;
1096 tcdr = cdr(t)((t)->rest);
1097 if (!tcdr) break;
1098 if (!tokIs(car(tcdr), DontPileSep)((((tcdr)->first))->tag == (KW_Semicolon))) continue;
1099 tcddr = cdr(tcdr)((tcdr)->rest);
1100 if (!tcddr || tokIsNonStarter(car(tcddr))(((tokInfoTable[((((tcddr)->first))->tag)-TK_START]).isFollower
) || ((tokInfoTable[((((tcddr)->first))->tag)-TK_START]
).isCloser))
)
1101 setcdr(t, listFreeDeeplyTo(Token)(tcdr,tcddr,tokFree))((t)->rest = ((Token_listPointer->FreeDeeplyTo)(tcdr,tcddr
,tokFree)))
;
1102 }
1103
1104 return tl;
1105}
1106
1107/*
1108 * Determine the true indentation a line, taking into account labels.
1109 */
1110localstatic int
1111linIndentation(TokenList tl)
1112{
1113 int ind;
1114
1115 if (DEBUG(lin)linDebug) {
1116 if (tl)
1117 tokPrint(dbOut, car(tl)((tl)->first));
1118 }
1119
1120 if (tl && tokIs(car(tl), KW_At)((((tl)->first))->tag == (KW_At))) {
1121 /* Skip '@' and 'id' if there. */
1122 tl = cdr(tl)((tl)->rest);
1123 if (tl) tl = cdr(tl)((tl)->rest);
1124 }
1125 ind = tl && !tokIs(car(tl), KW_NewLine)((((tl)->first))->tag == (KW_NewLine))
1126 ? sposChar(car(tl)((tl)->first)->pos)
1127 : MootIndentation(-1);
1128
1129 phaseDEBUGif (!phaseDebug) { } else afprintf(dbOut, " line indented to: %d\n", ind);
1130
1131 return ind;
1132}
1133
1134/****************************************************************************
1135 *
1136 * :: Apply piling rules.
1137 *
1138 ****************************************************************************/
1139
1140localstatic LNodeTree lin2DRulesPile (LNodeTree);
1141localstatic LNodeTree lin2DRulesPile0 (LNodeTree context, LNodeTree, int *, int *);
1142
1143localstatic LNodeTree joinUp (LNodeTree context, LNodeTreeList);
1144localstatic Bool isBackSetRequired (LNodeTree context, LNodeTree, LNodeTree);
1145localstatic Bool isPileRequired (LNodeTree context, LNodeTree);
1146
1147localstatic LNodeTree
1148lin2DRules(LNodeTree lnt)
1149{
1150 int i, n;
1151 n = lnt->argc;
1152
1153 switch (lnt->kind) {
1154 case LN_1Tok:
1155 case LN_NTok:
1156 break;
1157 case LN_NNodes:
1158 for (i = 0; i < n; i++)
1159 lnt->argv[i].lnode = lin2DRules(lnt->argv[i].lnode);
1160 break;
1161 case LN_DoPile:
1162 for (i = 0; i < n; i++)
1163 lnt->argv[i].lnode = lin2DRules(lnt->argv[i].lnode);
1164 lnt = lin2DRulesPile(lnt);
1165 break;
1166 }
1167
1168 return lnt;
1169}
1170
1171#define linIsArgKW(lnt,n,k)((lnt)->argc > (n) && (lnt)->argv[n].lnode->
kind == LN_1Tok && (((lnt)->argv[n].lnode->argv
[0].tok)->tag == (k)))
\
1172 ((lnt)->argc > (n) && (lnt)->argv[n].lnode->kind == LN_1Tok && \
1173 tokIs((lnt)->argv[n].lnode->argv[0].tok, k)(((lnt)->argv[n].lnode->argv[0].tok)->tag == (k)))
1174
1175localstatic LNodeTree
1176lin2DRulesPile(LNodeTree lnt)
1177{
1178 Bool hasStarter, hasEnder;
1179 int iS, iE;
1180 LNodeTree rnt;
1181
1182 assert(lnt->kind == LN_DoPile)do { if (!(lnt->kind == LN_DoPile)) _do_assert(("lnt->kind == LN_DoPile"
),"linear.c",1182); } while (0)
;
1183
1184 hasStarter = linIsArgKW(lnt, int0, DoPileStart)((lnt)->argc > (((int) 0)) && (lnt)->argv[((
int) 0)].lnode->kind == LN_1Tok && (((lnt)->argv
[((int) 0)].lnode->argv[0].tok)->tag == (KW_StartPile))
)
;
1185 hasEnder = linIsArgKW(lnt, lnt->argc-1, DoPileEnd)((lnt)->argc > (lnt->argc-1) && (lnt)->argv
[lnt->argc-1].lnode->kind == LN_1Tok && (((lnt)
->argv[lnt->argc-1].lnode->argv[0].tok)->tag == (
KW_EndPile)))
;
1186
1187 iS = hasStarter ? 1 : 0;
1188 iE = hasStarter && hasEnder ? lnt->argc - 2 : lnt->argc - 1;
1189
1190 /*
1191 * Consider xxx1
1192 * xxx2
1193 * xxx3
1194 * xxx4
1195 * xxx5
1196 */
1197
1198 /* Handle pile starting with first line: xxx1..xxx4 */
1199 rnt = lin2DRulesPile0(NULL((void*)0), lnt, &iS, &iE);
1200
1201 /* Handle subsequent outdented piles: e.g., xxx5 */
1202 while (iS <= iE)
1203 rnt = lin2DRulesPile0(rnt, lnt, &iS, &iE);
1204
1205 lntFreeNode(lnt);
1206 return rnt;
1207}
1208
1209
1210/*
1211 * Piles a range of descendents. Note that since the final argument is
1212 * never updated it ought to be passed by value.
1213 */
1214localstatic LNodeTree
1215lin2DRulesPile0(LNodeTree context, LNodeTree lnt, int *piS, int *piE)
1216{
1217 int iS = *piS, iE = *piE;
1218 int indentS, indent0;
1219 LNodeTree lnt0;
1220 LNodeTreeList sofar;
1221
1222 phaseDEBUGif (!phaseDebug) { } else afprintf(dbOut, " ==== Linearizing parts %d to %d \n", *piS, *piE);
1223
1224 if (iS > iE) return lntNewEmpty(LN_NNodes, int0((int) 0));
1225
1226 indentS = lnt->argv[iS].lnode->indent;
1227 sofar = 0;
1228
1229 phaseDEBUGif (!phaseDebug) { } else afprintf(dbOut, "indentS = %d\n", indentS);
1230 while (iS <= iE) {
1231 lnt0 = lnt->argv[iS].lnode;
1232 indent0 = lnt0->indent;
1233
1234 if (DEBUG(phase)phaseDebug) {
1235 fprintf(dbOut,"%d/%d/%d. indent0 = %d (argc = %d)\n",
1236 iS, iE, (int) lnt->argc,
1237 indent0, (int) lnt0->argc);
1238 lntPrint(dbOut, lnt0);
1239 fnewline(dbOut);
1240 }
1241
1242 if (linIsBlank(lnt0)(!((lnt0)->has & (1<<1))) || indent0 == MootIndentation(-1)) {
1243 iS++;
1244 phaseDEBUGif (!phaseDebug) { } else afprintf(dbOut, "Ah.... a blank line _________\n");
1245 sofar = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt0, sofar);
1246 continue;
1247 }
1248
1249 phaseDEBUGif (!phaseDebug) { } else afprintf(dbOut, "%d :: %d\n", indent0, indentS);
1250 if (indent0 < indentS)
1251 break;
1252
1253 if (indent0 == indentS) {
1254 iS++;
1255 sofar = listCons(LNodeTree)(LNodeTree_listPointer->Cons)(lnt0, sofar);
1256 if (DEBUG(phase)phaseDebug) {
1257 fprintf(dbOut,"Adding one more +++++++++++++ ");
1258 listPrint(LNodeTree)(LNodeTree_listPointer->Print)(dbOut, sofar, lntPrint);
1259 fnewline(dbOut);
1260 }
1261 }
1262 /* (indent0 > indentS) */
1263 else {
1264 setcar(sofar, lin2DRulesPile0(car(sofar),lnt,&iS,&iE))((sofar)->first = (lin2DRulesPile0(((sofar)->first),lnt
,&iS,&iE)))
;
1265 if (DEBUG(phase)phaseDebug) {
1266 fprintf(dbOut,"Joining indentee >>>>>>>>>>>> ");
1267 listPrint(LNodeTree)(LNodeTree_listPointer->Print)(dbOut, sofar, lntPrint);
1268 fnewline(dbOut);
1269 }
1270 }
1271 }
1272 sofar = listNReverse(LNodeTree)(LNodeTree_listPointer->NReverse)(sofar);
1273 lnt0 = lntConcat(context, joinUp(context, sofar));
1274
1275 if (DEBUG(phase)phaseDebug) {
1276 fprintf(dbOut,"Result of joinUp is !!!!!!!!!!!!! ");
1277 lntPrint(dbOut, lnt0);
1278 fnewline(dbOut);
1279 }
1280
1281 /* Free the list we just consed. */
1282 listFree(LNodeTree)(LNodeTree_listPointer->Free)(sofar);
1283 *piS = iS;
1284 *piE = iE;
1285 return lnt0;
1286}
1287
1288
1289/*
1290 * Insert SetTab .. BackSet .. BackSet ... BackTab
1291 */
1292localstatic LNodeTree
1293joinUp(LNodeTree context, LNodeTreeList tll)
1294{
1295 LNodeTreeList l;
1296 LNodeTree lnt, t0, t1;
1297 Bool hadBackSet;
1298
1299 assert(tll != 0)do { if (!(tll != 0)) _do_assert(("tll != 0"),"linear.c",1299
); } while (0)
;
1300
1301 /* Insert BackSets between the lines, if necessary. */
1302 lnt = car(tll)((tll)->first);
1303 hadBackSet = false((int) 0);
1304
1305 for (l = tll, t0 = lnt; cdr(l)((l)->rest); l = cdr(l)((l)->rest), t0 = t1) {
1306 t1 = car(cdr(l))((((l)->rest))->first);
1307
1308 if (isBackSetRequired(context, t0, t1)) {
1309 hadBackSet = true1;
1310 lnt = lntSeparate(lnt, KW_BackSet, t1);
1311 }
1312 else
1313 lnt = lntConcat(lnt, t1);
1314 }
1315
1316 /* Surround with SetTab and BackTab, if necessary. */
1317 if (hadBackSet || isPileRequired(context, lnt))
1318 lnt = lntWrap(KW_SetTab, lnt, KW_BackTab);
1319
1320 return lnt;
1321}
1322
1323/*
1324 * "isPileRequired" decides whether a SetTab/BackTab empiling is needed
1325 * for the line which is to be joined to *pcontext.
1326 *
1327 * A single line pile is formed whenever the previous word is an alphabetic
1328 * language keyword, e.g. "return", "then", "else", etc.
1329 * (Note, this does not include user-definable operators such as "quo".)
1330 */
1331localstatic Bool
1332isPileRequired(LNodeTree context, LNodeTree lnt)
1333{
1334 /*ARGSUSED*/
1335 Token tok = lntLastTokLessNL(context);
1336
1337 phaseDEBUGif (!phaseDebug) { } else afprintf(dbOut,"In isPileRequired %s",
1338 tok? "with token: " : "NO TOK\n");
1339
1340 if (!tok) return false((int) 0);
1341
1342 if (DEBUG(phase)phaseDebug) {
1343 tokPrint(dbOut, tok);
1344 }
1345
1346 return tokIs(tok, KW_Then)((tok)->tag == (KW_Then)) || tokIs(tok, KW_Else)((tok)->tag == (KW_Else)) ||
1347 tokIs(tok, KW_With)((tok)->tag == (KW_With)) || tokIs(tok, KW_Add)((tok)->tag == (KW_Add)) ||
1348 tokIs(tok, KW_Try)((tok)->tag == (KW_Try)) || tokIs(tok, KW_But)((tok)->tag == (KW_But)) ||
1349 tokIs(tok, KW_Catch)((tok)->tag == (KW_Catch)) || tokIs(tok, KW_Finally)((tok)->tag == (KW_Finally)) ||
1350 tokIs(tok, KW_Always)((tok)->tag == (KW_Always));
1351}
1352
1353
1354/*
1355 * "isBackSetRequired" decides whether a BackSet is needed between tl1 and tl2.
1356 * Normally a BackSet is needed. The exceptions are:
1357 *
1358 * 1. tl1 contains only ++ comments (-- comments already deleted)
1359 * This allows
1360 *
1361 * ++ xxx
1362 * f: T -> Y
1363 *
1364 * 2. tl1 ends with "," or an opener ("(" "[" etc).
1365 * This allows
1366 *
1367 * f(x, a := [
1368 * y, 1, 2, 3,
1369 * z) 4, 5, 6 ]
1370 *
1371 * 3. tl2 begins with "in", "then", "else" or a closer (")" "]" "}" etc)
1372 * (i.e. words which CANNOT start an expression).
1373 * This allows
1374 *
1375 * if aaa let f(x, a := [1, 2, 3,
1376 * then bbb f == 1 y 4, 5, 6
1377 * else ccc in x := f+f ) ]
1378 *
1379 * 4. The lines occur within "{ }"
1380 *
1381 * Note: case 4 appears to be ignored and the context is not used.
1382 */
1383localstatic Bool
1384isBackSetRequired(LNodeTree context, LNodeTree lnt1, LNodeTree lnt2)
1385{
1386 /*ARGSUSED*/
1387 Token tok1 = lntLastTokLessNL (lnt1);
1388 Token tok2 = lntFirstTok (lnt2);
1389
1390 if (DEBUG(phase)phaseDebug) {
1391 fprintf(dbOut,"In isBackSetRequrired ");
1392 fprintf(dbOut,"First tree ");
1393 lntPrint(dbOut, lnt1);
1394 fnewline(dbOut);
1395 fprintf(dbOut,"Second tree ");
1396 lntPrint(dbOut, lnt2);
1397 fnewline(dbOut);
1398
1399 if (tok1){ fprintf(dbOut," with tok1 "); tokPrint(dbOut,tok1); }
1400 else {fprintf(dbOut,"No first token\n"); }
1401 if (tok2){ fprintf(dbOut," with tok2 "); tokPrint(dbOut,tok2); }
1402 else {fprintf(dbOut,"No second token\n"); }
1403 fnewline(dbOut);
1404 }
1405
1406 /* Rule 1 */
1407 if (linIsCom(lnt1)(!((lnt1)->has & (1<<0))) || linIsBlank(lnt1)(!((lnt1)->has & (1<<1))) || linIsBlank(lnt2)(!((lnt2)->has & (1<<1))))
1408 return false((int) 0);
1409
1410 if (!tok1 || !tok2)
1411 return true1;
1412
1413 /* Rule 2 */
1414 if (tokIs(tok1, KW_Comma)((tok1)->tag == (KW_Comma)) || tokIsOpener(tok1)((tokInfoTable[((tok1)->tag)-TK_START]).isOpener))
1415 return false((int) 0);
1416
1417 /* Rule 3 */
1418 if (tokIsFollower(tok2)((tokInfoTable[((tok2)->tag)-TK_START]).isFollower) || tokIsCloser(tok2)((tokInfoTable[((tok2)->tag)-TK_START]).isCloser))
1419 return false((int) 0);
1420
1421 return true1;
1422}
1423