a68g-pretty.c

     
   1  //! @file a68g-pretty.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //!
   6  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   7  //! Copyright 2001-2025 J. Marcel van der Veer [algol68g@xs4all.nl].
   8  
   9  //! @section License
  10  //!
  11  //! This program is free software; you can redistribute it and/or modify it 
  12  //! under the terms of the GNU General Public License as published by the 
  13  //! Free Software Foundation; either version 3 of the License, or 
  14  //! (at your option) any later version.
  15  //!
  16  //! This program is distributed in the hope that it will be useful, but 
  17  //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  //! more details. You should have received a copy of the GNU General Public 
  20  //! License along with this program. If not, see [http://www.gnu.org/licenses/].
  21  
  22  //! @section Synopsis
  23  //!
  24  //! Lay-out formatter for Algol 68.
  25  
  26  // Basic indenter for hopeless code.
  27  // It applies one style only.
  28  
  29  #include "a68g.h"
  30  #include "a68g-genie.h"
  31  #include "a68g-parser.h"
  32  #include "a68g-optimiser.h"
  33  #include "a68g-prelude.h"
  34  
  35  #define MAX_INDENT 60
  36  
  37  #define ONE_LINER (A68G_TRUE)
  38  #define KEYWORD (A68G_TRUE)
  39  #define BLANK {put_str (" ");}
  40  
  41  #define IS_OPEN_SYMBOL(p) (IS (p, OPEN_SYMBOL) || IS (p, SUB_SYMBOL) || IS (p, ACCO_SYMBOL))
  42  #define IS_CLOSE_SYMBOL(p) (IS (p, CLOSE_SYMBOL) || IS (p, BUS_SYMBOL) || IS (p, OCCA_SYMBOL))
  43  #define IS_IDENTIFIER(p) (IS (p, IDENTIFIER) || IS (p, DEFINING_IDENTIFIER) || IS (p, FIELD_IDENTIFIER))
  44  
  45  void indent_declarer (NODE_T *);
  46  void indent_serial (NODE_T *, BOOL_T, NODE_T **);
  47  void indent_statement (NODE_T *);
  48  void indent_format (NODE_T *);
  49  
  50  //! @brief Write newline and indent.
  51  
  52  void put_nl (void)
  53  {
  54    WRITE (A68G_INDENT (fd), "\n");
  55    for (A68G_INDENT (col) = 1; A68G_INDENT (col) < A68G_INDENT (ind); A68G_INDENT (col)++) {
  56      if (A68G_INDENT (col) <= MAX_INDENT) {
  57        WRITE (A68G_INDENT (fd), " ");
  58      }
  59    }
  60  }
  61  
  62  //! @brief Write a string.
  63  
  64  void put_str (char *txt)
  65  {
  66    WRITE (A68G_INDENT (fd), txt);
  67    A68G_INDENT (col) += strlen (txt);
  68  }
  69  
  70  //! @brief Write a character.
  71  
  72  void put_ch (char ch)
  73  {
  74    char str[2];
  75    str[0] = ch;
  76    str[1] = NULL_CHAR;
  77    put_str (str);
  78  }
  79  
  80  //! @brief Write pragment string.
  81  
  82  void put_pragment (NODE_T * p)
  83  {
  84    for (char *txt = NPRAGMENT (p); txt != NO_TEXT && txt[0] != NULL_CHAR; txt++) {
  85      if (txt[0] == NEWLINE_CHAR) {
  86        put_nl ();
  87      } else {
  88        put_ch (txt[0]);
  89      }
  90    }
  91  }
  92  
  93  //! @brief Write pragment string.
  94  
  95  void pretty_pragment (NODE_T * p, BOOL_T keyw)
  96  {
  97    if (NPRAGMENT (p) != NO_TEXT) {
  98      if (NPRAGMENT_TYPE (p) == BOLD_COMMENT_SYMBOL || NPRAGMENT_TYPE (p) == BOLD_PRAGMAT_SYMBOL) {
  99        if (!keyw) {
 100          put_nl ();
 101        }
 102        put_pragment (p);
 103        put_nl ();
 104        put_nl ();
 105      } else {
 106        if (!keyw && strlen (NPRAGMENT (p)) < 20) {
 107          if (A68G_INDENT (col) > A68G_INDENT (ind)) {
 108            BLANK;
 109          }
 110          put_pragment (p);
 111          BLANK;
 112        } else {
 113          if (A68G_INDENT (col) > A68G_INDENT (ind)) {
 114            put_nl ();
 115          }
 116          put_pragment (p);
 117          put_nl ();
 118        }
 119      }
 120    }
 121  }
 122  
 123  //! @brief Write with typographic display features.
 124  
 125  void put_sym (NODE_T * p, BOOL_T keyw)
 126  {
 127    char *txt = NSYMBOL (p);
 128    char *sym = NCHAR_IN_LINE (p);
 129    int n = 0;
 130    size_t size = strlen (txt);
 131    pretty_pragment (p, keyw);
 132    if (txt[0] != sym[0] || (INT_T) strlen (sym) - 1 <= size) {
 133  // Without features..
 134      put_str (txt);
 135    } else {
 136  // With features. Preserves spaces in identifiers etcetera..
 137      while (n < size) {
 138        put_ch (sym[0]);
 139        if (TO_LOWER (txt[0]) == TO_LOWER (sym[0])) {
 140          txt++;
 141          n++;
 142        }
 143        sym++;
 144      }
 145    }
 146  }
 147  
 148  //! @brief Count units and separators in a sub-tree.
 149  
 150  void count (NODE_T * p, int *units, int *seps)
 151  {
 152    for (; p != NO_NODE; FORWARD (p)) {
 153      if (IS (p, UNIT)) {
 154        (*units)++;
 155        count (SUB (p), units, seps);
 156      } else if (IS (p, SEMI_SYMBOL)) {
 157        (*seps)++;
 158      } else if (IS (p, COMMA_SYMBOL)) {
 159        (*seps)++;
 160      } else if (IS (p, CLOSED_CLAUSE)) {
 161        (*units)--;
 162      } else if (IS (p, COLLATERAL_CLAUSE)) {
 163        (*units)--;
 164        count (SUB (p), units, seps);
 165      } else {
 166        count (SUB (p), units, seps);
 167      }
 168    }
 169  }
 170  
 171  //! @brief Count units and separators in a sub-tree.
 172  
 173  void count_stowed (NODE_T * p, int *units, int *seps)
 174  {
 175    for (; p != NO_NODE; FORWARD (p)) {
 176      if (IS (p, UNIT)) {
 177        MOID_T *v = MOID (p);
 178        BOOL_T stowed = (BOOL_T) (IS_FLEX (v) || IS_ROW (v) || IS_STRUCT (v));
 179        if (stowed) {
 180          (*units)++;
 181        }
 182      } else if (IS (p, SEMI_SYMBOL)) {
 183        (*seps)++;
 184      } else if (IS (p, COMMA_SYMBOL)) {
 185        (*seps)++;
 186      } else {
 187        count_stowed (SUB (p), units, seps);
 188      }
 189    }
 190  }
 191  
 192  //! @brief Count enclosed_clauses in a sub-tree.
 193  
 194  void count_enclos (NODE_T * p, int *enclos, int *seps)
 195  {
 196    for (; p != NO_NODE; FORWARD (p)) {
 197      if (IS (p, ENCLOSED_CLAUSE)) {
 198        (*enclos)++;
 199      } else if (IS (p, SEMI_SYMBOL)) {
 200        (*seps)++;
 201      } else if (IS (p, COMMA_SYMBOL)) {
 202        (*seps)++;
 203      } else {
 204        count_enclos (SUB (p), enclos, seps);
 205      }
 206    }
 207  }
 208  
 209  //! @brief Indent sizety.
 210  
 211  void indent_sizety (NODE_T * p)
 212  {
 213    for (; p != NO_NODE; FORWARD (p)) {
 214      if (IS (p, LONGETY) || IS (p, SHORTETY)) {
 215        indent_sizety (SUB (p));
 216      } else if (IS (p, LONG_SYMBOL) || IS (p, SHORT_SYMBOL)) {
 217        put_sym (p, !KEYWORD);
 218        BLANK;
 219      }
 220    }
 221  }
 222  
 223  //! @brief Indent generic list.
 224  
 225  void indent_generic_list (NODE_T * p, NODE_T ** what, BOOL_T one_liner)
 226  {
 227    for (; p != NULL; FORWARD (p)) {
 228      if (IS_OPEN_SYMBOL (p)) {
 229        put_sym (p, KEYWORD);
 230        A68G_INDENT (ind) = A68G_INDENT (col);
 231      } else if (IS_CLOSE_SYMBOL (p)) {
 232        put_sym (p, KEYWORD);
 233      } else if (IS (p, BEGIN_SYMBOL)) {
 234        put_sym (p, KEYWORD);
 235        BLANK;
 236      } else if (IS (p, END_SYMBOL)) {
 237        BLANK;
 238        put_sym (p, KEYWORD);
 239      } else if (IS (p, AT_SYMBOL)) {
 240        if (NSYMBOL (p)[0] == '@') {
 241          put_sym (p, !KEYWORD);
 242        } else {
 243          BLANK;
 244          put_sym (p, !KEYWORD);
 245          BLANK;
 246        }
 247      } else if (IS (p, COLON_SYMBOL)) {
 248        BLANK;
 249        put_sym (p, !KEYWORD);
 250        BLANK;
 251      } else if (IS (p, DOTDOT_SYMBOL)) {
 252        BLANK;
 253        put_sym (p, !KEYWORD);
 254        BLANK;
 255      } else if (IS (p, UNIT)) {
 256        *what = p;
 257        indent_statement (SUB (p));
 258      } else if (IS (p, SPECIFIER)) {
 259        NODE_T *q = SUB (p);
 260        put_sym (q, KEYWORD);
 261        FORWARD (q);
 262        indent_declarer (q);
 263        FORWARD (q);
 264        if (IS_IDENTIFIER (q)) {
 265          BLANK;
 266          put_sym (q, !KEYWORD);
 267          FORWARD (q);
 268        }
 269        put_sym (q, !KEYWORD);
 270        FORWARD (q);
 271        put_sym (NEXT (p), !KEYWORD);     // : 
 272        BLANK;
 273        FORWARD (p);
 274      } else if (IS (p, COMMA_SYMBOL)) {
 275        put_sym (p, !KEYWORD);
 276        if (one_liner) {
 277          BLANK;
 278        } else {
 279          put_nl ();
 280        }
 281      } else {
 282        indent_generic_list (SUB (p), what, one_liner);
 283      }
 284    }
 285  }
 286  
 287  //! @brief Indent declarer pack.
 288  
 289  void indent_pack (NODE_T * p)
 290  {
 291    for (; p != NO_NODE; FORWARD (p)) {
 292      if (IS_OPEN_SYMBOL (p) || IS_CLOSE_SYMBOL (p)) {
 293        put_sym (p, KEYWORD);
 294      } else if (IS (p, COMMA_SYMBOL)) {
 295        put_sym (p, !KEYWORD);
 296        BLANK;
 297      } else if (IS (p, VOID_SYMBOL)) {
 298        put_sym (p, !KEYWORD);
 299      } else if (IS (p, DECLARER)) {
 300        indent_declarer (p);
 301        if (NEXT (p) != NO_NODE && IS_IDENTIFIER (NEXT (p))) {
 302          BLANK;
 303        }
 304      } else if (IS_IDENTIFIER (p)) {
 305        put_sym (p, !KEYWORD);
 306      } else {
 307        indent_pack (SUB (p));
 308      }
 309    }
 310  }
 311  
 312  //! @brief Indent declarer.
 313  
 314  void indent_declarer (NODE_T * p)
 315  {
 316    if (IS (p, DECLARER)) {
 317      indent_declarer (SUB (p));
 318    } else if (IS (p, LONGETY) || IS (p, SHORTETY)) {
 319      indent_sizety (SUB (p));
 320      indent_declarer (NEXT (p));
 321    } else if (IS (p, VOID_SYMBOL)) {
 322      put_sym (p, !KEYWORD);
 323    } else if (IS (p, REF_SYMBOL)) {
 324      put_sym (p, !KEYWORD);
 325      BLANK;
 326      indent_declarer (NEXT (p));
 327    } else if (IS_FLEX (p)) {
 328      put_sym (p, !KEYWORD);
 329      BLANK;
 330      indent_declarer (NEXT (p));
 331    } else if (IS (p, BOUNDS) || IS (p, FORMAL_BOUNDS)) {
 332      NODE_T *what = NO_NODE;
 333      int pop_ind = A68G_INDENT (ind);
 334      indent_generic_list (SUB (p), &what, ONE_LINER);
 335      A68G_INDENT (ind) = pop_ind;
 336      BLANK;
 337      indent_declarer (NEXT (p));
 338    } else if (IS_STRUCT (p) || IS_UNION (p)) {
 339      NODE_T *pack = NEXT (p);
 340      put_sym (p, !KEYWORD);
 341      BLANK;
 342      indent_pack (pack);
 343    } else if (IS (p, PROC_SYMBOL)) {
 344      NODE_T *q = NEXT (p);
 345      put_sym (p, KEYWORD);
 346      BLANK;
 347      if (IS (q, FORMAL_DECLARERS)) {
 348        indent_pack (SUB (q));
 349        BLANK;
 350        FORWARD (q);
 351      }
 352      indent_declarer (q);
 353      return;
 354    } else if (IS (p, OP_SYMBOL)) {       // Operator plan
 355      NODE_T *q = NEXT (p);
 356      put_sym (p, KEYWORD);
 357      BLANK;
 358      if (IS (q, FORMAL_DECLARERS)) {
 359        indent_pack (SUB (q));
 360        BLANK;
 361        FORWARD (q);
 362      }
 363      indent_declarer (q);
 364      return;
 365    } else if (IS (p, INDICANT)) {
 366      put_sym (p, !KEYWORD);
 367    }
 368  }
 369  
 370  //! @brief Indent conditional.
 371  
 372  void indent_conditional (NODE_T * p)
 373  {
 374    for (; p != NO_NODE; FORWARD (p)) {
 375      if (IS (p, IF_PART) || IS (p, ELIF_IF_PART)) {
 376        NODE_T *what = NO_NODE;
 377        int pop_ind = A68G_INDENT (col);
 378        put_sym (SUB (p), KEYWORD);
 379        BLANK;
 380        A68G_INDENT (ind) = A68G_INDENT (col);
 381        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 382        A68G_INDENT (ind) = pop_ind;
 383        put_nl ();
 384      } else if (IS (p, THEN_PART)) {
 385        NODE_T *what = NO_NODE;
 386        int pop_ind = A68G_INDENT (col);
 387        put_sym (SUB (p), KEYWORD);
 388        BLANK;
 389        A68G_INDENT (ind) = A68G_INDENT (col);
 390        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 391        A68G_INDENT (ind) = pop_ind;
 392        put_nl ();
 393      } else if (IS (p, ELSE_PART)) {
 394        NODE_T *what = NO_NODE;
 395        int pop_ind = A68G_INDENT (col);
 396        put_sym (SUB (p), KEYWORD);
 397        BLANK;
 398        A68G_INDENT (ind) = A68G_INDENT (col);
 399        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 400        A68G_INDENT (ind) = pop_ind;
 401        put_nl ();
 402      } else if (IS (p, ELIF_PART)) {
 403        indent_conditional (SUB (p));
 404      } else if (IS (p, FI_SYMBOL)) {
 405        put_sym (p, KEYWORD);
 406      } else if (IS (p, OPEN_PART)) {
 407        NODE_T *what = NO_NODE;
 408        put_sym (SUB (p), KEYWORD);
 409        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 410      } else if (IS (p, ELSE_OPEN_PART)) {
 411        NODE_T *what = NO_NODE;
 412        BLANK;
 413        put_sym (SUB (p), KEYWORD);
 414        BLANK;
 415        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 416      } else if (IS (p, CHOICE)) {
 417        NODE_T *what = NO_NODE;
 418        BLANK;
 419        put_sym (SUB (p), KEYWORD);
 420        BLANK;
 421        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 422      } else if (IS (p, BRIEF_ELIF_PART)) {
 423        indent_conditional (SUB (p));
 424      } else if (IS_CLOSE_SYMBOL (p)) {
 425        put_sym (p, KEYWORD);
 426      }
 427    }
 428  }
 429  
 430  //! @brief Indent integer case clause.
 431  
 432  void indent_case (NODE_T * p)
 433  {
 434    for (; p != NO_NODE; FORWARD (p)) {
 435      if (IS (p, CASE_PART) || IS (p, OUSE_PART)) {
 436        NODE_T *what = NO_NODE;
 437        int pop_ind = A68G_INDENT (col);
 438        put_sym (SUB (p), KEYWORD);
 439        BLANK;
 440        A68G_INDENT (ind) = A68G_INDENT (col);
 441        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 442        A68G_INDENT (ind) = pop_ind;
 443        put_nl ();
 444      } else if (IS (p, CASE_IN_PART)) {
 445        NODE_T *what = NO_NODE;
 446        int pop_ind = A68G_INDENT (col);
 447        put_sym (SUB (p), KEYWORD);
 448        BLANK;
 449        A68G_INDENT (ind) = A68G_INDENT (col);
 450        indent_generic_list (NEXT_SUB (p), &what, ONE_LINER);
 451        A68G_INDENT (ind) = pop_ind;
 452        put_nl ();
 453      } else if (IS (p, OUT_PART)) {
 454        NODE_T *what = NO_NODE;
 455        int pop_ind = A68G_INDENT (col);
 456        put_sym (SUB (p), KEYWORD);
 457        BLANK;
 458        A68G_INDENT (ind) = A68G_INDENT (col);
 459        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 460        A68G_INDENT (ind) = pop_ind;
 461        put_nl ();
 462      } else if (IS (p, CASE_OUSE_PART)) {
 463        indent_case (SUB (p));
 464      } else if (IS (p, ESAC_SYMBOL)) {
 465        put_sym (p, KEYWORD);
 466      } else if (IS (p, OPEN_PART)) {
 467        NODE_T *what = NO_NODE;
 468        put_sym (SUB (p), KEYWORD);
 469        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 470      } else if (IS (p, ELSE_OPEN_PART)) {
 471        NODE_T *what = NO_NODE;
 472        BLANK;
 473        put_sym (SUB (p), KEYWORD);
 474        BLANK;
 475        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 476      } else if (IS (p, CASE_CHOICE_CLAUSE)) {
 477        NODE_T *what = NO_NODE;
 478        BLANK;
 479        put_sym (SUB (p), KEYWORD);
 480        BLANK;
 481        indent_generic_list (NEXT_SUB (p), &what, ONE_LINER);
 482      } else if (IS (p, CHOICE)) {
 483        NODE_T *what = NO_NODE;
 484        BLANK;
 485        put_sym (SUB (p), KEYWORD);
 486        BLANK;
 487        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 488      } else if (IS (p, BRIEF_OUSE_PART)) {
 489        indent_case (SUB (p));
 490      } else if (IS_CLOSE_SYMBOL (p)) {
 491        put_sym (p, KEYWORD);
 492      }
 493    }
 494  }
 495  
 496  //! @brief Indent conformity clause.
 497  
 498  void indent_conformity (NODE_T * p)
 499  {
 500    for (; p != NO_NODE; FORWARD (p)) {
 501      if (IS (p, CASE_PART) || IS (p, OUSE_PART)) {
 502        NODE_T *what = NO_NODE;
 503        int pop_ind = A68G_INDENT (col);
 504        put_sym (SUB (p), KEYWORD);
 505        BLANK;
 506        A68G_INDENT (ind) = A68G_INDENT (col);
 507        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 508        A68G_INDENT (ind) = pop_ind;
 509        put_nl ();
 510      } else if (IS (p, CONFORMITY_IN_PART)) {
 511        NODE_T *what = NO_NODE;
 512        int pop_ind = A68G_INDENT (col);
 513        put_sym (SUB (p), KEYWORD);
 514        BLANK;
 515        A68G_INDENT (ind) = A68G_INDENT (col);
 516        indent_generic_list (NEXT_SUB (p), &what, ONE_LINER);
 517        A68G_INDENT (ind) = pop_ind;
 518        put_nl ();
 519      } else if (IS (p, OUT_PART)) {
 520        NODE_T *what = NO_NODE;
 521        int pop_ind = A68G_INDENT (col);
 522        put_sym (SUB (p), KEYWORD);
 523        BLANK;
 524        A68G_INDENT (ind) = A68G_INDENT (col);
 525        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 526        A68G_INDENT (ind) = pop_ind;
 527        put_nl ();
 528      } else if (IS (p, CONFORMITY_OUSE_PART)) {
 529        indent_conformity (SUB (p));
 530      } else if (IS (p, ESAC_SYMBOL)) {
 531        put_sym (p, KEYWORD);
 532      } else if (IS (p, OPEN_PART)) {
 533        NODE_T *what = NO_NODE;
 534        put_sym (SUB (p), KEYWORD);
 535        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 536      } else if (IS (p, ELSE_OPEN_PART)) {
 537        NODE_T *what = NO_NODE;
 538        BLANK;
 539        put_sym (SUB (p), KEYWORD);
 540        BLANK;
 541        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 542      } else if (IS (p, CONFORMITY_CHOICE)) {
 543        NODE_T *what = NO_NODE;
 544        BLANK;
 545        put_sym (SUB (p), KEYWORD);
 546        BLANK;
 547        indent_generic_list (NEXT_SUB (p), &what, ONE_LINER);
 548      } else if (IS (p, CHOICE)) {
 549        NODE_T *what = NO_NODE;
 550        BLANK;
 551        put_sym (SUB (p), KEYWORD);
 552        BLANK;
 553        indent_serial (NEXT_SUB (p), ONE_LINER, &what);
 554      } else if (IS (p, BRIEF_CONFORMITY_OUSE_PART)) {
 555        indent_conformity (SUB (p));
 556      } else if (IS_CLOSE_SYMBOL (p)) {
 557        put_sym (p, KEYWORD);
 558      }
 559    }
 560  }
 561  
 562  //! @brief Indent loop.
 563  
 564  void indent_loop (NODE_T * p)
 565  {
 566    int parts = 0, pop_ind = A68G_INDENT (col);
 567    for (; p != NO_NODE; FORWARD (p)) {
 568      if (IS (p, FOR_PART)) {
 569        put_sym (SUB (p), KEYWORD);
 570        BLANK;
 571        put_sym (NEXT_SUB (p), !KEYWORD);
 572        BLANK;
 573        parts++;
 574      } else if (is_one_of (p, FROM_PART, BY_PART, TO_PART, STOP)) {
 575        put_sym (SUB (p), KEYWORD);
 576        BLANK;
 577        indent_statement (NEXT_SUB (p));
 578        BLANK;
 579        parts++;
 580      } else if (IS (p, WHILE_PART)) {
 581        NODE_T *what = NO_NODE;
 582        A68G_INDENT (ind) = pop_ind;
 583        if (parts > 0) {
 584          put_nl ();
 585        }
 586        put_sym (SUB (p), KEYWORD);
 587        BLANK;
 588        A68G_INDENT (ind) = A68G_INDENT (col);
 589        indent_serial (NEXT_SUB (p), !ONE_LINER, &what);
 590        A68G_INDENT (ind) = pop_ind;
 591        parts++;
 592      } else if (is_one_of (p, DO_PART, ALT_DO_PART, STOP)) {
 593        NODE_T *q = SUB (p);
 594        NODE_T *what = NO_NODE;
 595        A68G_INDENT (ind) = pop_ind;
 596        if (parts > 0) {
 597          put_nl ();
 598        }
 599        put_sym (q, KEYWORD);     // DO
 600        BLANK;
 601        A68G_INDENT (ind) = A68G_INDENT (col);
 602        FORWARD (q);
 603        parts = 0;
 604        if (IS (q, SERIAL_CLAUSE)) {
 605          indent_serial (SUB (q), !ONE_LINER, &what);
 606          FORWARD (q);
 607          parts++;
 608        }
 609        if (IS (q, UNTIL_PART)) {
 610          int pop_ind2 = A68G_INDENT (ind);
 611          if (parts > 0) {
 612            put_nl ();
 613          }
 614          put_sym (SUB (q), KEYWORD);
 615          BLANK;
 616          A68G_INDENT (ind) = A68G_INDENT (col);
 617          indent_serial (NEXT_SUB (q), !ONE_LINER, &what);
 618          A68G_INDENT (ind) = pop_ind2;
 619          FORWARD (q);
 620        }
 621        A68G_INDENT (ind) = pop_ind;
 622        put_nl ();
 623        put_sym (q, KEYWORD);     // OD
 624        parts++;
 625      }
 626    }
 627  }
 628  
 629  //! @brief Indent closed clause.
 630  
 631  void indent_closed (NODE_T * p)
 632  {
 633    int units = 0, seps = 0;
 634    count (SUB_NEXT (p), &units, &seps);
 635    if (units <= 3 && seps == (units - 1)) {
 636      put_sym (p, KEYWORD);
 637      if (IS (p, BEGIN_SYMBOL)) {
 638        NODE_T *what = NO_NODE;
 639        BLANK;
 640        indent_serial (SUB_NEXT (p), ONE_LINER, &what);
 641        BLANK;
 642      } else {
 643        NODE_T *what = NO_NODE;
 644        indent_serial (SUB_NEXT (p), ONE_LINER, &what);
 645      }
 646      put_sym (NEXT_NEXT (p), KEYWORD);
 647    } else if (units <= 3 && seps == (units - 1) && IS_OPEN_SYMBOL (p)) {
 648      NODE_T *what = NO_NODE;
 649      put_sym (p, KEYWORD);
 650      indent_serial (SUB_NEXT (p), ONE_LINER, &what);
 651      put_sym (NEXT_NEXT (p), KEYWORD);
 652    } else {
 653      NODE_T *what = NO_NODE;
 654      int pop_ind = A68G_INDENT (col);
 655      put_sym (p, KEYWORD);
 656      if (IS (p, BEGIN_SYMBOL)) {
 657        BLANK;
 658      }
 659      A68G_INDENT (ind) = A68G_INDENT (col);
 660      indent_serial (SUB_NEXT (p), !ONE_LINER, &what);
 661      A68G_INDENT (ind) = pop_ind;
 662      if (IS (NEXT_NEXT (p), END_SYMBOL)) {
 663        put_nl ();
 664      }
 665      put_sym (NEXT_NEXT (p), KEYWORD);
 666    }
 667  }
 668  
 669  //! @brief Indent collateral clause.
 670  
 671  void indent_collateral (NODE_T * p)
 672  {
 673    int units = 0, seps = 0;
 674    NODE_T *what = NO_NODE;
 675    int pop_ind = A68G_INDENT (col);
 676    count_stowed (p, &units, &seps);
 677    if (units <= 3) {
 678      indent_generic_list (p, &what, ONE_LINER);
 679    } else {
 680      indent_generic_list (p, &what, !ONE_LINER);
 681    }
 682    A68G_INDENT (ind) = pop_ind;
 683  }
 684  
 685  //! @brief Indent enclosed clause.
 686  
 687  void indent_enclosed (NODE_T * p)
 688  {
 689    if (IS (p, ENCLOSED_CLAUSE)) {
 690      indent_enclosed (SUB (p));
 691    } else if (IS (p, CLOSED_CLAUSE)) {
 692      indent_closed (SUB (p));
 693    } else if (IS (p, COLLATERAL_CLAUSE)) {
 694      indent_collateral (SUB (p));
 695    } else if (IS (p, PARALLEL_CLAUSE)) {
 696      put_sym (SUB (p), KEYWORD);
 697      indent_enclosed (NEXT_SUB (p));
 698    } else if (IS (p, CONDITIONAL_CLAUSE)) {
 699      indent_conditional (SUB (p));
 700    } else if (IS (p, CASE_CLAUSE)) {
 701      indent_case (SUB (p));
 702    } else if (IS (p, CONFORMITY_CLAUSE)) {
 703      indent_conformity (SUB (p));
 704    } else if (IS (p, LOOP_CLAUSE)) {
 705      indent_loop (SUB (p));
 706    }
 707  }
 708  
 709  //! @brief Indent a literal.
 710  
 711  void indent_literal (char *txt)
 712  {
 713    put_str ("\"");
 714    while (txt[0] != NULL_CHAR) {
 715      if (txt[0] == '\"') {
 716        put_str ("\"\"");
 717      } else {
 718        put_ch (txt[0]);
 719      }
 720      txt++;
 721    }
 722    put_str ("\"");
 723  }
 724  
 725  //! @brief Indent denotation.
 726  
 727  void indent_denotation (NODE_T * p)
 728  {
 729    if (IS (p, ROW_CHAR_DENOTATION)) {
 730      indent_literal (NSYMBOL (p));
 731    } else if (IS (p, LONGETY) || IS (p, SHORTETY)) {
 732      indent_sizety (SUB (p));
 733      indent_denotation (NEXT (p));
 734    } else {
 735      put_sym (p, !KEYWORD);
 736    }
 737  }
 738  
 739  //! @brief Indent label.
 740  
 741  void indent_label (NODE_T * p)
 742  {
 743    for (; p != NO_NODE; FORWARD (p)) {
 744      if (SUB (p) != NULL) {
 745        indent_label (SUB (p));
 746      } else if (IS (p, DEFINING_IDENTIFIER)) {
 747        put_sym (p, !KEYWORD);
 748        put_sym (NEXT (p), KEYWORD);
 749      }
 750    }
 751  }
 752  
 753  //! @brief Indent literal list.
 754  
 755  void indent_collection (NODE_T * p)
 756  {
 757    for (; p != NO_NODE; FORWARD (p)) {
 758      if (IS (p, FORMAT_OPEN_SYMBOL) || IS (p, FORMAT_CLOSE_SYMBOL)) {
 759        put_sym (p, !KEYWORD);
 760      } else if (IS (p, COMMA_SYMBOL)) {
 761        put_sym (p, !KEYWORD);
 762        BLANK;
 763      } else {
 764        indent_format (SUB (p));
 765      }
 766    }
 767  }
 768  
 769  //! @brief Indent format text.
 770  
 771  void indent_format (NODE_T * p)
 772  {
 773    for (; p != NO_NODE; FORWARD (p)) {
 774      if (IS (p, FORMAT_DELIMITER_SYMBOL)) {
 775        put_sym (p, !KEYWORD);
 776      } else if (IS (p, COLLECTION)) {
 777        indent_collection (SUB (p));
 778      } else if (IS (p, ENCLOSED_CLAUSE)) {
 779        indent_enclosed (SUB (p));
 780      } else if (IS (p, LITERAL)) {
 781        indent_literal (NSYMBOL (p));
 782      } else if (IS (p, STATIC_REPLICATOR)) {
 783        indent_denotation (p);
 784      } else if (IS (p, COMMA_SYMBOL)) {
 785        put_sym (p, !KEYWORD);
 786        BLANK;
 787      } else {
 788        if (SUB (p) != NO_NODE) {
 789          indent_format (SUB (p));
 790        } else {
 791          switch (ATTRIBUTE (p)) {
 792          case FORMAT_ITEM_A:
 793          case FORMAT_ITEM_B:
 794          case FORMAT_ITEM_C:
 795          case FORMAT_ITEM_D:
 796          case FORMAT_ITEM_E:
 797          case FORMAT_ITEM_ESCAPE:
 798          case FORMAT_ITEM_F:
 799          case FORMAT_ITEM_G:
 800          case FORMAT_ITEM_H:
 801          case FORMAT_ITEM_I:
 802          case FORMAT_ITEM_J:
 803          case FORMAT_ITEM_K:
 804          case FORMAT_ITEM_L:
 805          case FORMAT_ITEM_M:
 806          case FORMAT_ITEM_MINUS:
 807          case FORMAT_ITEM_N:
 808          case FORMAT_ITEM_O:
 809          case FORMAT_ITEM_P:
 810          case FORMAT_ITEM_PLUS:
 811          case FORMAT_ITEM_POINT:
 812          case FORMAT_ITEM_Q:
 813          case FORMAT_ITEM_R:
 814          case FORMAT_ITEM_S:
 815          case FORMAT_ITEM_T:
 816          case FORMAT_ITEM_U:
 817          case FORMAT_ITEM_V:
 818          case FORMAT_ITEM_W:
 819          case FORMAT_ITEM_X:
 820          case FORMAT_ITEM_Y:
 821          case FORMAT_ITEM_Z: {
 822              put_sym (p, !KEYWORD);
 823              break;
 824            }
 825          }
 826        }
 827      }
 828    }
 829  }
 830  
 831  //! @brief Constant folder - replace constant statement with value.
 832  
 833  BOOL_T indent_folder (NODE_T * p)
 834  {
 835    if (MOID (p) == M_INT) {
 836      A68G_INT k;
 837      A68G_SP = 0;
 838      push_unit (p);
 839      POP_OBJECT (p, &k, A68G_INT);
 840      if (ERROR_COUNT (&A68G_JOB) == 0) {
 841        ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, A68G_LD, VALUE (&k)) >= 0);
 842        put_str (A68G (output_line));
 843        return A68G_TRUE;
 844      } else {
 845        return A68G_FALSE;
 846      }
 847    } else if (MOID (p) == M_REAL) {
 848      A68G_REAL x;
 849      REAL_T conv;
 850      A68G_SP = 0;
 851      push_unit (p);
 852      POP_OBJECT (p, &x, A68G_REAL);
 853  // Mind overflowing or underflowing values.
 854      if (ERROR_COUNT (&A68G_JOB) != 0) {
 855        return A68G_FALSE;
 856      } else if (VALUE (&x) == A68G_REAL_MAX) {
 857        return A68G_FALSE;
 858      } else if (VALUE (&x) == -A68G_REAL_MAX) {
 859        return A68G_FALSE;
 860      } else {
 861        ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "%.*g", A68G_REAL_WIDTH, VALUE (&x)) >= 0);
 862        errno = 0;
 863        conv = strtod (A68G (output_line), NO_REF);
 864        if (errno == ERANGE && conv == 0.0) {
 865          put_str ("0.0");
 866          return A68G_TRUE;
 867        } else if (errno == ERANGE) {
 868          return A68G_FALSE;
 869        } else {
 870          if (strchr (A68G (output_line), '.') == NO_TEXT && strchr (A68G (output_line), 'e') == NO_TEXT && strchr (A68G (output_line), 'E') == NO_TEXT) {
 871            a68g_bufcat (A68G (output_line), ".0", BUFFER_SIZE);
 872          }
 873          put_str (A68G (output_line));
 874          return A68G_TRUE;
 875        }
 876      }
 877    } else if (MOID (p) == M_BOOL) {
 878      A68G_BOOL b;
 879      A68G_SP = 0;
 880      push_unit (p);
 881      POP_OBJECT (p, &b, A68G_BOOL);
 882      if (ERROR_COUNT (&A68G_JOB) != 0) {
 883        return A68G_FALSE;
 884      } else {
 885        ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "%s", (VALUE (&b) ? "TRUE" : "FALSE")) >= 0);
 886        put_str (A68G (output_line));
 887        return A68G_TRUE;
 888      }
 889    } else if (MOID (p) == M_CHAR) {
 890      A68G_CHAR c;
 891      A68G_SP = 0;
 892      push_unit (p);
 893      POP_OBJECT (p, &c, A68G_CHAR);
 894      if (ERROR_COUNT (&A68G_JOB) == 0) {
 895        return A68G_FALSE;
 896      } else if (VALUE (&c) == '\"') {
 897        put_str ("\"\"\"\"");
 898        return A68G_TRUE;
 899      } else {
 900        ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "\"%c\"", (int) VALUE (&c)) >= 0);
 901        return A68G_TRUE;
 902      }
 903    }
 904    return A68G_FALSE;
 905  }
 906  
 907  //! @brief Indent statement.
 908  
 909  void indent_statement (NODE_T * p)
 910  {
 911    if (IS (p, LABEL)) {
 912      int enclos = 0, seps = 0;
 913      indent_label (SUB (p));
 914      FORWARD (p);
 915      count_enclos (SUB (p), &enclos, &seps);
 916      if (enclos == 0) {
 917        BLANK;
 918      } else {
 919        put_nl ();
 920      }
 921    }
 922    if (A68G_INDENT (use_folder) && folder_mode (MOID (p)) && constant_unit (p)) {
 923      if (indent_folder (p)) {
 924        return;
 925      };
 926    }
 927    if (is_coercion (p)) {
 928      indent_statement (SUB (p));
 929    } else if (is_one_of (p, PRIMARY, SECONDARY, TERTIARY, UNIT, LABELED_UNIT, STOP)) {
 930      indent_statement (SUB (p));
 931    } else if (IS (p, ENCLOSED_CLAUSE)) {
 932      indent_enclosed (SUB (p));
 933    } else if (IS (p, DENOTATION)) {
 934      indent_denotation (SUB (p));
 935    } else if (IS (p, FORMAT_TEXT)) {
 936      indent_format (SUB (p));
 937    } else if (IS (p, IDENTIFIER)) {
 938      put_sym (p, !KEYWORD);
 939    } else if (IS (p, CAST)) {
 940      NODE_T *decl = SUB (p);
 941      NODE_T *rhs = NEXT (decl);
 942      indent_declarer (decl);
 943      BLANK;
 944      indent_enclosed (rhs);
 945    } else if (IS (p, CALL)) {
 946      NODE_T *primary = SUB (p);
 947      NODE_T *arguments = NEXT (primary);
 948      NODE_T *what = NO_NODE;
 949      int pop_ind = A68G_INDENT (col);
 950      indent_statement (primary);
 951      BLANK;
 952      indent_generic_list (arguments, &what, ONE_LINER);
 953      A68G_INDENT (ind) = pop_ind;
 954    } else if (IS (p, SLICE)) {
 955      NODE_T *primary = SUB (p);
 956      NODE_T *indexer = NEXT (primary);
 957      NODE_T *what = NO_NODE;
 958      int pop_ind = A68G_INDENT (col);
 959      indent_statement (primary);
 960      indent_generic_list (indexer, &what, ONE_LINER);
 961      A68G_INDENT (ind) = pop_ind;
 962    } else if (IS (p, SELECTION)) {
 963      NODE_T *selector = SUB (p);
 964      NODE_T *secondary = NEXT (selector);
 965      indent_statement (selector);
 966      indent_statement (secondary);
 967    } else if (IS (p, SELECTOR)) {
 968      NODE_T *identifier = SUB (p);
 969      put_sym (identifier, !KEYWORD);
 970      BLANK;
 971      put_sym (NEXT (identifier), !KEYWORD);      // OF
 972      BLANK;
 973    } else if (IS (p, GENERATOR)) {
 974      NODE_T *q = SUB (p);
 975      put_sym (q, !KEYWORD);
 976      BLANK;
 977      indent_declarer (NEXT (q));
 978    } else if (IS (p, FORMULA)) {
 979      NODE_T *lhs = SUB (p);
 980      NODE_T *op = NEXT (lhs);
 981      indent_statement (lhs);
 982      if (op != NO_NODE) {
 983        NODE_T *rhs = NEXT (op);
 984        BLANK;
 985        put_sym (op, !KEYWORD);
 986        BLANK;
 987        indent_statement (rhs);
 988      }
 989    } else if (IS (p, MONADIC_FORMULA)) {
 990      NODE_T *op = SUB (p);
 991      NODE_T *rhs = NEXT (op);
 992      put_sym (op, !KEYWORD);
 993      if (strchr (MONADS, (NSYMBOL (op))[0]) == NO_TEXT) {
 994        BLANK;
 995      }
 996      indent_statement (rhs);
 997    } else if (IS (p, NIHIL)) {
 998      put_sym (p, !KEYWORD);
 999    } else if (IS (p, AND_FUNCTION) || IS (p, OR_FUNCTION)) {
1000      NODE_T *lhs = SUB (p);
1001      NODE_T *op = NEXT (lhs);
1002      NODE_T *rhs = NEXT (op);
1003      indent_statement (lhs);
1004      BLANK;
1005      put_sym (op, !KEYWORD);
1006      BLANK;
1007      indent_statement (rhs);
1008    } else if (IS (p, TRANSPOSE_FUNCTION) || IS (p, DIAGONAL_FUNCTION) || IS (p, ROW_FUNCTION) || IS (p, COLUMN_FUNCTION)) {
1009      NODE_T *q = SUB (p);
1010      if (IS (p, TERTIARY)) {
1011        indent_statement (q);
1012        BLANK;
1013        FORWARD (q);
1014      }
1015      put_sym (q, !KEYWORD);
1016      BLANK;
1017      indent_statement (NEXT (q));
1018    } else if (IS (p, ASSIGNATION)) {
1019      NODE_T *dst = SUB (p);
1020      NODE_T *bec = NEXT (dst);
1021      NODE_T *src = NEXT (bec);
1022      indent_statement (dst);
1023      BLANK;
1024      put_sym (bec, !KEYWORD);
1025      BLANK;
1026      indent_statement (src);
1027    } else if (IS (p, ROUTINE_TEXT)) {
1028      NODE_T *q = SUB (p);
1029      int units, seps;
1030      if (IS (q, PARAMETER_PACK)) {
1031        indent_pack (SUB (q));
1032        BLANK;
1033        FORWARD (q);
1034      }
1035      indent_declarer (q);
1036      FORWARD (q);
1037      put_sym (q, !KEYWORD);      // :
1038      FORWARD (q);
1039      units = 0;
1040      seps = 0;
1041      count (q, &units, &seps);
1042      if (units <= 1) {
1043        BLANK;
1044        indent_statement (q);
1045      } else {
1046        put_nl ();
1047        indent_statement (q);
1048      }
1049    } else if (IS (p, IDENTITY_RELATION)) {
1050      NODE_T *lhs = SUB (p);
1051      NODE_T *op = NEXT (lhs);
1052      NODE_T *rhs = NEXT (op);
1053      indent_statement (lhs);
1054      BLANK;
1055      put_sym (op, !KEYWORD);
1056      BLANK;
1057      indent_statement (rhs);
1058    } else if (IS (p, JUMP)) {
1059      NODE_T *q = SUB (p);
1060      if (IS (q, GOTO_SYMBOL)) {
1061        put_sym (q, !KEYWORD);
1062        BLANK;
1063        FORWARD (q);
1064      }
1065      put_sym (q, !KEYWORD);
1066    } else if (IS (p, SKIP)) {
1067      put_sym (p, !KEYWORD);
1068    } else if (IS (p, ASSERTION)) {
1069      NODE_T *q = SUB (p);
1070      put_sym (q, KEYWORD);
1071      BLANK;
1072      indent_enclosed (NEXT (q));
1073    } else if (IS (p, CODE_CLAUSE)) {
1074      NODE_T *q = SUB (p);
1075      put_sym (q, KEYWORD);
1076      BLANK;
1077      FORWARD (q);
1078      indent_collection (SUB (q));
1079      FORWARD (q);
1080      put_sym (q, KEYWORD);
1081    }
1082  }
1083  
1084  //! @brief Indent identifier declarations.
1085  
1086  void indent_iddecl (NODE_T * p)
1087  {
1088    for (; p != NO_NODE; FORWARD (p)) {
1089      if (IS (p, IDENTITY_DECLARATION) || IS (p, VARIABLE_DECLARATION)) {
1090        indent_iddecl (SUB (p));
1091      } else if (IS (p, QUALIFIER)) {
1092        put_sym (SUB (p), !KEYWORD);
1093        BLANK;
1094      } else if (IS (p, DECLARER)) {
1095        indent_declarer (SUB (p));
1096        BLANK;
1097      } else if (IS (p, DEFINING_IDENTIFIER)) {
1098        NODE_T *q = p;
1099        int pop_ind = A68G_INDENT (ind);
1100        put_sym (q, !KEYWORD);
1101        FORWARD (q);
1102        if (q != NO_NODE) {       // := unit
1103          BLANK;
1104          put_sym (q, !KEYWORD);
1105          BLANK;
1106          FORWARD (q);
1107          indent_statement (q);
1108        }
1109        A68G_INDENT (ind) = pop_ind;
1110      } else if (IS (p, COMMA_SYMBOL)) {
1111        put_sym (p, !KEYWORD);
1112        BLANK;
1113      }
1114    }
1115  }
1116  
1117  //! @brief Indent procedure declarations.
1118  
1119  void indent_procdecl (NODE_T * p)
1120  {
1121    for (; p != NO_NODE; FORWARD (p)) {
1122      if (IS (p, PROCEDURE_DECLARATION) || IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
1123        indent_procdecl (SUB (p));
1124      } else if (IS (p, PROC_SYMBOL)) {
1125        put_sym (p, KEYWORD);
1126        BLANK;
1127        A68G_INDENT (ind) = A68G_INDENT (col);
1128      } else if (IS (p, DEFINING_IDENTIFIER)) {
1129        NODE_T *q = p;
1130        int pop_ind = A68G_INDENT (ind);
1131        put_sym (q, !KEYWORD);
1132        FORWARD (q);
1133        BLANK;
1134        put_sym (q, !KEYWORD);
1135        BLANK;
1136        FORWARD (q);
1137        indent_statement (q);
1138        A68G_INDENT (ind) = pop_ind;
1139      } else if (IS (p, COMMA_SYMBOL)) {
1140        put_sym (p, !KEYWORD);
1141        put_nl ();
1142      }
1143    }
1144  }
1145  
1146  //! @brief Indent operator declarations.
1147  
1148  void indent_opdecl (NODE_T * p)
1149  {
1150    for (; p != NO_NODE; FORWARD (p)) {
1151      if (IS (p, OPERATOR_DECLARATION) || IS (p, BRIEF_OPERATOR_DECLARATION)) {
1152        indent_opdecl (SUB (p));
1153      } else if (IS (p, OP_SYMBOL)) {
1154        put_sym (p, KEYWORD);
1155        BLANK;
1156        A68G_INDENT (ind) = A68G_INDENT (col);
1157      } else if (IS (p, OPERATOR_PLAN)) {
1158        indent_declarer (SUB (p));
1159        BLANK;
1160        A68G_INDENT (ind) = A68G_INDENT (col);
1161      } else if (IS (p, DEFINING_OPERATOR)) {
1162        NODE_T *q = p;
1163        int pop_ind = A68G_INDENT (ind);
1164        put_sym (q, !KEYWORD);
1165        FORWARD (q);
1166        BLANK;
1167        put_sym (q, !KEYWORD);
1168        BLANK;
1169        FORWARD (q);
1170        indent_statement (q);
1171        A68G_INDENT (ind) = pop_ind;
1172      } else if (IS (p, COMMA_SYMBOL)) {
1173        put_sym (p, !KEYWORD);
1174        put_nl ();
1175      }
1176    }
1177  }
1178  
1179  //! @brief Indent priority declarations.
1180  
1181  void indent_priodecl (NODE_T * p)
1182  {
1183    for (; p != NO_NODE; FORWARD (p)) {
1184      if (IS (p, PRIORITY_DECLARATION)) {
1185        indent_priodecl (SUB (p));
1186      } else if (IS (p, PRIO_SYMBOL)) {
1187        put_sym (p, KEYWORD);
1188        BLANK;
1189      } else if (IS (p, DEFINING_OPERATOR)) {
1190        NODE_T *q = p;
1191        put_sym (q, !KEYWORD);
1192        FORWARD (q);
1193        BLANK;
1194        put_sym (q, !KEYWORD);
1195        BLANK;
1196        FORWARD (q);
1197        put_sym (q, !KEYWORD);
1198      } else if (IS (p, COMMA_SYMBOL)) {
1199        put_sym (p, !KEYWORD);
1200        BLANK;
1201      }
1202    }
1203  }
1204  
1205  //! @brief Indent mode declarations.
1206  
1207  void indent_modedecl (NODE_T * p)
1208  {
1209    for (; p != NO_NODE; FORWARD (p)) {
1210      if (IS (p, MODE_DECLARATION)) {
1211        indent_modedecl (SUB (p));
1212      } else if (IS (p, MODE_SYMBOL)) {
1213        put_sym (p, KEYWORD);
1214        BLANK;
1215        A68G_INDENT (ind) = A68G_INDENT (col);
1216      } else if (IS (p, DEFINING_INDICANT)) {
1217        NODE_T *q = p;
1218        int pop_ind = A68G_INDENT (ind);
1219        put_sym (q, !KEYWORD);
1220        FORWARD (q);
1221        BLANK;
1222        put_sym (q, !KEYWORD);
1223        BLANK;
1224        FORWARD (q);
1225        indent_declarer (q);
1226        A68G_INDENT (ind) = pop_ind;
1227      } else if (IS (p, COMMA_SYMBOL)) {
1228        put_sym (p, !KEYWORD);
1229        put_nl ();
1230      }
1231    }
1232  }
1233  
1234  //! @brief Indent declaration list.
1235  
1236  void indent_declist (NODE_T * p, BOOL_T one_liner)
1237  {
1238    for (; p != NO_NODE; FORWARD (p)) {
1239      if (IS (p, IDENTITY_DECLARATION) || IS (p, VARIABLE_DECLARATION)) {
1240        int pop_ind = A68G_INDENT (ind);
1241        indent_iddecl (p);
1242        A68G_INDENT (ind) = pop_ind;
1243      } else if (IS (p, PROCEDURE_DECLARATION) || IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
1244        int pop_ind = A68G_INDENT (ind);
1245        indent_procdecl (p);
1246        A68G_INDENT (ind) = pop_ind;
1247      } else if (IS (p, OPERATOR_DECLARATION) || IS (p, BRIEF_OPERATOR_DECLARATION)) {
1248        int pop_ind = A68G_INDENT (ind);
1249        indent_opdecl (p);
1250        A68G_INDENT (ind) = pop_ind;
1251      } else if (IS (p, PRIORITY_DECLARATION)) {
1252        int pop_ind = A68G_INDENT (ind);
1253        indent_priodecl (p);
1254        A68G_INDENT (ind) = pop_ind;
1255      } else if (IS (p, MODE_DECLARATION)) {
1256        int pop_ind = A68G_INDENT (ind);
1257        indent_modedecl (p);
1258        A68G_INDENT (ind) = pop_ind;
1259      } else if (IS (p, COMMA_SYMBOL)) {
1260        put_sym (p, !KEYWORD);
1261        if (one_liner) {
1262          BLANK;
1263        } else {
1264          put_nl ();
1265        }
1266      } else {
1267        indent_declist (SUB (p), one_liner);
1268      }
1269    }
1270  }
1271  
1272  //! @brief Indent serial clause.
1273  
1274  void indent_serial (NODE_T * p, BOOL_T one_liner, NODE_T ** what)
1275  {
1276    for (; p != NO_NODE; FORWARD (p)) {
1277      if (IS (p, UNIT) || IS (p, LABELED_UNIT)) {
1278        int pop_ind = A68G_INDENT (col);
1279        (*what) = p;
1280        indent_statement (p);
1281        A68G_INDENT (ind) = pop_ind;
1282      } else if (IS (p, DECLARATION_LIST)) {
1283        (*what) = p;
1284        indent_declist (p, one_liner);
1285      } else if (IS (p, SEMI_SYMBOL)) {
1286        put_sym (p, !KEYWORD);
1287        if (!one_liner) {
1288          put_nl ();
1289          if ((*what) != NO_NODE && IS ((*what), DECLARATION_LIST)) {
1290  //        put_nl ();
1291          }
1292        } else {
1293          BLANK;
1294        }
1295      } else if (IS (p, EXIT_SYMBOL)) {
1296        if (NPRAGMENT (p) == NO_TEXT) {
1297          BLANK;
1298        }
1299        put_sym (p, !KEYWORD);
1300        if (!one_liner) {
1301          put_nl ();
1302        } else {
1303          BLANK;
1304        }
1305      } else {
1306        indent_serial (SUB (p), one_liner, what);
1307      }
1308    }
1309  }
1310  
1311  //! @brief Do not pretty-print the environ.
1312  
1313  void skip_environ (NODE_T * p)
1314  {
1315    for (; p != NO_NODE; FORWARD (p)) {
1316      if (LINE_NUMBER (p) == 0) {
1317        pretty_pragment (p, !KEYWORD);
1318        skip_environ (SUB (p));
1319      } else {
1320        NODE_T *what = NO_NODE;
1321        indent_serial (p, !ONE_LINER, &what);
1322      }
1323    }
1324  }
1325  
1326  //! @brief Indenter driver.
1327  
1328  void indenter (MODULE_T * q)
1329  {
1330    A68G_INDENT (ind) = 1;
1331    A68G_INDENT (col) = 1;
1332    A68G_INDENT (indentation) = OPTION_INDENT (q);
1333    A68G_INDENT (use_folder) = OPTION_FOLD (q);
1334    FILE_PRETTY_FD (q) = open (FILE_PRETTY_NAME (q), O_WRONLY | O_CREAT | O_TRUNC, A68G_PROTECTION);
1335    ABEND (FILE_PRETTY_FD (q) == -1, ERROR_ACTION, __func__);
1336    FILE_PRETTY_OPENED (q) = A68G_TRUE;
1337    A68G_INDENT (fd) = FILE_PRETTY_FD (q);
1338    skip_environ (TOP_NODE (q));
1339    ASSERT (close (A68G_INDENT (fd)) == 0);
1340    FILE_PRETTY_OPENED (q) = A68G_FALSE;
1341  }
     


© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)