home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / fweb153.zip / fweb-1.53 / web / prod.web < prev    next >
Text File  |  1995-09-23  |  121KB  |  5,881 lines

  1. @z --- prod.web ---
  2.  
  3. FWEB version 1.53 (September 23, 1995)
  4.  
  5. Based on version 0.5 of S. Levy's CWEB [copyright (C) 1987 Princeton University]
  6.  
  7. @x-----------------------------------------------------------------------------
  8.  
  9. \Title{PROD.WEB} % Productions for the FWEAVE processor.
  10.  
  11. @c
  12.  
  13. @* INTRODUCTION.
  14. In order to accomodate memory-starved personal computers, the productions
  15. have been split off from the main part of \FWEAVE.
  16.  
  17. @d _PROD_h
  18.  
  19. @A 
  20. @<Possibly split into parts@>@;
  21.  
  22. @<Include files@>@;
  23. @<Typedef declarations@>@;
  24. @<Prototypes@>@;
  25. @<Global variables@>@;
  26.  
  27. /* For pc's, the file is split into two compilable parts using the
  28. compiler-line macro |part|, which must equal either~1 or~2. */
  29. #if(part != 2)
  30.     @<Part 1@>@;
  31. #endif /* Part 1 */
  32.  
  33. #if(part != 1)
  34.     @<Part 2@>@;
  35. #endif /* Part 2 */
  36.  
  37. @I typedefs.hweb
  38.  
  39. @
  40. @<Include...@>=
  41. #include "map.h"
  42.  
  43. @ The function prototypes must appear before the global variables.
  44. @<Proto...@>=
  45.  
  46. #include "p_type.h"
  47.  
  48. @I xrefs.hweb
  49. @I tokens.hweb
  50.  
  51. @* PARSING.  The most intricate part of \.{WEAVE} is its mechanism for
  52. converting \cee-like code into \TeX\ code, and we might as well plunge into
  53. this aspect of the program now. A ``bottom up'' approach is used to parse
  54. the \cee-like material, since \.{WEAVE} must deal with fragmentary
  55. constructions whose overall ``part of speech'' is not known.
  56.  
  57. At the lowest level, the input is represented as a sequence of entities
  58. that we shall call {\it scraps}, where each scrap of information consists
  59. of two parts, its {\it category} and its {\it translation}. The category is
  60. essentially a syntactic class, and the translation is a token list that
  61. represents \TeX\ code. Rules of syntax and semantics tell us how to combine
  62. adjacent scraps into larger ones, and if we are lucky an entire \cee\ text
  63. that starts out as hundreds of small scraps will join together into one
  64. gigantic scrap whose translation is the desired \TeX\ code. If we are
  65. unlucky, we will be left with several scraps that don't combine; their
  66. translations will simply be output, one by one.
  67.  
  68. The combination rules are given as context-sensitive productions that are
  69. applied from left to right. Suppose that we are currently working on the
  70. sequence of scraps $s_1\,s_2\ldots s_n$. We try first to find the longest
  71. production that applies to an initial substring $s_1\,s_2\ldots\,$; but if
  72. no such productions exist, we find to find the longest production
  73. applicable to the next substring $s_2\,s_3\ldots\,$; and if that fails, we
  74. try to match $s_3\,s_4\ldots\,$, etc.
  75.  
  76. A production applies if the category codes have a given pattern. For
  77. example, one of the productions is $$\hbox{|expr| |binop| |expr| $\RA$
  78. |expr|}$$ and it means that three consecutive scraps whose respective
  79. categories are |expr|, |binop|, and |expr| are con\-verted to one scraps
  80. whose category is |expr|.  The scraps are simply concatenated.  The case of
  81. $$\hbox{|expr| |comma| |expr| $\RA$ |expr|}$$ is only slightly more
  82. complicated: here the resulting |expr| scrap consists not only of the three
  83. original scraps, but also of the tokens~|opt| and~9 between the |comma| and
  84. the following |expr|.  In the \TeX\ file, this will specify an additional
  85. thin space after the comma, followed by an optional line break with penalty~90.
  86.  
  87. At each opportunity the longest possible production is applied: for
  88. example, if the current sequence of scraps is |struct_like| |expr| |lbrace|
  89. this is transformed into a |struct_hd| by rule~31, but if the sequence is
  90. |struct_like| |expr| followed by anything other than |lbrace| only two
  91. scraps are used (by rule~32) to form an |int_like|.
  92.  
  93. @I ccodes.hweb
  94.  
  95. @ For debugging, we need to append a newline to the output of certain
  96. routines so the output gets flushed.
  97.  
  98. @d DFLUSH if(dflush) puts("");
  99.  
  100. @<Glob...@>=
  101.  
  102. IN_PROD boolean dflush PSET(NO); // Turn this on from debugger.
  103.  
  104. @ The following function symbolically prints out a category. (In using the
  105. |OUT1| macro, we take advantage of the fact that the \.{\#}~operator does
  106. not put a second set of quotes around a string. By enclosing the |name|
  107. arguments in quotes, we keep \FWEAVE\ from getting confused about the part
  108. of speech under discussion; it's not used to seeing a reserved word in the
  109. location of an argument.)
  110.  
  111. @m OUT(cs) case cs: printf(#*cs); @~ break@;
  112. @m OUT1(cs,name) case cs: printf(#*name); @~ break@;
  113.  
  114. @<Part 1@>=
  115. #ifdef DEBUG
  116.  
  117. @[SRTN 
  118. prn_cat FCN((c))
  119.     eight_bits c C1("Category.")@;
  120. {
  121.   switch(c) 
  122.     {
  123.     OUT1(language_scrap,"@@L");
  124.     OUT(expr);
  125.     OUT1(exp_op,"^^");
  126.     OUT1(_EXPR,$_EXPR); @~ OUT1(EXPR_,$EXPR_); @~ OUT1(_EXPR_,$_EXPR_);
  127.     OUT(new_like);
  128.     OUT(stmt);
  129.     OUT(decl);
  130.     OUT(decl_hd);
  131.     OUT1(Decl_hd,$Decl_hd);
  132.     OUT(struct_hd);
  133.     OUT(functn);
  134.     OUT(fn_decl);
  135.     OUT(fcn_hd);
  136.     OUT1(else_like,"else");
  137.     OUT1(ELSE_like,ELSE);
  138.     OUT(if_hd);
  139.     OUT(IF_top);
  140.     OUT(else_hd);
  141.     OUT(for_hd);
  142.     OUT(unop);
  143.     OUT1(UNOP,$UNOP_ @e);
  144.     OUT(binop);
  145.     OUT1(BINOP,@e $_BINOP_ @e);
  146.     OUT(unorbinop);
  147.     OUT1(semi,";");
  148.     OUT1(colon,":");
  149.     OUT1(comma,`,`);
  150.     OUT1(COMMA,@e $_COMMA_ @e);
  151.     OUT1(question,"?");
  152.     OUT(tag);
  153.     OUT(cast);
  154.     OUT1(lpar,"(");
  155.     OUT1(rpar,")");
  156.     OUT1(lbracket,"[");
  157.     OUT1(rbracket,"]");
  158.     OUT1(lbrace,"{");
  159.     OUT1(rbrace,"}");
  160.     OUT(common_hd);
  161.     OUT(read_hd);
  162.     OUT1(slash_like,"slash");
  163.     OUT1(private_like, "private");
  164.     OUT(slashes);
  165.     OUT1(lproc,"#{");
  166.     OUT(LPROC);
  167.     OUT1(rproc,"#}");
  168.     OUT1(ignore_scrap,"ignore");
  169.  
  170.     OUT1(define_like,define);
  171.     OUT(no_order);
  172.     OUT1(do_like,"do");
  173.     OUT1(while_do, "while");
  174.     OUT1(Rdo_like,Rdo);
  175.     OUT1(if_like,"if");
  176.     OUT1(IF_like,IF);
  177.     OUT1(for_like,"for");
  178.     OUT1(program_like,program);
  179.     OUT1(int_like,int);
  180.     OUT(modifier);
  181.     OUT1(huge_like,"huge");
  182.     OUT1(CASE_like,CASE);
  183.     OUT1(case_like,"case");
  184.     OUT1(sizeof_like,sizeof @e);
  185.     OUT1(op_like,"op");
  186.     OUT1(proc_like,"proc");
  187.     OUT1(class_like,"class");
  188.     OUT1(struct_like,"struct");
  189.     OUT1(typedef_like,"typedef");
  190.     OUT1(imp_reserved,"imp_rsrvd");
  191.     OUT1(extern_like,"extern");
  192.     OUT1(common_like,common);
  193.     OUT1(read_like,read);
  194.     OUT1(entry_like,entry);
  195.     OUT1(implicit_like,implicit);
  196.     OUT(implicit_hd);
  197.     OUT(built_in);
  198.     OUT1(endif_like,endif);
  199.     OUT1(end_like,end);
  200.     OUT1(END_like,END);
  201.     OUT(END_stmt);
  202.     OUT1(go_like,go);
  203.     OUT1(newline,"\n");
  204.     OUT(label);
  205.     OUT(space);
  206.     OUT1(until_like,until);
  207.     OUT(template);
  208.     OUT(langle);
  209.     OUT(rangle);
  210.     OUT(tstart);
  211.     OUT(tlist);
  212.     OUT(namespace);
  213.     OUT(virtual);
  214.     OUT1(reference,ref);
  215.  
  216.     OUT1(0,zero);
  217.     default: printf("UNKNOWN"); @~ break;
  218.     }
  219.  
  220. DFLUSH;
  221. }
  222.  
  223. #endif /* |DEBUG| */
  224.  
  225. @I output.hweb
  226.  
  227. @ Here is a table of all the productions. The reader can best get a feel for
  228. @^productions, table of@>
  229. how they work by trying them out by hand on small examples; no amount of
  230. explanation will be as effective as watching the rules in action.  Parsing
  231. can also be watched by debugging with~`\.{@@2}' or by using the
  232. command-line option ``\.{-2}''.  [Please see file
  233. \.{examples/prod.web}.]
  234.  
  235. @i scraps.hweb
  236.  
  237. @ This dummy module keeps \FTANGLE\ from complaining. (It's needed only by
  238. \FWEAVE.)
  239.  
  240.  
  241. @<Rest of |trans_plus| union@>=
  242.  
  243. @ The following functions prints a token list. It is intended to be called
  244. from the debugger.
  245.  
  246. @<Part 1@>=
  247. #ifdef DEBUG
  248.  
  249. SRTN 
  250. prn_text FCN((p))
  251.     text_pointer p C1("The token list.")@;
  252. {
  253.   token_pointer j; /* index into |tok_mem| */
  254.   sixteen_bits r; /* remainder of token after the flag has been stripped off */
  255.  
  256.   if (p>=text_ptr) printf("BAD");
  257.   else for (j=*p; j<*(p+1); j++) 
  258.     {
  259.         r = (sixteen_bits)(*j % id_flag);
  260.  
  261.         switch (*j/id_flag) 
  262.         {
  263.       case 1: printf("\\\\{"); prn_id((name_dir+r)); printf("}"); break;
  264.     /* |id_flag| */
  265.       case 2: printf("\\&{"); prn_id((name_dir+r)); printf("}"); break;
  266.     /* |res_flag| */
  267.       case 3: printf("<"); prn_id((name_dir+r)); printf(">"); break;
  268.         /* |mod_flag| */
  269.       case 4: printf("[[%d]]",r); break; /* |tok_flag| */
  270.       case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
  271.       default: @<Print token |r| in symbolic form@>;
  272.         }
  273.       }
  274.  
  275. DFLUSH;
  276. }
  277.  
  278. #endif /* |DEBUG| */
  279.  
  280. @<Print token |r|...@>=
  281.  
  282. switch (r) 
  283.     {
  284.   case math_bin: printf("\\mathbin}"); @~ break;
  285.   case math_rel: printf("\\mathrel}"); @~ break;
  286.   case big_cancel: printf("[ccancel]"); @~ break;
  287.   case cancel: printf("[cancel]"); @~ break;
  288.   case indent: printf("[indent]"); @~ break;
  289.   case outdent: printf("[outdent]"); @~ break;
  290.   case backup: printf("[backup]"); @~ break;
  291.   case opt: printf("[opt]"); @~ break;
  292.   case break_space: printf("[break]"); @~ break;
  293.   case force: printf("[force]"); @~ break;
  294.   case big_force: printf("[fforce]"); @~ break;
  295.   case end_translation: printf("[quit]"); @~ break;
  296.   default: putxchar(XCHR(r));
  297.     }
  298.  
  299. @ The production rules listed above are embedded directly into the
  300. \.{WEAVE} program, since it is easier to do this than to write an
  301. interpretive system that would handle production systems in general.
  302. Several macros are defined here so that the program for each production is
  303. fairly short.
  304.  
  305. All of our productions conform to the general notion that some~|k|
  306. consecutive scraps starting at some position~|j| are to be replaced by a
  307. single scrap of some category~|c| whose translations is composed from the
  308. translations of the disappearing scraps. After this production has been
  309. applied, the production pointer~|pp| should change by an amount~|d|. Such a
  310. production can be represented by the quadruple |(j,k,c,d)|. For example,
  311. the production `|expr@,comma@,expr| $\RA$ |expr|' would be represented by
  312. `|(pp,3,expr,-2)|'; in this case the pointer |pp| should decrease by~2
  313. after the production has been applied, because some productions with |expr|
  314. in their second or third positions might now match, but no productions have
  315. |expr| in the fourth position of their left-hand sides. Note that the value
  316. of~|d| is determined by the whole collection of productions, not by an
  317. individual one.  The determination of~|d| has been done by hand in each
  318. case, based on the full set of productions but not on the grammar of the
  319. language or on the rules for constructing the initial scraps.
  320.  
  321. We also attach a serial number of each production, so that additional
  322. information is available when debugging. For example, the program below
  323. contains the statement `|REDUCE(pp,3,expr,-2,4)|' when it implements the
  324. production just mentioned.
  325.  
  326. Before calling |reduce|, the program should have appended the tokens of the
  327. new translation to the |tok_mem| array. We commonly want to append copies
  328. of several existing translations, and macros are defined to simplify these
  329. common cases. For example, |b_app2(pp)| will append the translations of
  330. two consecutive scraps, |pp->trans| and |(pp+1)->trans|, to the current
  331. token list. If the entire new translation is formed in this way, we write
  332. `|SQUASH(j,k,c,d)|' instead of `|REDUCE(j,k,c,d)|'. For example,
  333. `|SQUASH(pp,3,expr,-2,3)|' is an abbreviation for `|b_app3(pp);
  334. REDUCE(pp,3,math,-2,3)|'.
  335.  
  336. The code below is an exact translation of the production rules into~C
  337. using such macros, and the reader should have no difficulty understanding
  338. the format by comparing the code with the symbolic productions as they were
  339. listed earlier.
  340.  
  341. To understand the routines that append tokens or scraps in detail, we must
  342. discuss the concept of \It{mathness}. This is used to determine how to
  343. enclose things in dollar signs---i.e., what things should be treated in
  344. math mode. 
  345.  
  346. Routines such as |app| or |app_str| append stuff to the list without
  347. changing the mathness.
  348.  
  349. Routines such as |b_app| or |b_app1| (the 'b' stands for 'big')
  350. provisionally change the mathness depending on what's come before and
  351. what's being appended.
  352.  
  353. Three flags handle the mathness. |cur_mathness| is the mathness at this
  354. point in the construction. |ini_mathness| is the initial mathness of the
  355. stuff that's been appended so far. |last_mathness| is the mathness of the
  356. last stuff that's been appended. (|cur_mathness| and |last_mathness| appear
  357. to be redundant, but we're not changing the code right now.)
  358.  
  359. The next macros \It{big\_appn} append $n$~consective tokens.
  360.  
  361. @D b_app2(a) b_app1(a); @~ b_app1(a+1)
  362. @D b_app3(a) b_app2(a); @~ b_app1(a+2)
  363. @D b_app4(a) b_app3(a); @~ b_app1(a+3)
  364.  
  365. @<Global...@>=
  366.  
  367. IN_PROD int cur_mathness, ini_mathness, last_mathness;
  368.  
  369. @ Append an entire string, converting to |ASCII| if necessary. (Don't
  370. change the mathness.)
  371.  
  372. @<Part 1@>=@[
  373.  
  374. SRTN 
  375. app_str FCN((s))
  376.     CONST outer_char HUGE *s C1("String to be appended.")@;
  377. while (*s) app(XORD(*(s++)));
  378. }
  379.  
  380. SRTN 
  381. app_ASCII_str FCN((s))
  382.     CONST ASCII HUGE *s C1("")@;
  383. {
  384. while(*s) app(*s++);
  385. }
  386.  
  387. @ Append a token, possibly changing the mathness.
  388.  
  389. @<Part 1@>=@[
  390.  
  391. SRTN 
  392. b_app FCN((a))
  393.     Token a C1("Token to be appended.")@;
  394. {
  395. if (a==@' ' || (a>=big_cancel && a<=big_force))
  396.     {/* Appending a non-math token, including a space. */
  397.     if (cur_mathness ==maybe_math) ini_mathness=no_math;
  398.     else if (cur_mathness==yes_math) app(@'$'); /* End math    mode. */ 
  399.  
  400.     cur_mathness=last_mathness=no_math;
  401.     }
  402. else 
  403.     { /* Append a math token. (Tokens can't be |maybe_math|.) */
  404.     if (cur_mathness==maybe_math) ini_mathness=yes_math;
  405.     else if (cur_mathness==no_math) app(@'$'); /* Begin math mode. */
  406.  
  407.     cur_mathness=last_mathness=yes_math;
  408. }
  409.  
  410. app(a);
  411. }
  412.  
  413. @ Append an entire scrap, possibly changing the mathness. The mathness for
  414. scraps is stored in an |eight_bits| in the form |4*last_mathness +
  415. ini_mathness|. 
  416.  
  417. @<Part 1@>=@[
  418.  
  419. SRTN 
  420. b_app1 FCN((a))
  421.     scrap_pointer a C1("Scrap to be appended.")@;
  422. {
  423. switch (a->mathness % 4) 
  424.     { /* Left boundary (|ini_mathness|) of the current scrap. */
  425.   case no_math:
  426.         if (cur_mathness==maybe_math) 
  427.         ini_mathness = no_math;
  428.         else if (cur_mathness==yes_math) 
  429.         APP_STR("{}$"); /* End math mode. (The braces take care of
  430. ending the math part with something like a~$+$.) */
  431.     
  432.         cur_mathness = last_mathness = a->mathness / 4; 
  433.         /* Right boundary (|last_mathness|) */
  434.         break;
  435.  
  436.   case yes_math:
  437.         if (cur_mathness==maybe_math) 
  438.         ini_mathness=yes_math;
  439.         else if (cur_mathness==no_math) 
  440.         APP_STR("${}"); /* Begin math mode.  (The braces take care
  441. of beginning the math part with something like a~$+$.) */
  442.  
  443.         cur_mathness = last_mathness = a->mathness / 4; 
  444.         /* Right boundary (|last_mathness|) */
  445.         break;
  446.  
  447.   case maybe_math: 
  448.     break; /* No changes */ 
  449.       }
  450.  
  451. app(a->trans + tok_flag - tok_start);
  452. }
  453.  
  454. @ Let us consider the big switch for productions now, before looking at its
  455. context. We want to design the program so that this switch works, so we
  456. might as well not keep ourselves in suspense about exactly what code needs
  457. to be provided with a proper environment.
  458.  
  459. \Ratfor\ and \Fortran\ are treated as two dialects of the same language,
  460. because almost all of the rules are the same. The most important exception
  461. is in the \&{if} statements.
  462.  
  463. The first thing we do is to process any language scrap.  Such scraps begin
  464. with |begin_language|, then the language number as the next token.  We use
  465. that token to reset the language.
  466.  
  467. If it's not a language scrap, we gobble up any |ignore_scrap|. For reasons
  468. that are now obscure, we regress by $-2$ after that. This doesn't work
  469. quite right; the logic of some of the |if| statements gets screwed up if
  470. there's a comment in the wrong place.
  471.  
  472. @<Match a production at |pp|, or increase |pp| if there is no match@>= 
  473. {
  474. if(cat0 == language_scrap)
  475.     {
  476.     language = lan_enum(get_language(pp->trans)); /* Get language from
  477. language~\#. */
  478.     ini0_language(); // Reset params like |auto_semi|.
  479.     SQUASH(pp,1,ignore_scrap,-1,0);
  480.     }
  481. else if(cat1==ignore_scrap) SQUASH(pp,2,cat0,-2,0);//Gobble an |ignore_scrap|.
  482. @% else if(cat0==ignore_scrap) SQUASH(pp,2,cat1,0,0); // Screws language cmd.
  483. else switch(language)
  484.         {
  485.           case NO_LANGUAGE:
  486.         CONFUSION("match production","Language isn't defined");
  487.  
  488.        case C: 
  489.        case C_PLUS_PLUS:
  490.         C_productions();
  491.         break;
  492.  
  493.        case RATFOR:
  494.        case RATFOR_90:
  495.         if(!RAT_OK("(translate)"))
  496.             CONFUSION("match production",
  497.                 "Language shouldn't be Ratfor here");
  498.  
  499.        case FORTRAN:
  500.        case FORTRAN_90:        
  501.         R_productions();
  502.         break;
  503.  
  504.        case LITERAL:
  505.         V_productions();
  506.         break;
  507.  
  508.        case TEX:
  509.         X_productions();
  510.         break;
  511.  
  512.        case NUWEB_OFF:
  513.        case NUWEB_ON:
  514.         CONFUSION("match a production","Invalid language");
  515.         }
  516.  
  517. pp++; // if no match was found, we move to the right and try again.
  518. }
  519.  
  520. @<Part 1@>=@[
  521. int 
  522. get_language FCN((xp))
  523.     text_pointer xp C1("")@;
  524. {
  525. token_pointer tp,tp1;
  526.  
  527. tp = *xp;
  528. tp1 = *(xp+1) - 1; /* The |-1| is because we should always have the
  529.     combination |begin_language| followed by the language number. */
  530.  
  531. while(tp < tp1)
  532.     if(*tp++ == begin_language) return *tp;
  533.  
  534. return CONFUSION("get_language",
  535.     "Can't find |begin_language| token in language_scrap");
  536. }
  537.  
  538. @* PRODUCTIONS for C. The productions have been made into individual
  539. functions to accomodate memory-starved pc's.
  540.  
  541. @<Part 1@>=@[
  542.  
  543. SRTN 
  544. C_productions(VOID)
  545. {
  546. switch (pp->cat) 
  547.     {
  548.     case ignore_scrap:  @<CASES for |ignore_scrap| (C)@>@; break;
  549.     case built_in: @<CASES for |built_in| (R)@>@; @~ break;
  550.     case expr: @<CASES for |expr| (C)@>@; @~ break;
  551.     case exp_op: @<CASES for |exp_op| (R)@>@; @~ break;
  552.     case _EXPR: @<CASES for |_EXPR| (C)@>@; @~ break;
  553.     case _EXPR_: @<CASES for |_EXPR_| (C)@>@; @~ break;
  554.     case EXPR_: @<CASES for |EXPR_| (C)@>@; @~ break;
  555.     case new_like: @<CASES for |new_like| (C)@>@; @~ break;
  556.     case lpar: @<CASES for |lpar| (C)@>@; @~ break;
  557.     case lbracket: @<CASES for |lbracket| (C)@>@; @~ break;
  558.     case rbracket: @<CASES for |rbracket| (C)@>@; @~ break;
  559.     case question: @<CASES for |question| (C)@>@; @~ break;
  560.     case unop: @<CASES for |unop| (C)@>@; @~ break;
  561.     case UNOP: @<CASES for |UNOP| (C)@>@; @~ break;
  562.     case unorbinop: @<CASES for |unorbinop| (C)@>@; @~ break;
  563.     case binop: @<CASES for |binop| (C)@>@; @~ break;
  564.     case BINOP: @<CASES for |BINOP| (C)@>@; @~ break;
  565.     case COMMA: @<CASES for |COMMA| (C)@>@; @~ break;
  566.     case cast: @<CASES for |cast| (C)@>@; @~ break;
  567.     case sizeof_like: @<CASES for |sizeof_like| (C)@>@; @~ break;
  568.     case int_like: @<CASES for |int_like| (C)@>@; @~ break;
  569.     case extern_like: @<CASES for |extern_like| (C)@>@; @~ break;
  570.     case modifier: @<CASES for |modifier| (C)@>@; @~ break;
  571.     case huge_like: @<CASES for |huge_like| (C)@>@; @~ break;
  572.     case decl_hd: @<CASES for |decl_hd| (C)@>@; @~ break;
  573.     case decl: @<CASES for |decl| (C)@>@; @~ break;
  574.     case typedef_like: @<CASES for |typedef_like| (C)@>@; @~ break;
  575.     case imp_reserved: @<CASES for |imp_reserved| (C)@>@; @~ break;
  576.     case op_like: @<CASES for |op_like| (C)@>@; @~ break;
  577.     case class_like: @<CASES for |class_like| (C)@>@; @~ break;
  578.     case struct_like: @<CASES for |struct_like| (C)@>@; @~ break;
  579.     case struct_hd: @<CASES for |struct_hd| (C)@>@; @~ break;
  580.     case fn_decl: @<CASES for |fn_decl| (C)@>@; @~ break;
  581.     case functn: @<CASES for |functn| (C)@>@; @~ break;
  582.     case lbrace: @<CASES for |lbrace| (C)@>@; @~ break;
  583.     case do_like: @<CASES for |do_like| (C)@>@; @~ break;
  584.     case while_do: @<CASES for |while_do| (C)@>@; @~ break;
  585.     case if_like: @<CASES for |if_like| (C)@>@; @~ break;
  586.     case IF_like: @<CASES for |IF_like| (C)@>@; @~ break;
  587.     case IF_top: @<CASES for |IF_top| (C)@>@; @~ break;
  588.     case for_like: @<CASES for |for_like| (C)@>@; @~ break;
  589.     case for_hd: @<CASES for |for_hd| (C)@>@; @~ break;
  590.     case else_like: @<CASES for |else_like| (C)@>@; @~ break;
  591. @#if(0)
  592.     case ELSE_like: @<CASES for |ELSE_like| (C)@>@; @~ break;
  593. @#endif
  594.     case if_hd: @<CASES for |if_hd| (C)@>@; @~ break;
  595.     case else_hd: @<CASES for |else_hd| (C)@>@; @~ break;
  596.     case case_like: @<CASES for |case_like| (C)@>@; @~ break;
  597.     case stmt: @<CASES for |stmt| (C)@>@; @~ break;
  598.     case tag: @<CASES for |tag| (C)@>@; @~ break;
  599.     case semi: @<CASES for |semi| (C)@>@; @~ break;
  600.     case lproc: @<CASES for |lproc| (C)@>@; @~ break;
  601.     case LPROC: @<CASES for |LPROC| (C)@>@; @~ break;
  602.     case space: @<CASES for |space| (C)@>@; @~ break;
  603.  
  604.     case template: @<CASES for |template| (C++)@>@; @~ break;
  605.     case langle: @<CASES for |langle| (C++)@>@; @~ break;
  606.     case rangle: @<CASES for |rangle| (C++)@>@; @~ break;
  607.     case tstart: @<CASES for |tstart| (C++)@>@; @~ break;
  608.     case tlist: @<CASES for |tlist| (C++)@>@; @~ break;
  609.  
  610.     case virtual: @<CASES for |virtual| (C++)@>@; @~ break;
  611.     case reference: @<CASES for |reference| (C++)@>@; @~ break;
  612.     case namespace: @<CASES for |namespace| (C++)@>@; @~ break;
  613.   }
  614. }
  615.  
  616. @ In~C, new specifier names can be defined via |typedef|, and we want
  617. to make the parser recognize future ocurrences of the identifier thus
  618. defined as specifiers.  This is done by the procedure |make_reserved|,
  619. which changes the |ilk| of the relevant identifier. (One difficulty with
  620. this solution is that it is implemented in phase~2, so if one uses an
  621. identifier before it is actually |typedef|'d, it won't typeset properly. In
  622. these cases, an explicit~\.{@@f} is required as well.)
  623.  
  624. The original \CWEB\ design of |make_reserved| didn't handle a situation such as
  625. |typedef int (*I)()|, because |I|~was inside parentheses. The procedure has
  626. been augmented to handle this situation by following the indirection chain
  627. to the bitter end.
  628.  
  629. @<Part 1@>=@[
  630.  
  631. SRTN 
  632. make_reserved FCN((p)) /* Make the first identifier in |p->trans| like
  633.                 |int| */ 
  634.     scrap_pointer p C1("")@;
  635. {
  636. sixteen_bits tok_value = first_id(p->trans); 
  637.     // The first identifier, plus its flag.
  638. name_pointer pname = name_dir + tok_value - id_flag;
  639.  
  640. if(!tok_value || tok_value==@'(') 
  641.     return; // Emergency return; no    identifier found.
  642.  
  643. if(DEFINED_TYPE(pname) == M_MACRO || DEFINED_TYPE(pname) == D_MACRO)
  644.     return; // Don't |typedef| macro names.
  645.  
  646. /* Change categories of all future occurrences of the identifier. */
  647.   for (; p<=scrp_ptr; p++) 
  648.     {
  649.         if (p->cat==expr) 
  650.         {
  651.             if (**(p->trans)==tok_value) 
  652.             {
  653.             p->cat=int_like;
  654.             **(p->trans)+=res_flag-id_flag; // Mark as reserved.
  655.                 }
  656.         }
  657.       }
  658.  
  659. pname->ilk = int_like;
  660. pname->reserved_word |= (boolean)language;
  661.  
  662. if(mark_defined.typedef_name)
  663.     {
  664.     pname->defined_in(language) = module_count;
  665.     SET_TYPE(pname,TYPEDEF_NAME);
  666.     }
  667. }
  668.  
  669. @ This function hunts through a translation until it finds the first
  670. identifier, if there is one.
  671.  
  672. @d FIRST_ID(p) ( ((tok0=first_id(p->trans)) && tok0!=@'(') ? name_dir + tok0 -
  673.         id_flag : name_dir)      // Ptr to actual id.
  674.  
  675. @<Glob...@>=
  676.  
  677. IN_PROD sixteen_bits tok0;
  678.  
  679. @ This function considers a token list between~|pk| and~|pk1|; it returns
  680. the first (flagged) identifier token it finds, or 0~if there's none.
  681. Because each component of the token list may itself be a token list, this
  682. routine is called recursively.
  683.  
  684. @<Part 1@>=@[
  685.  
  686. sixteen_bits 
  687. first_id FCN((t))
  688.     text_pointer t C1("Pointer to start of token list")@;
  689. {
  690. token_pointer pk = *t; // Start of end.
  691. token_pointer pk1 = *(t+1); // End of list.
  692. sixteen_bits tok_value; // Current element.
  693.  
  694. for(; pk < pk1; pk++)
  695.     {
  696.     tok_value = *pk;
  697.  
  698.     if(tok_value > inner_tok_flag) tok_value -= (inner_tok_flag -
  699. tok_flag); 
  700.  
  701.     if(tok_value <= tok_flag)
  702.         { // It's an ordinary (non-flagged) token.
  703.         if( tok_value >= id_flag && tok_value < res_flag)
  704.             return tok_value; // Found identifier.
  705.         else if(tok_value == @'(') return tok_value; // STOP!!!
  706.         }
  707.     else
  708.         { // Flagged token; use indirection.
  709.          t = tok_start + (int)(tok_value - tok_flag); /* Flagged token
  710. corresponds to a |text_pointer|; |*t|~points to beginning of translation. */
  711.         tok_value = first_id(t);// Check that translation recursively. 
  712.         if(tok_value) return tok_value;
  713.         }
  714.     }
  715.  
  716. return 0; // Really couldn't find anything!
  717. }
  718.  
  719. @ In the following situations we want to mark the occurrence of an
  720. identifier as a definition: when |make_reserved| has just been used; after
  721. a specifier, as in |char **argv|; before a colon, as in |found:|; and in
  722. the declaration of a function, as in |main(){@t\dots@>;}|.  This is
  723. accomplished by the invocation of |make_underlined| at appropriate times.
  724. Since, in the declaration of a function, we only find out that the
  725. identifier is being defined after it has been swallowed up by an |expr|, we
  726. must hunt through an indirection chain.
  727.  
  728. @<Part 1@>=@[
  729.  
  730. name_pointer 
  731. make_underlined FCN((p)) /* underline the entry for the first
  732.                 identifier in |p->trans| */ 
  733.     scrap_pointer p C1("")@;
  734. {
  735.   sixteen_bits tok_value; /* the name of this identifier, plus its flag */
  736.  
  737.   tok_value=**(p->trans);
  738.  
  739.   if (tok_value>inner_tok_flag) tok_value-=(inner_tok_flag-tok_flag);
  740.  
  741.   if (tok_value>tok_flag) {
  742.     do 
  743.         { /* Follow an indirection chain to a real identifier. {\bf
  744. Watch the 16-bit arithmetic!} */
  745.         tok_value=**(tok_start +
  746.                 (int)(tok_value-tok_flag));  /* {\bf Don't
  747. remove the parens!} */
  748.         }
  749.     while(tok_value > tok_flag);
  750.  
  751.     if (tok_value<id_flag || tok_value>=res_flag) return NULL; /* shouldn't
  752. happen */ 
  753.  
  754.     xref_switch=def_flag; underline_xref(tok_value-id_flag+name_dir);
  755.   }
  756.  
  757.   if (tok_value<id_flag || tok_value>=res_flag) return NULL; 
  758.     // shouldn't happen!
  759.  
  760.   xref_switch=def_flag; return underline_xref(tok_value-id_flag+name_dir);
  761. }
  762.  
  763. @ We cannot use |new_xref| to underline a cross-reference at this point
  764. because this would just make a new cross-reference at the end of the list.
  765. We actually have to search through the list for the existing
  766. cross-reference.
  767.  
  768. @<Part 1@>=@[
  769.  
  770. name_pointer 
  771. underline_xref FCN((p))
  772.     name_pointer p C1("")@;
  773. {
  774.   xref_pointer q = (xref_pointer)p->xref; /* Pointer to cross-reference
  775. being examined */ 
  776.   xref_pointer r; /* Temporary pointer for permuting cross-references */
  777.   sixteen_bits m; /* Cross-reference value to be installed */
  778.   sixteen_bits n; /* Cross-reference value being examined */
  779. extern boolean strt_off;
  780.  
  781.   if (no_xref || (strt_off && !index_hidden)) 
  782.     return p;
  783.  
  784.   xref_switch = def_flag;
  785.   m = (sixteen_bits)(module_count + xref_switch);
  786.  
  787.   while (q != xmem) 
  788.     {
  789.         n=q->num;
  790.  
  791.         if (n==m) return p;    /* Same status; need to do nothing. */
  792.         else if (m==n+def_flag) /* Module numbers match; update to
  793.                 defined. */ 
  794.         {
  795.         q->num=m; return p;
  796.          }
  797.         else if (n>=def_flag && n<m) break;
  798.  
  799.         q=q->xlink;
  800.       }
  801.  
  802. @<Insert new cross-reference at |q|, not at beginning of list@>;
  803.  
  804. return p;
  805. }
  806.  
  807. @ Record the module at which an identifier was defined. A global variable
  808. distinguishes between |INNER| and |OUTER| modes.
  809.  
  810. @<Glob...@>=
  811.  
  812. IN_PROD PARSING_MODE translate_mode; // Set by |translate|.
  813.  
  814. @
  815. @<Part 1@>=@[
  816.  
  817. SRTN 
  818. defined_at FCN((p))
  819.     name_pointer p C1("")@;
  820. {
  821. extern boolean ok_to_define;
  822.  
  823. if(ok_to_define && translate_mode==OUTER && p > name_dir) 
  824.     {
  825.     sixteen_bits mod_defined = p->defined_in(language);
  826.  
  827.     if(mod_defined && mod_defined != module_count)
  828.         {
  829.         printf("\n! (FWEAVE):  Implicit phase 2 declaration of `");
  830.         prn_id(p);
  831.         printf("' at %s \
  832. repeats or conflicts with previous declaration at %s.\n",
  833.             (char *)MOD_TRANS(module_count), 
  834.             (char *)MOD_TRANS(mod_defined));
  835.         mfree();
  836.         mark_harmless;
  837.         }
  838.     else if(mark_defined.fcn_name)
  839.         {
  840.         p->defined_in(language) = module_count;
  841.         SET_TYPE(p,FUNCTION_NAME);
  842.         }
  843.     }
  844. }
  845.  
  846. @ We get to this module only when the identifier is one letter long, so it
  847. didn't get a non-underlined entry during phase one.  But it may have got
  848. some explicitly underlined entries in later modules, so in order to
  849. preserve the numerical order of the entries in the index, we have to insert
  850. the new cross-reference not at the beginning of the list (namely, at
  851. |p->xref|), but rather right before~|q|.
  852.  
  853. @<Insert new cross-reference at |q|...@>=
  854.  
  855.   append_xref(0); /* This number doesn't matter */
  856.   xref_ptr->xlink = (xref_pointer)p->xref;
  857.  r = xref_ptr; p->xref = (ASCII *)xref_ptr;
  858.  
  859.   while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
  860.  
  861.   r->num=m; /* Everything from |q| on is left undisturbed */
  862.  
  863. @ Now comes the code that tries to match each production that starts with a
  864. particular type of scrap. Whenever a match is discovered, the |squash| or
  865. |reduce| procedures will cause the appropriate action to be performed,
  866. followed by |goto found|.
  867.  
  868. @D cat0 pp->cat
  869. @D cat1 (pp+1)->cat
  870. @D cat2 (pp+2)->cat
  871. @D cat3 (pp+3)->cat
  872. @D cat4 (pp+4)->cat
  873. @D cat5 (pp+5)->cat
  874.  
  875. @d indent_force b_app(indent); @~ b_app(force)@;
  876.  
  877. /* Append $m$~things, followed by a space, followed by $n$~things. */
  878. @m PP_PP(m,n) b_app##m(pp); @~ b_app(@' '); @~ b_app##n(pp+m)@;
  879.  
  880. @<CASES for |ignore_scrap| (C)@>=
  881.  
  882. #if FCN_CALLS
  883.     C_ignore_scrap();
  884. #else
  885.     @<Cases for |ignore_scrap| (C)@>@;
  886. #endif
  887.  
  888. @
  889. @<Part 1@>=
  890.  
  891. #if FCN_CALLS
  892.     @[SRTN C_ignore_scrap(VOID)
  893.         {
  894.         @<Cases for |ignore_scrap| (C)@>@;
  895.         }
  896. #endif
  897.  
  898. @
  899. @<Cases for |ignore_scrap| (C)@>=
  900. {
  901. switch(cat1)
  902.     {
  903.    case stmt:
  904.    case functn:
  905.     SQUASH(pp,2,cat1,0,1);
  906.     break;
  907.     }
  908. }
  909.  
  910. @ Ordinary expressions.
  911. @<CASES for |expr| (C)@>=
  912. #if FCN_CALLS
  913.     C_expr();
  914. #else
  915.     @<Cases for |expr| (C)@>@;
  916. #endif
  917.  
  918. @
  919. @<Part 1@>=
  920. #if FCN_CALLS
  921.     @[SRTN C_expr(VOID)
  922.         {
  923.         @<Cases for |expr| (C)@>@;
  924.         }
  925. #endif
  926.  
  927. @
  928.  
  929. @d OPT9    APP_SPACE; app(opt); app(@'9')@;
  930.  
  931. @<Cases for |expr| (C)@>=
  932. {
  933. if (cat1==lbrace || ((!Cpp) && cat1==int_like))
  934.     { /* ``|f(x) {}|'' or ``|f(x) float x;|'' (old-style) */
  935.     defined_at(make_underlined(pp)); /* Recognized function name;
  936. remember current module number. */
  937.     in_function = YES;
  938.     SQUASH(pp,1,fn_decl,0,111); 
  939.     }
  940. else if (cat1==unop) 
  941.     SQUASH(pp,2,expr,-2,2); /* ``|x--|'' */
  942. else if (cat1==binop)
  943.     {
  944.     if(cat2==expr) 
  945.         SQUASH(pp,3,expr,-2,3); /* ``|x + y|'' */
  946.     else if(cat2==decl_hd)
  947.         SQUASH(pp, 3, tstart, 0, 6061); 
  948.             /* Trap for ``|@c++ A<int>|'', with |A| undefined. */
  949.     }
  950. else if (cat1==unorbinop && cat2==expr)
  951.     {
  952.     sixteen_bits *s = *(pp+1)->trans;
  953.     b_app1(pp);
  954.  
  955. /* If the translation of the next scrap begins with an escape character, we
  956. assume we're seeing \.{\\amp}. */
  957.     if( (s[0] == (sixteen_bits)@'\\') && s[1] == (sixteen_bits)@'a'
  958.             && s[2] == (sixteen_bits)@'m')
  959.         {
  960.         APP_SPACE; b_app1(pp+1); @~ APP_SPACE; /* ``|x & y|'' */
  961.         }
  962.     else b_app1(pp+1); /* ``|x*y|'' */
  963.  
  964.     b_app1(pp+2);
  965.     REDUCE(pp,3,expr,-2,3000);
  966.     }
  967. else if (cat1==comma)
  968.     {
  969.     if((cat2==expr || cat2==int_like)) /* ``|x,y|'' or ``|x,char|''  */
  970.         {
  971.         b_app2(pp);
  972.         OPT9;
  973.         b_app1(pp+2); REDUCE(pp,3,cat2,-2,4);
  974.         }
  975.     else if(cat2==space)
  976.         SQUASH(pp, 3, expr, -2, 88); // Macros.
  977.     }
  978. else if (cat1==expr) 
  979.     SQUASH(pp,2,expr,-2,5); /* ``|f(x)|'' */
  980. else if (cat1==semi) 
  981.     SQUASH(pp,2,stmt,-1,6); /* ``|x;|'' */
  982. else if (cat1==colon)  /* ``|label:|'' */
  983.     {
  984.     if(!Cpp || in_function)
  985.         { /* Ordinary C tag. */
  986.         make_underlined (pp);  /* Label name. */
  987.         SQUASH(pp,2,tag,0,7);
  988.         }
  989.     else if(cat2==expr) 
  990.         { /* Put the spaces in explicitly in case we're not in math
  991. mode at the time. */
  992.         b_app1(pp); @~ b_app(@' '); @~ b_app1(pp+1); @~ b_app(@' '); 
  993. @~ b_app1(pp+2);        
  994.         REDUCE(pp,3,expr,-2,701); 
  995.             /* \Cpp: ``|@c++ derived() : base()|'' */
  996.         }
  997.     }
  998. else if(cat1==space) 
  999.     SQUASH(pp,2,expr,-2,8); /* For use in macros. */
  1000. }
  1001.  
  1002. @ The next several cases are for symbols that are formatted like operators.
  1003. These need to get explicit spaces to set them off from their surroundings.
  1004.  
  1005. @<Bracket with spaces@>=
  1006.  
  1007. APP_SPACE; @~ b_app1(pp); @~ APP_SPACE;
  1008.  
  1009. @ Name as unary operator: ``\.{\$UNOP\_\ }''.
  1010. @<CASES for |UNOP| (C)@>=
  1011. #if FCN_CALLS
  1012.     C_UNOP();
  1013. #else
  1014.     @<Cases for |UNOP| (C)@>@;
  1015. #endif
  1016.  
  1017. @
  1018. @<Part 1@>=
  1019. #if FCN_CALLS
  1020.     @[SRTN C_UNOP(VOID)
  1021.         {
  1022.         @<Cases for |UNOP| (C)@>@;
  1023.         }
  1024. #endif
  1025.  
  1026. @
  1027. @<Cases for |UNOP| (C)@>=
  1028. {
  1029. b_app1(pp); @~ APP_SPACE;
  1030. REDUCE(pp,1,unop,-1,4443);
  1031. }
  1032.  
  1033. @ Name as binary operator: ``\.{\ \$\_BINOP\_\ }''.
  1034. @<CASES for |BINOP| (C)@>=
  1035. #if FCN_CALLS
  1036.     C_BINOP();
  1037. #else
  1038.     @<Cases for |BINOP| (C)@>@;
  1039. #endif
  1040.  
  1041. @
  1042. @<Part 1@>=
  1043. #if FCN_CALLS
  1044.     @[SRTN C_BINOP(VOID)
  1045.         {
  1046.         @<Cases for |BINOP| (C)@>@;
  1047.         }
  1048. #endif
  1049.  
  1050. @
  1051. @<Cases for |BINOP| (C)@>=
  1052. {
  1053. @<Bracket with spaces@>;
  1054. REDUCE(pp,1,binop,-1,4444);
  1055. }
  1056.  
  1057. @ Name as comma: ``\.{\ \$\_COMMA\_\ }''.
  1058. @<CASES for |COMMA| (C)@>=
  1059. #if FCN_CALLS
  1060.     C_COMMA();
  1061. #else
  1062.     @<Cases for |COMMA| (C)@>@;
  1063. #endif
  1064.  
  1065. @
  1066. @<Part 1@>=
  1067. #if FCN_CALLS
  1068.     @[SRTN C_COMMA(VOID)
  1069.         {
  1070.         @<Cases for |COMMA| (C)@>@;
  1071.         }
  1072. #endif
  1073.  
  1074. @
  1075. @<Cases for |COMMA| (C)@>=
  1076. {
  1077. @<Bracket with spaces@>;
  1078. REDUCE(pp,1,comma,-1,4445);
  1079. }
  1080.  
  1081. @ Expression with space to left: ``\.{\ \$\_EXPR}''.
  1082. @<CASES for |_EXPR| (C)@>=
  1083. #if FCN_CALLS
  1084.     C__E();
  1085. #else
  1086.     @<Cases for |_EXPR| (C)@>@;
  1087. #endif
  1088.  
  1089. @
  1090. @<Part 1@>=
  1091. #if FCN_CALLS
  1092.     @[SRTN C__E(VOID)
  1093.         {
  1094.         @<Cases for |_EXPR| (C)@>@;
  1095.         }
  1096. #endif
  1097.  
  1098. @
  1099. @<Cases for |_EXPR| (C)@>=
  1100. {
  1101. APP_SPACE; @~ b_app1(pp);
  1102. REDUCE(pp,1,expr,-2,4446);
  1103. }
  1104.  
  1105. @ Expression with spaces on both sides: ``\.{\ \$\_EXPR\_\ }''.
  1106. @<CASES for |_EXPR_| (C)@>=
  1107. #if FCN_CALLS
  1108.     C__E_();
  1109. #else
  1110.     @<Cases for |_EXPR_| (C)@>@;
  1111. #endif
  1112.  
  1113. @
  1114. @<Part 1@>=
  1115. #if FCN_CALLS
  1116.     @[SRTN C__E_(VOID)
  1117.         {
  1118.         @<Cases for |_EXPR_| (C)@>@;
  1119.         }
  1120. #endif
  1121.  
  1122. @
  1123. @<Cases for |_EXPR_| (C)@>=
  1124. {
  1125. @<Bracket with spaces@>;
  1126. REDUCE(pp,1,expr,-2,4447);
  1127. }
  1128.  
  1129. @ Expression with space to right: ``\.{\$EXPR\_\ }''.
  1130. @<CASES for |EXPR_| (C)@>=
  1131. #if FCN_CALLS
  1132.     C_E_();
  1133. #else
  1134.     @<Cases for |EXPR_| (C)@>@;
  1135. #endif
  1136.  
  1137. @
  1138. @<Part 1@>=
  1139. #if FCN_CALLS
  1140.     @[SRTN C_E_(VOID)
  1141.         {
  1142.         @<Cases for |EXPR_| (C)@>@;
  1143.         }
  1144. #endif
  1145.  
  1146. @
  1147. @<Cases for |EXPR_| (C)@>=
  1148. {
  1149. b_app1(pp); @~ APP_SPACE;
  1150. REDUCE(pp,1,expr,-2,4448);
  1151. }
  1152.  
  1153. @ There are right and wrong ways of inserting a real space. What we want to
  1154. do is to insert the macro \.{\\\ } (which works either in or out of math mode)
  1155. without changing the mathness.
  1156.  
  1157. @d APP_SPACE APP_STR("\\ ")
  1158.  
  1159. @ The next stuff handles C~preprocessing (not very well).
  1160. @<Glob...@>=
  1161.  
  1162. IN_PROD boolean active_space PSET(NO);
  1163. IN_PROD boolean in_LPROC PSET(NO);
  1164. IN_PROD boolean expanded_lproc PSET(NO);
  1165.  
  1166. @ In \Cpp, the syntax for |new| and |delete| is unusual.
  1167. @<CASES for |new_like| (C)@>=
  1168. #if FCN_CALLS
  1169.     C_new_like();
  1170. #else
  1171.     @<Cases for |new_like| (C)@>@;
  1172. #endif
  1173.  
  1174. @
  1175. @<Part 1@>=
  1176. #if FCN_CALLS
  1177.     @[SRTN C_new_like(VOID)
  1178.         {
  1179.         @<Cases for |new_like| (C)@>@;
  1180.         }
  1181. #endif
  1182.  
  1183. @
  1184. @<Cases for |new_like| (C)@>=
  1185. {
  1186. if(cat1==decl_hd || cat1==expr)
  1187.     { /* \Cpp: |@c++ new int| or |@c++ new class(20)| */
  1188.     PP_PP(1,1);
  1189.     if(cat1==decl_hd) 
  1190.         {
  1191.         OUTDENT;
  1192.         }
  1193.     REDUCE(pp,2,expr,-2,909);
  1194.     }
  1195. }
  1196.  
  1197. @ The \CWEB\ code didn't work right here. The present attempt is a mess.
  1198.  
  1199. @<CASES for |lproc| (C)@>=
  1200. #if FCN_CALLS
  1201.     C_lproc();
  1202. #else
  1203.     @<Cases for |lproc| (C)@>@;
  1204. #endif
  1205.  
  1206. @
  1207. @<Part 1@>=
  1208. #if FCN_CALLS
  1209.     @[SRTN C_lproc(VOID)
  1210.         {
  1211.         @<Cases for |lproc| (C)@>@;
  1212.         }
  1213. #endif
  1214.  
  1215. @
  1216. @<Cases for |lproc| (C)@>=
  1217. {
  1218. expanded_lproc = YES;
  1219.  
  1220. if(!in_LPROC) 
  1221.     active_space = YES;
  1222.  
  1223. if(cat1==define_like) 
  1224.     make_underlined(pp+3); /* ``\.{\#\ define\ M}'' */
  1225.  
  1226. if (cat1==else_like || cat1==if_like ||cat1==define_like)
  1227.      SQUASH(pp,2,lproc,0,10); /* ``\.{\#\ define}'' $\to$
  1228. ``\.{\#define}'' */
  1229. else if (cat1==rproc)
  1230.     {
  1231.     expanded_lproc = active_space = in_LPROC = NO;
  1232.     SQUASH(pp,2,ignore_scrap,-1,11); 
  1233.     }
  1234. else if(cat1==expr) 
  1235.     SQUASH(pp,1,LPROC,0,12); /* ``|#if(0)|'' */
  1236. else if (cat1==space)
  1237.     { 
  1238.     if(cat2==lpar)
  1239.         SQUASH(pp, 1, lproc, PLUS 2, 1332); // \.{if\ (x)}
  1240. /* Following stuff for \&{\#define}.  
  1241. Absorb the identifier: ``\&{\#define M}'' */  
  1242.     else if(cat3==lpar) 
  1243.         SQUASH(pp,1,lproc,PLUS 3,1333); /* Expand the parens. */
  1244.     else if(cat3==expr) 
  1245.         SQUASH(pp,4,LPROC,0,13); /* |expr| should be
  1246.             ``|()|''; get them too. */ 
  1247.     else if(cat3==space || cat3==ignore_scrap || cat3==rproc) 
  1248.         SQUASH(pp,3,LPROC,0,14); /* Just the identifier. */ 
  1249.     }
  1250. expanded_lproc = NO;
  1251. }
  1252.  
  1253. @<CASES for |LPROC| (C)@>=
  1254. #if FCN_CALLS
  1255.     C_LPRC();
  1256. #else
  1257.     @<Cases for |LPROC| (C)@>@;
  1258. #endif
  1259.  
  1260. @
  1261. @<Part 1@>=
  1262. #if FCN_CALLS
  1263.     @[SRTN C_LPRC(VOID)
  1264.         {
  1265.         @<Cases for |LPROC| (C)@>@;
  1266.         }
  1267. #endif
  1268.  
  1269. @
  1270. @<Cases for |LPROC| (C)@>=
  1271. {
  1272. active_space = NO; in_LPROC = YES;
  1273.  
  1274. if(cat1==space) 
  1275.     {
  1276.     b_app1(pp);
  1277.     b_app(@' ');
  1278.     REDUCE(pp, 2, LPROC, 0, 20);
  1279.     }
  1280. else if(cat1==rproc) 
  1281.     {
  1282.     in_LPROC = NO;
  1283.     SQUASH(pp,2,ignore_scrap,-1,21);
  1284.     }
  1285. else if(cat2==rproc)
  1286.     {
  1287.     in_LPROC = NO;
  1288.     SQUASH(pp,3,ignore_scrap,-1,22);
  1289.     }
  1290.  
  1291. #if(0)
  1292.     if(cat3==lpar && cat4==expr && cat5==rpar)
  1293.       if (cat2==rproc) 
  1294.         {
  1295.             b_app1(pp); b_app(@' '); b_app2(pp+1);
  1296.             REDUCE(pp,3,ignore_scrap,-1,53);
  1297.           }
  1298.       else if (cat2==expr && cat3==rproc) 
  1299.         { 
  1300.         b_app1(pp); b_app(@' '); b_app1(pp+1); b_app(@' ');
  1301.         b_app2(pp+2); REDUCE(pp,4,ignore_scrap,-1,53);
  1302.         }
  1303. #endif
  1304. }
  1305.  
  1306. @
  1307. @<CASES for |space| (C)@>=
  1308. #if FCN_CALLS
  1309.     C_space();
  1310. #else
  1311.     @<Cases for |space| (C)@>@;
  1312. #endif
  1313.  
  1314. @
  1315. @<Part 1@>=
  1316. #if FCN_CALLS
  1317.     @[SRTN C_space(VOID)
  1318.         {
  1319.         @<Cases for |space| (C)@>@;
  1320.         }
  1321. #endif
  1322.  
  1323. @
  1324. @<Cases for |space| (C)@>=
  1325. {
  1326. if(active_space)
  1327.     {
  1328.     if(expanded_lproc) 
  1329.         SQUASH(pp,1,space,-1,5336);
  1330.     else 
  1331.         SQUASH(pp,1,space,1,5335);
  1332.     }
  1333. else 
  1334.     REDUCE(pp,1,ignore_scrap,-1,5334);
  1335. }
  1336.  
  1337. @<CASES for |question| (C)@>=
  1338. #if FCN_CALLS
  1339.     C_question();
  1340. #else
  1341.     @<Cases for |question| (C)@>@;
  1342. #endif
  1343.  
  1344. @
  1345. @<Part 1@>=
  1346. #if FCN_CALLS
  1347.     @[SRTN C_question(VOID)
  1348.         {
  1349.         @<Cases for |question| (C)@>@;
  1350.         }
  1351. #endif
  1352.  
  1353. @
  1354. @<Cases for |question| (C)@>=
  1355. {
  1356. if (cat1==expr && cat2==colon) SQUASH(pp,3,binop,-2,30); /* ``|i==1 ? YES :
  1357.                     NO|'' */
  1358. }
  1359.  
  1360. @<CASES for |int_like| (C)@>=
  1361. #if FCN_CALLS
  1362.     C_int_like();
  1363. #else
  1364.     @<Cases for |int_like| (C)@>@;
  1365. #endif
  1366.  
  1367. @
  1368. @<Part 1@>=
  1369. #if FCN_CALLS
  1370.     @[SRTN C_int_like(VOID)
  1371.         {
  1372.         @<Cases for |int_like| (C)@>@;
  1373.         }
  1374. #endif
  1375.  
  1376. @
  1377. @<Cases for |int_like| (C)@>=
  1378. {
  1379. if(cat1==unop)
  1380.     {
  1381.     if(cat2==expr || cat2==int_like) 
  1382.         SQUASH(pp,3,expr,-2,35); /* \Cpp: |@c++ class::f| or
  1383.             constructor: |@c++ class::class| */ 
  1384.     else if(cat2==op_like) 
  1385.         SQUASH(pp,1,int_like,PLUS 2,36); /* \Cpp: Expand |@c++ operator|
  1386.             construction. */ 
  1387.     }
  1388. else if (cat1==int_like|| cat1==struct_like)
  1389.     { /* ``|extern int|'' or ``|@c++ typedef int bool|''. */
  1390.     PP_PP(1,1);
  1391.     REDUCE(pp,2,cat1,0,40);
  1392.     }    
  1393. else if(cat1==reference)
  1394.     SQUASH(pp, 2, int_like, -2, 43); // |@c++ int &ref;|
  1395. else if (cat1==expr || cat1==unorbinop || cat1==semi)
  1396.     { /* ``|int i|'' or ``|int *|'' */ 
  1397.     b_app1(pp); 
  1398.  
  1399.     if(cat1!=semi) 
  1400.         b_app(@' '); 
  1401.  
  1402.     INDENT; /* Start long declaration. (Note: Whenever we leave
  1403.             |decl_hd|, we must |OUTDENT|.) */ 
  1404.  
  1405.     REDUCE(pp,1,decl_hd,-1,41);
  1406.     }
  1407. else if(cat1==comma) 
  1408.     {
  1409.     b_app1(pp);
  1410.     INDENT;
  1411.     REDUCE(pp,1,decl_hd,-2,42); /* Function prototype: |int,|. */ 
  1412.     }
  1413. else if(cat1==rpar)
  1414.     {
  1415.     b_app1(pp);
  1416.     INDENT;
  1417.     REDUCE(pp,1,decl_hd,-2,502);
  1418.     }
  1419. else if(Cpp && cat1==lpar && !in_prototype)
  1420.     { // The \Cpp\ is a KLUDGE. Consider ``|int (*f)()|''.
  1421.     b_app1(pp);
  1422.     @<Append thinspace@>@;
  1423.     REDUCE(pp,1,expr,-2,5021); /* \Cpp\ constructor: ``|@c++ base()|'';
  1424.                     or ``|@c++ int(x)|''. */
  1425.     }
  1426. else if(cat1==binop && cat2==expr)
  1427.     SQUASH(pp,3,int_like,-2,5022); /* \Cpp\ initializer: |@c++ base = 0| */
  1428. else if(cat1 == langle)
  1429.     SQUASH(pp, 1, int_like, PLUS 1, 5997); // |@c++ int<24>|
  1430. else if(cat1 == rangle)
  1431.     {
  1432.     b_app1(pp);
  1433.     INDENT;
  1434.     REDUCE(pp,1,decl_hd,-2,5998);
  1435.     }
  1436. else if(cat1 == class_like)
  1437.     { // \Cpp:  |@c++ friend class|.
  1438.     PP_PP(1,1);
  1439.     REDUCE(pp, 2, class_like, 0, 5995);
  1440.     }    
  1441. else if(cat1 == tlist)
  1442.     SQUASH(pp, 2, int_like, -2, 5999);
  1443. else if(cat1 == namespace)
  1444.     { /* |@c++ using namespace| */
  1445.     PP_PP(1,1);
  1446.     REDUCE(pp, 2, namespace, 0, 5996);
  1447.     }
  1448. }
  1449.  
  1450. @ We need a special case for |extern|, because of constructions like |@c+
  1451. extern "C"| in \Cpp.
  1452.  
  1453. @<CASES for |extern_like| (C)@>=
  1454. #if FCN_CALLS
  1455.     C_ext_like();
  1456. #else
  1457.     @<Cases for |extern_like| (C)@>@;
  1458. #endif
  1459.  
  1460. @
  1461. @<Part 1@>=
  1462. #if FCN_CALLS
  1463.     @[SRTN C_ext_like(VOID)
  1464.         {
  1465.         @<Cases for |extern_like| (C)@>@;
  1466.         }
  1467. #endif
  1468.  
  1469. @
  1470. @<Cases for |extern_like| (C)@>=
  1471. {
  1472. if(Cpp &&cat1==expr)
  1473.     { /* |@c++ extern "C"| */
  1474.     PP_PP(1,1);
  1475.     if(cat2==lbrace)
  1476.         REDUCE(pp, 2, fn_decl, 0, 5025); // ``|@c++ extern "C" {}|''.
  1477.     else
  1478.         REDUCE(pp, 2, int_like, 0, 5023); 
  1479.             // ``|@c++ extern "C" int fcn();|''
  1480.     }
  1481. else 
  1482.     SQUASH(pp,1,int_like,0,5024);
  1483. }
  1484.  
  1485. @ A case related but not identical to |int_like| is |modifier|, which is
  1486. used for things like |const| and |volatile|. The difficulty is that it may
  1487. come first in the declaration, but it need not. Compare |const char c| and
  1488. |char const c|; also |char *const p| and |const char *p|.
  1489. @<CASES for |modifier| (C)@>=
  1490. #if FCN_CALLS
  1491.     C_modifier();
  1492. #else
  1493.     @<Cases for |modifier| (C)@>@;
  1494. #endif
  1495.  
  1496. @
  1497. @<Part 1@>=
  1498. #if FCN_CALLS
  1499.     @[SRTN C_modifier(VOID)
  1500.         {
  1501.         @<Cases for |modifier| (C)@>@;
  1502.         }
  1503. #endif
  1504.  
  1505. @
  1506. @<Cases for |modifier| (C)@>=
  1507. {
  1508. if(cat1==int_like)
  1509.     SQUASH(pp,1,int_like,-2,503);
  1510. else if(pp == lo_ptr)
  1511.     SQUASH(pp, 1, expr, 0, 5040);
  1512. else if(cat1==semi || cat1==lbrace)
  1513.     SQUASH(pp,1,_EXPR,0,5042); 
  1514.         // |@c++ int f() const;| or |@c++ int f() const {}|.
  1515. else
  1516.     SQUASH(pp,1,EXPR_,0,5041);
  1517. }
  1518.  
  1519. @ Personal computers have a strange syntax with the |HUGE| operator.  We
  1520. must deal with declarations such as |char HUGE *p;|.
  1521. @<CASES for |huge_like| (C)@>=
  1522. #if FCN_CALLS
  1523.     C_huge_like();
  1524. #else
  1525.     @<Cases for |huge_like| (C)@>@;
  1526. #endif
  1527.  
  1528. @
  1529. @<Part 1@>=
  1530. #if FCN_CALLS
  1531.     @[SRTN C_huge_like(VOID)
  1532.         {
  1533.         @<Cases for |huge_like| (C)@>@;
  1534.         }
  1535. #endif
  1536.  
  1537. @
  1538. @<Cases for |huge_like| (C)@>=
  1539. {
  1540. if(cat1==unorbinop) 
  1541.     {
  1542.     b_app1(pp); @~ APP_SPACE; @~ b_app1(pp+1);
  1543.     REDUCE(pp,2,unorbinop,-1,505);
  1544.     }
  1545. }
  1546.  
  1547. @<CASES for |virtual| (C++)@>=
  1548. #if FCN_CALLS
  1549.     C_virtual();
  1550. #else
  1551.     @<Cases for |virtual| (C++)@>@;
  1552. #endif
  1553.  
  1554. @
  1555. @<Part 1@>=
  1556. #if FCN_CALLS
  1557.     @[SRTN C_virtual(VOID)
  1558.         {
  1559.         @<Cases for |virtual| (C++)@>@;
  1560.         }
  1561. #endif
  1562.  
  1563. @
  1564. @<Cases for |virtual| (C++)@>=
  1565. {
  1566. b_app1(pp);
  1567.  
  1568. if(cat1==unop) 
  1569.     APP_SPACE; // |@c++ virtual ~base();|
  1570.  
  1571. REDUCE(pp,1,int_like,0,506);
  1572. }
  1573.  
  1574. @<CASES for |reference| (C++)@>=
  1575. #if FCN_CALLS
  1576.     C_reference();
  1577. #else
  1578.     @<Cases for |reference| (C++)@>@;
  1579. #endif
  1580.  
  1581. @
  1582. @<Part 1@>=
  1583. #if FCN_CALLS
  1584.     @[SRTN C_reference(VOID)
  1585.         {
  1586.         @<Cases for |reference| (C++)@>@;
  1587.         }
  1588. #endif
  1589.  
  1590. @ If we can't figure out that an ampersand if a reference, treat it just
  1591. like an asterisk.
  1592. @<Cases for |reference| (C++)@>=
  1593. {
  1594. SQUASH(pp, 1, unorbinop, -1, 507);
  1595. }
  1596.  
  1597. @ With the advent of ANSI~C, we have to deal with function prototypes,
  1598. which look very much like casts. 
  1599.  
  1600. @d INDENT if(!indented)
  1601.         {
  1602.         b_app(indent);
  1603.         indented = YES;
  1604.         }
  1605.  
  1606. @d OUTDENT if(indented)
  1607.         {
  1608.         b_app(outdent);
  1609.         indented = NO;
  1610.         }
  1611.  
  1612. @<Glob...@>=
  1613.  
  1614. IN_PROD int in_prototype PSET(NO); 
  1615.     // This is used as a numerical counter.
  1616. IN_PROD int indented PSET(NO);
  1617.  
  1618. @ For \Cpp, it becomes necessary to know whether one is inside or outside
  1619. of a function.
  1620.  
  1621. @<Glob...@>=
  1622.  
  1623. IN_PROD boolean in_function PSET(NO);
  1624.  
  1625. @ A |decl_hd| is something like ``|int i|''.
  1626.  
  1627. @<CASES for |decl_hd| (C)@>=
  1628. #if FCN_CALLS
  1629.     C_decl_hd();
  1630. #else
  1631.     @<Cases for |decl_hd| (C)@>@;
  1632. #endif
  1633.  
  1634. @
  1635. @<Part 1@>=
  1636. #if FCN_CALLS
  1637.     @[SRTN C_decl_hd(VOID)
  1638.         {
  1639.         @<Cases for |decl_hd| (C)@>@;
  1640.         }
  1641. #endif
  1642.  
  1643. @
  1644. @<Cases for |decl_hd| (C)@>=
  1645. {
  1646. if(cat1==rpar) 
  1647.     {
  1648.     if((pp-1)->cat==lpar) 
  1649.         SQUASH(pp,1,decl_hd,-1,4990); // ``|(int i)|''.
  1650.     else if((pp-2)->cat==decl_hd) 
  1651.         SQUASH(pp,1,decl_hd,-2,4991); // ``|(int i, int j)|''.
  1652.     else if((pp-3)->cat==decl_hd)
  1653.         SQUASH(pp, 1, decl_hd, -3, 4992);
  1654.     }
  1655. else if(cat1==decl_hd) 
  1656.     SQUASH(pp,2,decl_hd,0,50); // ``|(int,int)|''
  1657. else if(cat1==comma)
  1658.     {
  1659.     if(cat2==decl_hd)
  1660.         { /* For function prototype. */
  1661.         b_app2(pp); @~ OPT9;
  1662.         b_app1(pp+2);
  1663.         REDUCE(pp,3,decl_hd,0,501);
  1664.         }
  1665.     else if(cat2==ignore_scrap && cat3==decl_hd)
  1666.         { /* For function prototype with comment. */
  1667.         b_app2(pp); @~ OPT9;
  1668.         b_app2(pp+2);
  1669.         REDUCE(pp,4,decl_hd,0,504);
  1670.         }
  1671. #if 0
  1672.     else if(Cpp && (cat2==decl || cat2==stmt))
  1673.         SQUASH(pp, 3, stmt, -2, 508); 
  1674.             /* ``|@c++ for(int i=0, int j=0;;)|'' or ``|@c++
  1675.                 for(int i=0, int j=0, int k=0;;)|''. */
  1676. #endif
  1677.     else
  1678.     { /* ``|int i,|'' */
  1679.     if(cat2==ignore_scrap && (cat3==int_like || cat3==struct_like ||
  1680.             cat3==modifier) ) 
  1681.         {/* Function prototype, with intervening comment. */
  1682.         b_app1(pp);
  1683.         if((pp-3)->cat != decl_hd && (pp-2)->cat != decl_hd
  1684.                 && cat3 != modifier)
  1685.             in_prototype++;
  1686.         REDUCE(pp,1,decl_hd,PLUS 3,5221);
  1687.         }
  1688.     else if(cat2==int_like || cat2==struct_like || cat2==modifier) 
  1689.         { /* Function prototype. */ 
  1690.         b_app1(pp);
  1691.         if((pp-3)->cat != decl_hd && (pp-2)->cat != decl_hd
  1692.                 && cat2 != modifier)
  1693.             in_prototype++; /* The |modifier| clause is to
  1694. prevent a situation like |(int, const int)| from thinking it's two levels
  1695. of prototypes. */
  1696.         REDUCE(pp,1,decl_hd,PLUS 2,52);
  1697.         }
  1698.     else 
  1699.         {  /* Expecting list of something. */
  1700.         b_app2(pp); b_app(@' ');
  1701.  
  1702. #if 0
  1703.         if(Cpp)
  1704.             REDUCE(pp, 2, decl_hd, -2, 540); 
  1705.                 // ``|@c++ int i=0, int j=0|'' (e.g., in |for|)
  1706.         else
  1707. #endif
  1708.             REDUCE(pp,2,decl_hd,-1,54); // ``|int i,j|''
  1709.         }
  1710.     }
  1711.     }
  1712. else if (cat1==unorbinop) /* ``|int **p|'' */
  1713.     {
  1714.     b_app1(pp); 
  1715. @%    b_app(@'{'); 
  1716.     b_app1(pp+1); 
  1717. @%b_app(@'}');
  1718.     REDUCE(pp,2,decl_hd,-1,55);
  1719.     }
  1720. else if (cat1==expr) /* ``|int i|'' or ``|int i, j|'' */
  1721.     {
  1722.     make_underlined(pp+1);
  1723.     SQUASH(pp,2,decl_hd,-1,56);  /* The |-1| is to pick up a left
  1724.                     paren for function prototype. */
  1725.     }
  1726. else if ((cat1==binop||cat1==colon
  1727. ||cat1==expr    /* (for initializations) */
  1728. ) && cat2==expr && (cat3==comma || cat3==semi || cat3==rpar))
  1729. #if 0
  1730.     if(cat1==binop)
  1731.         {
  1732.         PP_PP(1,2);
  1733.         REDUCE(pp,3,decl_hd,-1,5660);
  1734.         }
  1735.     else 
  1736. #endif
  1737.         SQUASH(pp,3,decl_hd,-1,5661);
  1738. else if(cat1==int_like && (cat2==unop || cat2==langle))
  1739.     SQUASH(pp, 1, decl_hd, PLUS 1, 5662); 
  1740.     /* \Cpp:  ``|@c++ void *int::fcn()|'' or ``|@c++ void
  1741.         *int<int>::fcn()|'' */
  1742. else if (cat1==lbrace || (cat1==int_like && 
  1743.     ((pp-1)->trans == NULL || **(pp-1)->trans != @'('))) /*
  1744. Recognize beginning of function: ``|float f() {}|'' or ``|float f(x) float
  1745. x|'' */ 
  1746.     {
  1747.     b_app1(pp);
  1748.     OUTDENT;
  1749.     in_function = YES;
  1750.     defined_at(FIRST_ID(pp));
  1751.     REDUCE(pp,1,fn_decl,0,58); 
  1752.     }
  1753. else if (cat1==semi)
  1754.     { /* ``|int i;|'' */
  1755.     b_app2(pp);
  1756.     OUTDENT; /* Finish long declaration. */
  1757. #if 0
  1758.     if(Cpp)
  1759.         REDUCE(pp, 2, decl, -2, 594); 
  1760.             // ``|@c++ for(int i=0, int j=0;;)|''
  1761.     else
  1762. #endif
  1763.         REDUCE(pp,2,decl,-1,59);
  1764.     }
  1765. else if(Cpp && cat1==int_like && cat2==unop)
  1766.     SQUASH(pp,1,decl_hd,PLUS 1,590); /* \Cpp: |@c++ void *class::f| */
  1767. else if(Cpp && cat1 == rangle)
  1768.     SQUASH(pp, 1, decl_hd, -2, 591); /* \Cpp:  end of template. */
  1769. else if(Cpp && cat1 == struct_like)
  1770.     SQUASH(pp, 2, decl_hd, -1, 593); 
  1771.         /* \Cpp: |@c++ template<class C1, class C2>|. */
  1772. }
  1773.  
  1774. @ A |decl| is a |decl_hd| followed by a semicolon---i.e., a complete
  1775. statement. 
  1776.  
  1777. @<CASES for |decl| (C)@>=
  1778. #if FCN_CALLS
  1779.     C_decl();
  1780. #else
  1781.     @<Cases for |decl| (C)@>@;
  1782. #endif
  1783.  
  1784. @
  1785. @<Part 1@>=
  1786. #if FCN_CALLS
  1787.     @[SRTN C_decl(VOID)
  1788.         {
  1789.         @<Cases for |decl| (C)@>@;
  1790.         }
  1791. #endif
  1792.  
  1793. @
  1794. @<Cases for |decl| (C)@>=
  1795. {
  1796. if(Cpp)
  1797.     {
  1798.     if(cat1==functn)
  1799.         {
  1800.         b_app1(pp); @~ b_app(big_force);
  1801.         b_app1(pp+1);
  1802.         REDUCE(pp,2,functn,-1,61);
  1803.         }
  1804.     else 
  1805.         SQUASH(pp,1,stmt,-1,611); // E.g., ``|@c++ for(int i=0;;)|''
  1806.     }
  1807. else
  1808.     {
  1809.     if (cat1==decl)
  1810.         { /* ``|int i; float x;|'' */
  1811.         b_app1(pp); @~ b_app(force);
  1812.         b_app1(pp+1);
  1813.         REDUCE(pp,2,decl,-1,60);
  1814.         }
  1815.     else if (cat1==stmt || cat1==functn)
  1816.         {  /* ``|int i; x=0;|'' or ``|int i; f(){}|'' */
  1817.         b_app1(pp); @~ b_app(big_force); 
  1818.         b_app1(pp+1); 
  1819.         REDUCE(pp,2,cat1,-1,61);
  1820.         }
  1821.     }
  1822. }
  1823.  
  1824. @ A |fn_decl| is the beginning of a function.
  1825.  
  1826. @<CASES for |fn_decl| (C)@>=
  1827. #if FCN_CALLS
  1828.     C_fn_decl();
  1829. #else
  1830.     @<Cases for |fn_decl| (C)@>@;
  1831. #endif
  1832.  
  1833. @
  1834. @<Part 1@>=
  1835. #if FCN_CALLS
  1836.     @[SRTN C_fn_decl(VOID)
  1837.         {
  1838.         @<Cases for |fn_decl| (C)@>@;
  1839.         }
  1840. #endif
  1841.  
  1842. @
  1843. @<Cases for |fn_decl| (C)@>=
  1844. {
  1845. if(cat1 == semi && Cpp)
  1846.     { /* |@c++ using namespace X;| */
  1847.     b_app2(pp);
  1848.     REDUCE(pp, 2, stmt, -1, 72);
  1849.     }
  1850. else if (cat1==decl) /* ``|f(x) float x;|'' */
  1851.     {
  1852.     b_app1(pp); 
  1853.     b_app(indent); @~ indent_force;
  1854.         b_app1(pp+1); /* Accrete old-style declarations. */
  1855.     b_app(outdent); @~ b_app(outdent);
  1856.     REDUCE(pp,2,fn_decl,0,70);
  1857.     }
  1858. else if (cat1==stmt) /* ``|f(){}|'' */
  1859.     {
  1860. #if(0)
  1861.     b_app(backup); /* Beginning of function. */
  1862. #endif
  1863.     b_app1(pp); @~ b_app(force); 
  1864.     b_app(indent);
  1865.         b_app1(pp+1); /* Function body */
  1866.     b_app(outdent);
  1867.     in_function = NO;
  1868.     REDUCE(pp,2,functn,-1,71);
  1869.     }
  1870. }
  1871.  
  1872. @ Deal with a complete function. Handle ``|f(){} g(){}|'' or ``|f(){}
  1873. extern int i;|''. 
  1874. @<CASES for |functn| (C)@>=
  1875. #if FCN_CALLS
  1876.     C_functn();
  1877. #else
  1878.     @<Cases for |functn| (C)@>@;
  1879. #endif
  1880.  
  1881. @
  1882. @<Part 1@>=
  1883. #if FCN_CALLS
  1884.     @[SRTN C_functn(VOID)
  1885.         {
  1886.         @<Cases for |functn| (C)@>@;
  1887.         }
  1888. #endif
  1889.  
  1890. @ The |stmt| clause takes care of \Cpp\ constructions like |@c++ try{}
  1891. catch(){}|. 
  1892. @<Cases for |functn| (C)@>=
  1893. {
  1894. if (cat1==functn || cat1==decl || cat1==stmt) 
  1895.     {
  1896.     b_app1(pp); @~ b_app(big_force); 
  1897.     b_app1(pp+1); REDUCE(pp,2,cat1,-1,80); /* |-1| for \Cpp */
  1898.     }
  1899. }
  1900.  
  1901. @ Handle syntaxes like ``|typedef int I;|'' or ``|typedef int
  1902. (**f[])();|''.
  1903. @<CASES for |typedef_like| (C)@>=
  1904. #if FCN_CALLS
  1905.     C_typedef_like();
  1906. #else
  1907.     @<Cases for |typedef_like| (C)@>@;
  1908. #endif
  1909.  
  1910. @
  1911. @<Part 1@>=
  1912. #if FCN_CALLS
  1913.     @[SRTN C_typedef_like(VOID)
  1914.         {
  1915.         @<Cases for |typedef_like| (C)@>@;
  1916.         }
  1917. #endif
  1918.  
  1919. @
  1920. @<Glob...@>=
  1921.  
  1922. IN_PROD boolean typedefing PSET(NO); // Are we inside a |typedef|?
  1923.  
  1924. @
  1925. @<Cases for |typedef_like| (C)@>=
  1926. {
  1927. if (cat1==decl_hd && (cat2==expr || cat2 == int_like))
  1928.     {
  1929.     make_underlined(pp+2); make_reserved(pp+2); /* NEEDS TO BE IMPROVED! */
  1930.     b_app2(pp+1);
  1931.     REDUCE(pp+1,2,decl_hd,0,90);
  1932.     }
  1933. else if(cat1==decl)
  1934.     {
  1935.     PP_PP(1,1);
  1936.     REDUCE(pp,2,decl,-1,91);
  1937.     }
  1938. else if(cat1==semi)
  1939.     SQUASH(pp, 2, stmt, -1, 94); 
  1940.         /* ``|typedef|''. */
  1941. else if(cat1==stmt)
  1942.     {
  1943.     PP_PP(1,1);
  1944.     REDUCE(pp, 2, stmt, -1, 95);  
  1945.         /* ``|typedef int I[3]|''. (|I| is defined in first pass.) */
  1946.     }
  1947.     
  1948. }
  1949.  
  1950. @<CASES for |imp_reserved| (C)@>=
  1951. #if FCN_CALLS
  1952.     C_imp_reserved();
  1953. #else
  1954.     @<Cases for |imp_reserved| (C)@>@;
  1955. #endif
  1956.  
  1957. @
  1958. @<Part 1@>=
  1959. #if FCN_CALLS
  1960.     @[SRTN C_imp_reserved(VOID)
  1961.         {
  1962.         @<Cases for |imp_reserved| (C)@>@;
  1963.         }
  1964. #endif
  1965.  
  1966. @ The special type |imp_reserved| is needed for forward referencing, but
  1967. when it's encountered within a |typedef| it should be interpreted as an
  1968. expression. 
  1969. @<Cases for |imp_reserved| (C)@>=
  1970. {
  1971. if(typedefing) SQUASH(pp,1,expr,-2,92);
  1972. else SQUASH(pp,1,int_like,-2,93);
  1973. }
  1974.  
  1975. @ In \Cpp, operator overloading has a somewhat unusual syntax, in that
  1976. constructions like |operator -=| plays the role of a function name.
  1977.  
  1978. @d MAX_OP_TOKENS 5 /* Maximum \# of tokens that could conceivably make up
  1979.     the function name. */
  1980.  
  1981. @<CASES for |op_like| (C)@>=
  1982. #if FCN_CALLS
  1983.     C_op_like();
  1984. #else
  1985.     @<Cases for |op_like| (C)@>@;
  1986. #endif
  1987.  
  1988. @
  1989. @<Part 1@>=
  1990. #if FCN_CALLS
  1991.     @[SRTN C_op_like(VOID)
  1992.         {
  1993.         @<Cases for |op_like| (C)@>@;
  1994.         }
  1995. #endif
  1996.  
  1997. @
  1998. @<Cases for |op_like| (C)@>=
  1999. {
  2000. short n; 
  2001.  // The actual number of tokens that make up the effective function name. 
  2002.  
  2003. if((cat1==lpar && cat2==rpar) || (cat1==lbracket && cat2==rbracket))
  2004.     { /* |@c++ operator ()()|  is a special case because it begins with
  2005. left paren.  |@c++ operator []()| is handled as a special case because we
  2006. now have the categories |lbracket| and |rbracket|, and |lbracket| doesn't
  2007. regress when it's reduced to |lpar|. */
  2008.     PP_PP(1,1);
  2009.     @<Append thinspace@>@;
  2010.     b_app1(pp+2);
  2011.     n = 3;
  2012.     }
  2013. else
  2014.     { /* We'll search for the obligatory left paren that indicates the
  2015. argument list. */
  2016.     scrap_pointer q;
  2017.     int k; /* Counter. */
  2018.  
  2019. /* If the paren is missing, we could end up appending the entire rest of
  2020. the code, so we limit the search. */
  2021.     for(q = pp+1; q <= scrp_ptr && q-pp <= MAX_OP_TOKENS; q++)
  2022.         if(q->cat == lpar) break;
  2023.  
  2024.     n = (q->cat == lpar) ? PTR_DIFF(short, q, pp) : 0;
  2025.  
  2026. /* Append all the tokens between |operator| and left paren. */
  2027.     if(n > 0)
  2028.         {
  2029.         text_pointer xp;
  2030.         token_pointer tp,tp1;
  2031.  
  2032.         b_app1(pp); @~ b_app(@' '); /* |operator| */
  2033.         b_app(@'{'); /* Braces prevent possible spurious blanks
  2034. before the left paren. */
  2035.  
  2036.         id_first = id_loc = mod_text + 1;
  2037.  
  2038.         for(k=1; k<n; k++)
  2039.             {
  2040.             b_app1(pp+k);
  2041.  
  2042.             xp = indirect((pp+k)->trans);
  2043.             tp = *xp;
  2044.             tp1 = *(xp+1);
  2045.             while(tp < tp1)
  2046.                 *id_loc++ = (ASCII)(*tp++);
  2047.             }
  2048.  
  2049.         underline_xref(id_lookup(id_first,id_loc,0));
  2050.  
  2051.         b_app(@'}');
  2052.         }
  2053.     }
  2054.  
  2055. if(n > 0) 
  2056.     REDUCE(pp, n, expr, -2, 6666);
  2057. }
  2058.     
  2059. @ |@c++ class| is almost like |struct|, but it has to reserve the class name.
  2060. (Note that it might have been declared earlier, hence the |int_like| option.)
  2061.  
  2062. @<CASES for |class_like| (C)@>=
  2063. #if FCN_CALLS
  2064.     C_class_like();
  2065. #else
  2066.     @<Cases for |class_like| (C)@>@;
  2067. #endif
  2068.  
  2069. @
  2070. @<Part 1@>=
  2071. #if FCN_CALLS
  2072.     @[SRTN C_class_like(VOID)
  2073.         {
  2074.         @<Cases for |class_like| (C)@>@;
  2075.         }
  2076. #endif
  2077.  
  2078. @
  2079. @<Cases for |class_like| (C)@>=
  2080. {
  2081. if(cat1==expr || cat1==int_like)
  2082.     { /* \Cpp: |@c++ class A| */
  2083.     make_underlined(pp+1); @~ make_reserved(pp+1);
  2084.  
  2085.     PP_PP(1,1);
  2086.  
  2087.     if((pp-1)->cat == tstart || (pp-1)->cat == decl_hd)
  2088.         REDUCE(pp, 2, decl_hd, -1, 8998);
  2089.     else
  2090.         REDUCE(pp, 2, struct_like, 0, 8999);
  2091.     }
  2092. else if(cat1==lbrace)
  2093.     SQUASH(pp, 1, struct_like, 0, 8987); 
  2094.         // |@c++ class{}| or |@c++ struct{}|.
  2095. }
  2096.  
  2097. @ Deal with beginning of a structure.
  2098.  
  2099. @<CASES for |struct_like| (C)@>=
  2100. #if FCN_CALLS
  2101.     C_struct_like();
  2102. #else
  2103.     @<Cases for |struct_like| (C)@>@;
  2104. #endif
  2105.  
  2106. @
  2107. @<Part 1@>=
  2108. #if FCN_CALLS
  2109.     @[SRTN C_struct_like(VOID)
  2110.         {
  2111.         @<Cases for |struct_like| (C)@>@;
  2112.         }
  2113. #endif
  2114.  
  2115. @
  2116. @c++
  2117. @f base int
  2118. @f derived int
  2119. @<Cases for |struct_like| (C)@>=
  2120. {
  2121. if (cat1==lbrace)
  2122.     {  /* ``|struct {int i;} S;|'' or \Cpp: ``|@c++ class A{int i;};|'' */
  2123.     b_app1(pp); @~ indent_force;    
  2124.     b_app1(pp+1); REDUCE(pp,2,struct_hd,0,100);
  2125.     }
  2126. else if (cat1==expr) 
  2127.     { /* Structure name: ``|struct s|'' */
  2128.     if (cat2==lbrace) /* ``|struct s {}|'' */
  2129.         {
  2130. /* In \Cpp, this construction defines a new type. */
  2131.         if(Cpp) 
  2132.             {make_underlined(pp+1); @~ make_reserved(pp+1);}
  2133.  
  2134.         PP_PP(1,1);
  2135.         indent_force;
  2136.         b_app1(pp+2);
  2137.         REDUCE(pp,3,struct_hd,0,101);
  2138.         }
  2139.       else /* ``|struct s ss|'' */
  2140.         {
  2141.         b_app1(pp); b_app(@' '); b_app1(pp+1); 
  2142.         REDUCE(pp,2,int_like,-1,102);
  2143.         }
  2144.     }
  2145. else if(cat1==colon && cat2==int_like && Cpp)
  2146.     { /* |@c++ class A: base| */
  2147.     if(cat3==langle)
  2148.         SQUASH(pp, 1, struct_like, PLUS 3, 1023);
  2149.     else
  2150.         {
  2151.         b_app1(pp); @~ b_app(@' '); @~ b_app1(pp+1); @~ b_app(@' '); @~
  2152.             b_app1(pp+2);
  2153.         REDUCE(pp,3,struct_like,0,1021);
  2154.         }
  2155.     }
  2156. else if(cat1==comma && cat2==int_like && Cpp)
  2157.     { /* |@c++ class A: base, base | */
  2158.     if(cat3==langle)
  2159.         SQUASH(pp, 1, struct_like, PLUS 3, 1024);
  2160.     else
  2161.         {
  2162.         PP_PP(2, 1);
  2163.         REDUCE(pp,3,struct_like,0,1022);
  2164.         }
  2165.     }
  2166. else if(cat1==tlist)
  2167.     SQUASH(pp, 2, struct_like, 0, 1025); // \Cpp: |@c++ class A<int>|.
  2168. else if(cat1==semi) 
  2169.     SQUASH(pp,2,decl,-1,103); /* \Cpp: |@c++ class base;| */
  2170. else if(cat1 == rangle)
  2171.     SQUASH(pp, 1, decl_hd, -2, 592); /* \Cpp:  end of template. */
  2172. }
  2173.  
  2174. @ Handle ``|enum{red,yellow}|;''.
  2175. @<CASES for |struct_hd| (C)@>=
  2176. #if FCN_CALLS
  2177.     C_str_hd();
  2178. #else
  2179.     @<Cases for |struct_hd| (C)@>@;
  2180. #endif
  2181.  
  2182. @
  2183. @<Part 1@>=
  2184. #if FCN_CALLS
  2185.     @[SRTN C_str_hd(VOID)
  2186.         {
  2187.         @<Cases for |struct_hd| (C)@>@;
  2188.         }
  2189. #endif
  2190.  
  2191. @
  2192. @<Cases for |struct_hd| (C)@>=
  2193. {
  2194. if ((cat1==decl || cat1==stmt
  2195.  || cat1==expr /*  (For enum) */
  2196.  || cat1==functn /* \Cpp */
  2197. ) && cat2==rbrace) 
  2198.     {
  2199.     b_app1(pp); /* ``|struct {|'' */
  2200.     b_app(force); b_app1(pp+1); /* Body */
  2201.     b_app(force);  b_app1(pp+2); /* ``|}|'' */
  2202.     b_app(outdent); 
  2203. @#if 0
  2204.     b_app(break_space);
  2205. @#endif
  2206.     REDUCE(pp,3,int_like,-1,110);
  2207.     }
  2208. else if(cat1==rbrace)
  2209.     {
  2210.     b_app1(pp); @~ @<Append thin...@>@; b_app1(pp+1);
  2211.     b_app(outdent);
  2212.     REDUCE(pp,2,int_like,-1,1101);
  2213.     }
  2214. }
  2215.  
  2216. @<CASES for |lpar| (C)@>=
  2217. #if FCN_CALLS
  2218.     C_lpar();
  2219. #else
  2220.     @<Cases for |lpar| (C)@>@;
  2221. #endif
  2222.  
  2223. @
  2224. @<Part 1@>=
  2225. #if FCN_CALLS
  2226.     @[SRTN C_lpar(VOID)
  2227.         {
  2228.         @<Cases for |lpar| (C)@>@;
  2229.         }
  2230. #endif
  2231.  
  2232. @
  2233. @<Cases for |lpar| (C)@>=
  2234. {
  2235. if (cat2==rpar && (cat1==expr || cat1==unorbinop)) 
  2236.     SQUASH(pp,3,expr,-2,120); /* ``|(x)|''  or ``|(*)|''*/
  2237. else if (cat1==rpar) 
  2238.     { /* ``|()|''. This looks better with a bit of extra space between
  2239.         the parens. */ 
  2240.       b_app1(pp); @~ @<Append thickspace@>; @~ b_app1(pp+1);
  2241.       REDUCE(pp,2,expr,-2,121);
  2242.     }
  2243. else if ((cat1==decl_hd) && cat2==rpar)
  2244.     { /* Function prototype or cast, like ``|typedef (*T)|'' where |T|
  2245.         was |typedef|d on the first pass. */
  2246.     b_app3(pp);
  2247.  
  2248.     OUTDENT;
  2249.  
  2250.     if(in_prototype) 
  2251.         in_prototype--;
  2252.  
  2253.     REDUCE(pp,3,cast,-1,122);
  2254.     }
  2255. else if (cat1==stmt)
  2256.     { /* ``|for(x;y;z)|'' */
  2257.     b_app2(pp); b_app(@' '); REDUCE(pp,2,lpar,0,123);
  2258.     }
  2259. else if(cat1==for_like && cat2==rpar) 
  2260.     SQUASH(pp,3,expr,-2,1201); /* Macros: |(for)| */ 
  2261. }
  2262.  
  2263. @<CASES for |lbracket| (C)@>=
  2264. #if FCN_CALLS
  2265.     C_lbracket();
  2266. #else
  2267.     @<Cases for |lbracket| (C)@>@;
  2268. #endif
  2269.  
  2270. @
  2271. @<Part 1@>=
  2272. #if FCN_CALLS
  2273.     @[SRTN C_lbracket(VOID)
  2274.         {
  2275.         @<Cases for |lbracket| (C)@>@;
  2276.         }
  2277. #endif
  2278.  
  2279. @
  2280. @<Cases for |lbracket| (C)@>=
  2281. {
  2282. if(active_brackets)
  2283.     {
  2284.     b_app(@'\\');
  2285.     APP_STR("WXA{");
  2286.     }
  2287. else b_app1(pp);
  2288.  
  2289. REDUCE(pp,1,lpar,0,5000);
  2290. }
  2291.  
  2292. @<CASES for |rbracket| (C)@>=
  2293. #if FCN_CALLS
  2294.     C_rbracket();
  2295. #else
  2296.     @<Cases for |rbracket| (C)@>@;
  2297. #endif
  2298.  
  2299. @
  2300. @<Part 1@>=
  2301. #if FCN_CALLS
  2302.     @[SRTN C_rbracket(VOID)
  2303.         {
  2304.         @<Cases for |rbracket| (C)@>@;
  2305.         }
  2306. #endif
  2307.  
  2308. @
  2309. @<Cases for |rbracket| (C)@>=
  2310. {
  2311. if(active_brackets) 
  2312.     {
  2313.     text_pointer t = indirect(pp->trans);
  2314.  
  2315.     if(**t == @']') **t = @'}';
  2316.     }
  2317.  
  2318. b_app1(pp);
  2319.  
  2320. REDUCE(pp,1,rpar,-3,5001);
  2321. }
  2322.  
  2323. @<CASES for |lbrace| (C)@>=
  2324. #if FCN_CALLS
  2325.     C_lbrace();
  2326. #else
  2327.     @<Cases for |lbrace| (C)@>@;
  2328. #endif
  2329.  
  2330. @
  2331. @<Part 1@>=
  2332. #if FCN_CALLS
  2333.     @[SRTN C_lbrace(VOID)
  2334.         {
  2335.         @<Cases for |lbrace| (C)@>@;
  2336.         }
  2337. #endif
  2338.  
  2339. @
  2340. @<Cases for |lbrace| (C)@>=
  2341. {
  2342. if (cat1==rbrace)  /* ``|{}|'' */
  2343.     {
  2344.     b_app1(pp); @~ @<Append thinspace@>; @~ b_app1(pp+1); 
  2345.     REDUCE(pp,2,stmt,-1,130);
  2346.     }
  2347. else if ((cat1==stmt || cat1==decl || cat1==functn) && cat2==rbrace)  
  2348.     /* ``|{x;}|''  or \dots\ or \Cpp:  |@c++ main(){try{}catch(){}}| */
  2349.     {
  2350.     b_app(force);
  2351.     b_app1(pp);  /* ``|{|'' */
  2352.     b_app(force);
  2353.     b_app1(pp+1); /* Body */
  2354.     b_app(force); 
  2355.     b_app1(pp+2); /* ``|}|'' */
  2356.     REDUCE(pp,3,stmt,-1,131);
  2357.     }
  2358. else if (cat1==expr) 
  2359.     {
  2360.     if (cat2==rbrace) 
  2361.         SQUASH(pp,3,expr,-2,132); /* ``|enum{red}|'' */
  2362.     else if (cat2==comma && cat3==rbrace) 
  2363.         SQUASH(pp,4,expr,-2,132);
  2364.     }
  2365. }
  2366.  
  2367. @<CASES for |unop| (C)@>=
  2368. #if FCN_CALLS
  2369.     C__unop();
  2370. #else
  2371.     @<Cases for |unop| (C)@>@;
  2372. #endif
  2373.  
  2374. @
  2375. @<Part 1@>=
  2376. #if FCN_CALLS
  2377.     @[SRTN C__unop(VOID)
  2378.         {
  2379.         @<Cases for |unop| (C)@>@;
  2380.         }
  2381. #endif
  2382.  
  2383. @
  2384. @<Cases for |unop| (C)@>=
  2385. {
  2386. if (cat1==expr) 
  2387.     SQUASH(pp,2,expr,-2,140); /* ``|!x|'' or ``|++x|'' */
  2388. else if(cat1==int_like) 
  2389.     SQUASH(pp,2,int_like,0,141); /* \Cpp\ destructor:
  2390.             ``|@c++ ~base|'' */ 
  2391. }
  2392.  
  2393. @<CASES for |unorbinop| (C)@>=
  2394. #if FCN_CALLS
  2395.     C_unorbinop();
  2396. #else
  2397.     @<Cases for |unorbinop| (C)@>@;
  2398. #endif
  2399.  
  2400. @
  2401. @<Part 1@>=
  2402. #if FCN_CALLS
  2403.     @[SRTN C_unorbinop(VOID)
  2404.         {
  2405.         @<Cases for |unorbinop| (C)@>@;
  2406.         }
  2407. #endif
  2408.  
  2409. @
  2410. @<Cases for |unorbinop| (C)@>=
  2411. {
  2412. if(cat1==expr || (cat1==int_like && !(cat2 == lpar || cat2 == unop)) )
  2413.     {  /* ``|*p|'' or ``|&x|''; ``|typedef
  2414.         (*T)|'' where |T| was |typedef|d on the first pass.  Not
  2415. \Cpp:  ``|@c++ x + int(i)|'' or ``|@c++ x + base::y|''. */
  2416.     b_app(@'{'); @~b_app1(pp); @~ b_app(@'}'); 
  2417.     b_app1(pp+1); 
  2418.     REDUCE(pp,2,cat1,-2,150);
  2419.     }
  2420. else if (cat1==binop) 
  2421.     @<Reduce cases like |*=|@>@;
  2422. }
  2423.  
  2424. @
  2425. @<Reduce cases like |*=|@>=
  2426. {
  2427.   b_app(math_bin); 
  2428. b_app1(pp); 
  2429. b_app(@'{'); @~ b_app1(pp+1); @~ b_app(@'}');
  2430.   b_app(@'}'); /* End |math_bin| */
  2431.   REDUCE(pp,2,binop,-1,151);
  2432. }
  2433.  
  2434. @<CASES for |cast| (C)@>=
  2435. #if FCN_CALLS
  2436.     C_cast();
  2437. #else
  2438.     @<Cases for |cast| (C)@>@;
  2439. #endif
  2440.  
  2441. @
  2442. @<Part 1@>=
  2443. #if FCN_CALLS
  2444.     @[SRTN C_cast(VOID)
  2445.         {
  2446.         @<Cases for |cast| (C)@>@;
  2447.         }
  2448. #endif
  2449.  
  2450. @
  2451. @<Cases for |cast| (C)@>=
  2452. {
  2453. if (cat1==expr)  /* ``|(int *)p|'' */
  2454.     {
  2455.     b_app1(pp); @~ @<Append thinspace@>; @~ b_app1(pp+1); 
  2456.     REDUCE(pp,2,expr,-2,160);
  2457.     }
  2458. else if(cat1 == unorbinop || cat1 == reference)
  2459.     SQUASH(pp, 1, cast, PLUS 1, 162); // ``|(int *)&prms|''.
  2460. else 
  2461.     SQUASH(pp,1,expr,-2,161); // Turn function prototype into expression.
  2462. }
  2463.  
  2464. @<CASES for |sizeof_like| (C)@>=
  2465. #if FCN_CALLS
  2466.     C_sizeof_like();
  2467. #else
  2468.     @<Cases for |sizeof_like| (C)@>@;
  2469. #endif
  2470.  
  2471. @
  2472. @<Part 1@>=
  2473. #if FCN_CALLS
  2474.     @[SRTN C_sizeof_like(VOID)
  2475.         {
  2476.         @<Cases for |sizeof_like| (C)@>@;
  2477.         }
  2478. #endif
  2479.  
  2480. @
  2481. @<Cases for |sizeof_like| (C)@>=
  2482. {
  2483. if (cat1==cast) 
  2484.     SQUASH(pp,2,expr,-2,170); /* ``|sizeof (int *)|'' */
  2485. else if (cat1==expr) 
  2486.     SQUASH(pp,2,expr,-2,171); /* ``|sizeof(x)|'' */
  2487. }
  2488.  
  2489. @<CASES for |binop| (C)@>=
  2490. #if FCN_CALLS
  2491.     C__binop();
  2492. #else
  2493.     @<Cases for |binop| (C)@>@;
  2494. #endif
  2495.  
  2496. @
  2497. @<Part 1@>=
  2498. #if FCN_CALLS
  2499.     @[SRTN C__binop(VOID)
  2500.         {
  2501.         @<Cases for |binop| (C)@>@;
  2502.         }
  2503. #endif
  2504.  
  2505. @
  2506. @<Cases for |binop| (C)@>=
  2507. {
  2508. if (cat1==binop) 
  2509.     @<Reduce cases like |+=|@>@; /* ``|+=|'' */
  2510. else if(cat1==space)
  2511.     {
  2512.     b_app1(pp); // We eat the space in this macro situation.
  2513.     REDUCE(pp, 2, binop, -1, 181); // |#if(a == b)|.
  2514.     }
  2515. else if(Cpp && cat1==decl_hd)
  2516.     SQUASH(pp, 2, tstart, 0, 6063);
  2517.         /* Trap for ``|@c++ A<int>|'', with |A| undefined.  See
  2518.             also Rule 6061. */
  2519. }
  2520.  
  2521. @
  2522. @<Reduce cases like |+=|@>=
  2523. {
  2524.   b_app(math_bin); b_app1(pp); 
  2525. b_app(@'{'); @~ b_app1(pp+1); @~ b_app(@'}');
  2526.   b_app(@'}'); /* End |math_bin| */
  2527.   REDUCE(pp,2,binop,-1,180);
  2528. }
  2529.  
  2530. @<CASES for |do_like| (C)@>=
  2531. #if FCN_CALLS
  2532.     C_do_like();
  2533. #else
  2534.     @<Cases for |do_like| (C)@>@;
  2535. #endif
  2536.  
  2537. @
  2538. @<Part 1@>=
  2539. #if FCN_CALLS
  2540.     @[SRTN C_do_like(VOID)
  2541.         {
  2542.         @<Cases for |do_like| (C)@>@;
  2543.         }
  2544. #endif
  2545.  
  2546. @
  2547. @<Cases for |do_like| (C)@>=
  2548. {
  2549. if (cat1==stmt)
  2550.     if(cat2==for_like)
  2551.         {
  2552.         cat2 = while_do;
  2553.         SQUASH(pp, 1, do_like, PLUS 2, 191);
  2554.         }
  2555.     else if(cat2==expr && cat3==semi)
  2556.         { /* ``|do {} while(flag);|'' */
  2557.         b_app1(pp); // ``\&{do}''
  2558.         indent_force;
  2559.            b_app1(pp+1); // stmt 
  2560.         b_app(outdent);
  2561.         b_app(force);
  2562.         b_app2(pp+2); // ``\&{while}\dots''
  2563.         REDUCE(pp,4,stmt,-1,190);
  2564.         }
  2565.     }
  2566.  
  2567. @
  2568. @<CASES for |while_do| (C)@>=
  2569. #if FCN_CALLS
  2570.     C_wh_do();
  2571. #else
  2572.     @<Cases for |while_do| (C)@>@;
  2573. #endif
  2574.  
  2575. @
  2576. @<Part 1@>=
  2577. #if FCN_CALLS
  2578.     @[SRTN C_wh_do(VOID)
  2579.         {
  2580.         @<Cases for |while_do| (C)@>@;
  2581.         }
  2582. #endif
  2583.  
  2584. @
  2585. @<Cases for |while_do| (C)@>=
  2586. {
  2587. b_app1(pp);
  2588. @<Append thinspace@>;
  2589. REDUCE(pp, 1, expr, 0, 192);
  2590. }
  2591.  
  2592. @ Identifiers that are |for_like| must in normal usage be followed by a
  2593. parenthesized expression. However, since they might be used in isolation in
  2594. a macro argument, we allow a default possibility.
  2595.  
  2596. @<CASES for |for_like| (C)@>=
  2597. #if FCN_CALLS
  2598.     C_for_like();
  2599. #else
  2600.     @<Cases for |for_like| (C)@>@;
  2601. #endif
  2602.  
  2603. @
  2604. @<Part 1@>=
  2605. #if FCN_CALLS
  2606.     @[SRTN C_for_like(VOID)
  2607.         {
  2608.         @<Cases for |for_like| (C)@>@;
  2609.         }
  2610. #endif
  2611.  
  2612. @
  2613. @<Cases for |for_like| (C)@>=
  2614. {
  2615. if (cat1==expr)
  2616.     { /* ``\&{for}\dots'' */
  2617.     b_app1(pp); @~ @<Append thinspace@>;  @~ b_app1(pp+1); 
  2618.     b_app(@' ');
  2619.  
  2620.     if(cat2==semi)
  2621.         { /* ``|for(;;);|'' */
  2622.         if(!auto_semi || (auto_semi && cat3==semi))
  2623.             {
  2624.             indent_force;
  2625.             b_app1(pp+2); // Semi on separate line.
  2626.             b_app(outdent);
  2627.             REDUCE(pp,3,stmt,-2,200); /*  The $-2$ is for the
  2628. \&{do} case. Also get here from Ratfor's \&{until}. */ 
  2629.             }
  2630.         else 
  2631.             REDUCE(pp,3,for_hd,0,2011); // Eat the |auto_semi|.
  2632.         }
  2633.     else 
  2634.         REDUCE(pp,2,for_hd,0,201); // Eat the arguments.
  2635.     }
  2636. else if(cat1 != lpar) 
  2637.     SQUASH(pp,1,expr,0,2010); // Default possiblity.
  2638. }
  2639.  
  2640. @<CASES for |for_hd| (C)@>=
  2641. #if FCN_CALLS
  2642.     C_forhd();
  2643. #else
  2644.     @<Cases for |for_hd| (C)@>@;
  2645. #endif
  2646.  
  2647. @
  2648. @<Part 1@>=
  2649. #if FCN_CALLS
  2650.     @[SRTN C_forhd(VOID)
  2651.         {
  2652.         @<Cases for |for_hd| (C)@>@;
  2653.         }
  2654. #endif
  2655.  
  2656. @
  2657. @<Cases for |for_hd| (C)@>=
  2658. {
  2659. if (cat1==stmt)
  2660.     { /* ``|for(;;) x;|'' */
  2661.     b_app1(pp); 
  2662.     indent_force;
  2663.        b_app1(pp+1);
  2664.     b_app(outdent);
  2665.     REDUCE(pp,2,stmt,-1,210);
  2666.     }
  2667. }
  2668.  
  2669. @ Begin an \&{if} statement by just absorbing the argument in parentheses.
  2670. We check to see if there's a comment coming up, and set a flag. We have to
  2671. do that here because |ignore_scrap| is digested before the big switch.
  2672.  
  2673. @<CASES for |if_like| (C)@>=
  2674. #if FCN_CALLS
  2675.     C_if_like();
  2676. #else
  2677.     @<Cases for |if_like| (C)@>@;
  2678. #endif
  2679.  
  2680. @
  2681. @<Part 1@>=
  2682. #if FCN_CALLS
  2683.     @[SRTN C_if_like(VOID)
  2684.         {
  2685.         @<Cases for |if_like| (C)@>@;
  2686.         }
  2687. #endif
  2688.  
  2689. @
  2690. @<Cases for |if_like| (C)@>=
  2691. {
  2692. if (cat1==lpar && cat2==expr && cat3==rpar) /* ``|if(x)|'' */
  2693.     {
  2694.       b_app1(pp); @<Append thinspace@>;  b_app3(pp+1); 
  2695. #if(0)
  2696.     cmnt_after_IF = (cat4==ignore_scrap); /* Comment coming up? */
  2697. #endif
  2698.     REDUCE(pp,4,IF_like,0,220);
  2699.     }
  2700. }
  2701.  
  2702. @ We need a flag to tell us whether a comment (really, |ignore_scrap|)
  2703. follows an |if(x)| construction. If so, we'll put even simple statements on
  2704. the next line, properly indented. (Not working yet!)
  2705.  
  2706. @<Glob...@>=
  2707.  
  2708. @#if(0)
  2709.     IN_PROD cmnt_after_IF PSET(NO);
  2710. @#endif
  2711.  
  2712. @ Attach |stmt| to |if(x)|. Statements get indented on next line. 
  2713. If there's no \&{else} following, we're done.
  2714.  
  2715. @<CASES for |IF_like| (C)@>=
  2716. #if FCN_CALLS
  2717.     C_IF();
  2718. #else
  2719.     @<Cases for |IF_like| (C)@>@;
  2720. #endif
  2721.  
  2722. @
  2723. @<Part 1@>=
  2724. #if FCN_CALLS
  2725.     @[SRTN C_IF(VOID)
  2726.         {
  2727.         @<Cases for |IF_like| (C)@>@;
  2728.         }
  2729. #endif
  2730.  
  2731. @
  2732. @<Cases for |IF_like| (C)@>=
  2733. {
  2734. if(cat1==stmt
  2735.     || cat1==lbrace || cat1==if_like || cat1==for_like || cat1==do_like
  2736.         || cat1==Rdo_like
  2737. #if(0)
  2738.  || cmnt_after_IF
  2739. #endif
  2740.         )
  2741.     SQUASH(pp,1,if_hd,0,230); // |if_hd| does the indenting.
  2742. #if(0)
  2743. else if(cat1==stmt) 
  2744.     { /* Attach simple statement. */
  2745.     PP_PP(1,1);
  2746.     REDUCE(pp,2,IF_top,-1,231);
  2747.     }
  2748. #endif
  2749. }
  2750.  
  2751. @ The purpose here is to take a complete statement and indent it on the
  2752. next line. 
  2753. @<CASES for |if_hd| (C)@>=
  2754. #if FCN_CALLS
  2755.     C_if_hd();
  2756. #else
  2757.     @<Cases for |if_hd| (C)@>@;
  2758. #endif
  2759.  
  2760. @
  2761. @<Part 1@>=
  2762. #if FCN_CALLS
  2763.     @[SRTN C_if_hd(VOID)
  2764.         {
  2765.         @<Cases for |if_hd| (C)@>@;
  2766.         }
  2767. #endif
  2768.  
  2769. @
  2770. @<Cases for |if_hd| (C)@>=
  2771. {
  2772. if (cat1==stmt) /* ``|if(x) {}|'' */
  2773.     {
  2774.     b_app1(pp); /* ``|if(x)|'' */
  2775.     indent_force;
  2776.      b_app1(pp+1); /* ``|{}|'' */
  2777.     b_app(outdent);
  2778.     REDUCE(pp,2,IF_top,-1,233);
  2779.     }
  2780. else if(cat1==IF_top && cat2==else_like) 
  2781.     SQUASH(pp,1,if_hd,2,234);
  2782. }
  2783.  
  2784. @
  2785. @<CASES for |else_hd| (C)@>=
  2786. #if FCN_CALLS
  2787.     C_els_hd();
  2788. #else
  2789.     @<Cases for |else_hd| (C)@>@;
  2790. #endif
  2791.  
  2792. @
  2793. @<Part 1@>=
  2794. #if FCN_CALLS
  2795.     @[SRTN C_els_hd(VOID)
  2796.         {
  2797.         @<Cases for |else_hd| (C)@>@;
  2798.         }
  2799. #endif
  2800.  
  2801. @
  2802. @<Cases for |else_hd| (C)@>=
  2803. {
  2804. if (cat1==stmt) /* ``|if(x) {}|'' */
  2805.     {
  2806.     b_app1(pp); /* ``|if(x)|'' */
  2807.     indent_force;
  2808.      b_app1(pp+1); /* ``|{}|'' */
  2809.     b_app(outdent);
  2810.     REDUCE(pp,2,ELSE_like,-1,241);
  2811.     }
  2812. }
  2813.  
  2814. @<CASES for |else_like| (C)@>=
  2815. #if FCN_CALLS
  2816.     C_else();
  2817. #else
  2818.     @<Cases for |else_like| (C)@>@;
  2819. #endif
  2820.  
  2821. @
  2822. @<Part 1@>=
  2823. #if FCN_CALLS
  2824.     @[SRTN C_else(VOID)
  2825.         {
  2826.         @<Cases for |else_like| (C)@>@;
  2827.         }
  2828. #endif
  2829.  
  2830. @
  2831. @<Cases for |else_like| (C)@>=
  2832. {
  2833. if(cat1==if_like) /* ``|else if|'' */
  2834.     {
  2835.     PP_PP(1,1);
  2836.     REDUCE(pp,2,if_like,0,235);
  2837.     }
  2838. else if(cat1==stmt || cat1==lbrace || cat1==for_like || cat1==do_like)
  2839.     SQUASH(pp,1,else_hd,0,236); /* ``|else {}|'' */
  2840. #if 0 /* The following puts simple statement on same line. */
  2841. else if(cat1==stmt) /* ``|else z;|'' */
  2842.     {
  2843.     PP_PP(1,1);
  2844.     REDUCE(pp,2,ELSE_like,-1,237);
  2845.     }
  2846. #endif
  2847. }
  2848.  
  2849. @ This is commented out above.
  2850. @<CASES for |ELSE_like| (C)@>=
  2851. #if FCN_CALLS
  2852.     C_ELS();
  2853. #else
  2854.     @<Cases for |ELSE_like| (C)@>@;
  2855. #endif
  2856.  
  2857. @
  2858. @<Part 1@>=
  2859. #if FCN_CALLS
  2860.     @[SRTN C_ELS(VOID)
  2861.         {
  2862.         @<Cases for |ELSE_like| (C)@>@;
  2863.         }
  2864. #endif
  2865.  
  2866. @
  2867. @<Cases for |ELSE_like| (C)@>=
  2868.  
  2869. @
  2870. @<CASES for |IF_top| (C)@>=
  2871. #if FCN_CALLS
  2872.     C_IF_top();
  2873. #else
  2874.     @<Cases for |IF_top| (C)@>@;
  2875. #endif
  2876.  
  2877. @
  2878. @<Part 1@>=
  2879. #if FCN_CALLS
  2880.     @[SRTN C_IF_top(VOID)
  2881.         {
  2882.         @<Cases for |IF_top| (C)@>@;
  2883.         }
  2884. #endif
  2885.  
  2886. @
  2887. @<Cases for |IF_top| (C)@>=
  2888. {
  2889. if(cat1==else_like || cat1==else_hd) 
  2890.     SQUASH(pp,1,IF_top,1,242); /* Expand ahead. */ 
  2891. else if(cat1==IF_top)
  2892.     {
  2893.     b_app1(pp); /* \&{if}\dots */
  2894.     b_app(force);
  2895.     b_app1(pp+1); /* \&{else if}\dots */
  2896.     REDUCE(pp,2,IF_top,-1,238);
  2897.     }
  2898. else if(cat1==ELSE_like)
  2899.     {
  2900.     b_app1(pp); /* \&{if} */
  2901.     b_app(force);
  2902.     b_app1(pp+1); /* \&{else} */
  2903.     REDUCE(pp,2,stmt,-1,239);
  2904.     }
  2905. else if(cat1==IF_like && (cat2==expr || cat2==stmt))
  2906.     SQUASH(pp,1,IF_top,1,241);
  2907. else 
  2908.     SQUASH(pp,1,stmt,-1,240);
  2909. }
  2910.  
  2911. @<CASES for |stmt| (C)@>=
  2912. #if FCN_CALLS
  2913.     C_stmt();
  2914. #else
  2915.     @<Cases for |stmt| (C)@>@;
  2916. #endif
  2917.  
  2918. @
  2919. @<Part 1@>=
  2920. #if FCN_CALLS
  2921.     @[SRTN C_stmt(VOID)
  2922.         {
  2923.         @<Cases for |stmt| (C)@>@;
  2924.         }
  2925. #endif
  2926.  
  2927. @
  2928. @<Cases for |stmt| (C)@>=
  2929. {
  2930. if (cat1==stmt || (Cpp && cat1==decl)) /* ``|x; y;|'' */
  2931.     {
  2932.       b_app1(pp); @~ b_app(force); 
  2933.        b_app1(pp+1); REDUCE(pp,2,stmt,-1,250);
  2934.     }
  2935. else if (cat1==functn)
  2936.     {
  2937.     b_app1(pp); @~ b_app(big_force);
  2938.     b_app1(pp+1);
  2939.     REDUCE(pp,2,stmt,-1,251);
  2940.     }
  2941. }
  2942.  
  2943. @<CASES for |case_like| (C)@>=
  2944. #if FCN_CALLS
  2945.     C_case_like();
  2946. #else
  2947.     @<Cases for |case_like| (C)@>@;
  2948. #endif
  2949.  
  2950. @
  2951. @<Part 1@>=
  2952. #if FCN_CALLS
  2953.     @[SRTN C_case_like(VOID)
  2954.         {
  2955.         @<Cases for |case_like| (C)@>@;
  2956.         }
  2957. #endif
  2958.  
  2959. @
  2960. @<Cases for |case_like| (C)@>=
  2961. {
  2962. if (cat1==semi) 
  2963.     SQUASH(pp,2,stmt,-1,260); /* |return;| */
  2964. else if (cat1==colon) 
  2965.     SQUASH(pp,2,tag,-1,261); /* |default:| or \Cpp: |@c++ public:| */
  2966. else if (cat1==expr) 
  2967.     {
  2968.       if (cat2==semi) /* |return x;| */
  2969.         {
  2970.         PP_PP(1,2);
  2971.         REDUCE(pp,3,stmt,-1,262);
  2972.         }
  2973.       else if (cat2==colon)  /* |case one:| */
  2974.         {
  2975.         PP_PP(1,2);
  2976.         REDUCE(pp,3,tag,-1,263);
  2977.         }
  2978.     }
  2979. else if(cat1==int_like)
  2980.     { /* \Cpp: |@c++ public base| */
  2981.     PP_PP(1,1);
  2982.     REDUCE(pp,2,int_like,-2,264);
  2983.     }
  2984. }
  2985.  
  2986. @<CASES for |tag| (C)@>=
  2987. #if FCN_CALLS
  2988.     C_tag();
  2989. #else
  2990.     @<Cases for |tag| (C)@>@;
  2991. #endif
  2992.  
  2993. @
  2994. @<Part 1@>=
  2995. #if FCN_CALLS
  2996.     @[SRTN C_tag(VOID)
  2997.         {
  2998.         @<Cases for |tag| (C)@>@;
  2999.         }
  3000. #endif
  3001.  
  3002. @
  3003. @<Cases for |tag| (C)@>=
  3004. {
  3005. if (cat1==tag) /* ``|case one: case two:|'' */
  3006.     {
  3007.       b_app1(pp); 
  3008.       b_app(force);
  3009.       b_app(backup);
  3010.       b_app1(pp+1); REDUCE(pp,2,tag,-1,270);
  3011.     }
  3012. else if (cat1==stmt || cat1==decl || cat1==functn) /* ``|case one:
  3013.         break;|'' or \Cpp: ``|@c++ public: int constructor();|''  */
  3014.     {
  3015.     b_app(big_force); 
  3016.     b_app(backup); @~ b_app1(pp); @~ b_app(force);
  3017.     b_app1(pp+1); 
  3018.     REDUCE(pp,2,cat1,-1,271);
  3019.     }
  3020. }
  3021.  
  3022. @ To help distinguish a null statement, we preface the semicolon by a space.
  3023. @<CASES for |semi| (C)@>=
  3024. #if FCN_CALLS
  3025.     C_semi();
  3026. #else
  3027.     @<Cases for |semi| (C)@>@;
  3028. #endif
  3029.  
  3030. @
  3031. @<Part 1@>=
  3032. #if FCN_CALLS
  3033.     @[SRTN C_semi(VOID)
  3034.         {
  3035.         @<Cases for |semi| (C)@>@;
  3036.         }
  3037. #endif
  3038.  
  3039. @
  3040. @<Cases for |semi| (C)@>=
  3041. {
  3042. b_app(@' '); @~ b_app1(pp); 
  3043. REDUCE(pp,1,stmt,-1,280);
  3044. }
  3045.  
  3046. @
  3047. @<CASES for |template| (C++)@>=
  3048. #if FCN_CALLS
  3049.     C_template();
  3050. #else
  3051.     @<Cases for |template| (C++)@>@;
  3052. #endif
  3053.  
  3054. @
  3055. @<Part 1@>=
  3056. #if FCN_CALLS
  3057.     @[SRTN C_template(VOID)
  3058.         {
  3059.         @<Cases for |template| (C++)@>@;
  3060.         }
  3061. #endif
  3062.  
  3063. @
  3064. @<Cases for |template| (C++)@>=
  3065. {
  3066. if(cat1 == langle)
  3067.     SQUASH(pp, 1, template, PLUS 1, 6000);
  3068. else if(cat1 == tlist)
  3069.     {
  3070.     PP_PP(1, 1); @~ b_app(force);
  3071.     REDUCE(pp, 2, int_like, 0, 6001);
  3072.     }
  3073. }
  3074.  
  3075. @
  3076. @<CASES for |langle| (C++)@>=
  3077. #if FCN_CALLS
  3078.     C_langle();
  3079. #else
  3080.     @<Cases for |langle| (C++)@>@;
  3081. #endif
  3082.  
  3083. @
  3084. @<Part 1@>=
  3085. #if FCN_CALLS
  3086.     @[SRTN C_langle(VOID)
  3087.         {
  3088.         @<Cases for |langle| (C++)@>@;
  3089.         }
  3090. #endif
  3091.  
  3092. @ If the |langle| isn't grabbed up by |template|, it's just an ordinary
  3093. binary operator.
  3094. @<Cases for |langle| (C++)@>=
  3095. {
  3096. if((pp-1)->cat == template || (pp-1)->cat == int_like || (pp-1)->cat ==
  3097.         struct_like) 
  3098.     {
  3099.     b_app(@'\\');
  3100.     APP_STR("WLA "); // \.{\\WLA} $\equiv$ `$\WLA$'.
  3101.     REDUCE(pp, 1, tstart, 0, 6050); // Begining of template parameter list.
  3102.     }
  3103. else
  3104.     SQUASH(pp, 1, binop, -1, 6051);
  3105. }
  3106.  
  3107. @
  3108. @<CASES for |rangle| (C++)@>=
  3109. #if FCN_CALLS
  3110.     C_rangle();
  3111. #else
  3112.     @<Cases for |rangle| (C++)@>@;
  3113. #endif
  3114.  
  3115. @
  3116. @<Part 1@>=
  3117. #if FCN_CALLS
  3118.     @[SRTN C_rangle(VOID)
  3119.         {
  3120.         @<Cases for |rangle| (C++)@>@;
  3121.         }
  3122. #endif
  3123.  
  3124. @ If the |rangle| isn't grabbed up by |template|, it's just an ordinary
  3125. binary operator.
  3126. @<Cases for |rangle| (C++)@>=
  3127. {
  3128. SQUASH(pp, 1, binop, -1, 6052);
  3129. }
  3130.  
  3131. @
  3132. @<CASES for |tstart| (C++)@>=
  3133. #if FCN_CALLS
  3134.     C_tstart();
  3135. #else
  3136.     @<Cases for |tstart| (C++)@>@;
  3137. #endif
  3138.  
  3139. @
  3140. @<Part 1@>=
  3141. #if FCN_CALLS
  3142.     @[SRTN C_tstart(VOID)
  3143.         {
  3144.         @<Cases for |tstart| (C++)@>@;
  3145.         }
  3146. #endif
  3147.  
  3148. @
  3149. @<Cases for |tstart| (C++)@>=
  3150. {
  3151. if(cat2 == rangle && (cat1==int_like || cat1==decl_hd || cat1==expr 
  3152.         || cat1==unorbinop))
  3153.     {
  3154.     b_app2(pp);
  3155.     b_app(@'\\');
  3156.     APP_STR("WRA "); // Closing of template.
  3157.     OUTDENT;
  3158.     REDUCE(pp, 3, tlist, -1, 6060);
  3159.     }
  3160. }
  3161.  
  3162. @
  3163. @<CASES for |tlist| (C++)@>=
  3164. #if FCN_CALLS
  3165.     C_tlist();
  3166. #else
  3167.     @<Cases for |tlist| (C++)@>@;
  3168. #endif
  3169.  
  3170. @
  3171. @<Part 1@>=
  3172. #if FCN_CALLS
  3173.     @[SRTN C_tlist(VOID)
  3174.         {
  3175.         @<Cases for |tlist| (C++)@>@;
  3176.         }
  3177. #endif
  3178.  
  3179. @
  3180. @<Cases for |tlist| (C++)@>=
  3181.  
  3182. @
  3183. @<CASES for |namespace| (C++)@>=
  3184. #if FCN_CALLS
  3185.     C_namespace();
  3186. #else
  3187.     @<Cases for |namespace| (C++)@>@;
  3188. #endif
  3189.  
  3190. @
  3191. @<Part 1@>=
  3192. #if FCN_CALLS
  3193.     @[SRTN C_namespace(VOID)
  3194.         {
  3195.         @<Cases for |namespace| (C++)@>@;
  3196.         }
  3197. #endif
  3198.  
  3199. @
  3200. @<Cases for |namespace| (C++)@>=
  3201. {
  3202. if(cat1==expr || cat1==int_like)
  3203.     { /* \Cpp: |@c++ namespace A| */
  3204.     make_underlined(pp+1); @~ make_reserved(pp+1);
  3205.  
  3206.     PP_PP(1,1);
  3207.  
  3208.     REDUCE(pp, 2, fn_decl, 0, 7901);
  3209.     }
  3210. else if(cat1==lbrace)
  3211.     SQUASH(pp, 1, fn_decl, 0, 7902); // |@c++ namespace{}|
  3212. }
  3213.  
  3214. @
  3215. @<Glob...@>=
  3216.  
  3217. IN_PROD boolean forward_exp PSET(NO);
  3218.  
  3219. @* PRODUCTIONS for RATFOR and FORTRAN.
  3220. Note that in some cases we use the C~rules for \RATFOR\ as well.
  3221.  
  3222. @<Part 2@>=@[
  3223.  
  3224. SRTN 
  3225. R_productions(VOID)
  3226. {
  3227. switch (pp->cat) 
  3228.     {
  3229.     case ignore_scrap:  @<CASES for |ignore_scrap| (C)@>@; break;
  3230.     case expr: @<CASES for |expr| (R)@>@; @~ break;
  3231.     case key_wd: @<CASES for |key_wd| (R)@>@; @~ break;
  3232.     case exp_op: @<CASES for |exp_op| (R)@>@; @~ break;
  3233.     case _EXPR: @<CASES for |_EXPR| (C)@>@; @~ break;
  3234.     case _EXPR_: @<CASES for |_EXPR_| (C)@>@; @~ break;
  3235.     case EXPR_: @<CASES for |EXPR_| (C)@>@; @~ break;
  3236.     case lpar: @<CASES for |lpar| (R)@>@; @~ break;
  3237.     case lbracket: @<CASES for |lbracket| (C)@>@; @~ break;
  3238.     case rbracket: @<CASES for |rbracket| (C)@>@; @~ break;
  3239.     case unop: @<CASES for |unop| (R)@>@; @~ break;
  3240.     case UNOP: @<CASES for |UNOP| (C)@>@; @~ break;
  3241.     case unorbinop: @<CASES for |unorbinop| (R)@>@; @~ break;
  3242.     case binop: @<CASES for |binop| (R)@>@; @~ break;
  3243.     case BINOP: @<CASES for |BINOP| (C)@>@; @~ break;
  3244.     case slash_like: @<CASES for |slash_like| (R)@>@; @~ break;
  3245.     case colon: @<CASES for |colon| (R)@>@; @~ break;
  3246.     case program_like: @<CASES for |program_like| (R)@>@; @~ break;
  3247.     case struct_like: @<CASES for |struct_like| (R)@>@; @~ break;
  3248.     case struct_hd: @<CASES for |struct_hd| (R)@>@; @~ break;
  3249.     case op_like: @<CASES for |op_like| (R)@>@; @~ break;    
  3250.     case proc_like: @<CASES for |proc_like| (R)@>@; @~ break;
  3251.     case private_like: @<CASES for |private_like| (R)@>@; @~ break;
  3252.     case int_like: @<CASES for |int_like| (R)@>@; @~ break;
  3253.     case decl_hd: @<CASES for |decl_hd| (R)@>@; @~ break;
  3254.     case decl: @<CASES for |decl| (R)@>@; @~ break;
  3255.     case fn_decl: @<CASES for |fn_decl| (C)@>@; @~ break;
  3256.     case fcn_hd: @<CASES for |fcn_hd| (R)@>@; @~ break;
  3257.     case functn: @<CASES for |functn| (R)@>@; @~ break;
  3258.     case lbrace: @<CASES for |lbrace| (R)@>@; @~ break;
  3259.     case do_like: @<CASES for |do_like| (R)@>@; @~ break;
  3260.     case until_like: @<CASES for |until_like| (R)@>@; @~ break;
  3261.     case Rdo_like: @<CASES for |Rdo_like| (R)@>@; @~ break;
  3262.     case if_like: @<CASES for |if_like| (R)@>@; @~ break;
  3263.     case IF_like: @<CASES for |IF_like| (C)@>@; @~ break; /* The C form serves
  3264. both. */
  3265.     case IF_top: @<CASES for |IF_top| (C)@>@; @~ break;
  3266.     case endif_like: @<CASES for |endif_like| (R)@>@; @~ break;
  3267.     case end_like: @<CASES for |end_like| (R)@>@; @~ break;
  3268.     case END_like: @<CASES for |END_like| (R)@>@; @~ break;
  3269.     case go_like: @<CASES for |go_like| (R)@>@; @~ break;
  3270.     case for_like: @<CASES for |for_like| (C)@>@; @~ break;
  3271.     case for_hd: @<CASES for |for_hd| (C)@>@; @~ break; /* C serves both. */
  3272.     case else_like: @<CASES for |else_like| (R)@>@; @~ break;
  3273.     case else_hd: @<CASES for |else_hd| (C)@>@; @~ break;
  3274. @#if(0)
  3275.     case ELSE_like: @<CASES for |ELSE_like| (C)@>@; @~ break; /* C serves
  3276. both. */ 
  3277. @#endif
  3278.     case if_hd: @<CASES for |if_hd| (R)@>@; @~ break;
  3279.     case CASE_like: @<CASES for |CASE_like| (R)@>@; @~ break;
  3280.     case case_like: @<CASES for |case_like| (R)@>@; @~ break;
  3281.     case stmt: @<CASES for |stmt| (R)@>@; @~ break;
  3282.     case tag: @<CASES for |tag| (R)@>@; @~ break;
  3283.     case label: @<CASES for |label| (R)@>@; @~ break;
  3284.     case semi: @<CASES for |semi| (R)@>@; @~ break;
  3285.  
  3286.     case common_like: @<CASES for |common_like| (R)@>@; @~ break;
  3287.     case common_hd: @<CASES for |common_hd| (R)@>@; @~ break;
  3288.     case read_like: @<CASES for |read_like| (R)@>@; @~ break;
  3289.     case read_hd: @<CASES for |read_hd| (R)@>@; @~ break;
  3290.     case entry_like: @<CASES for |entry_like| (R)@>@; @~ break;
  3291.     case implicit_like: @<CASES for |implicit_like| (R)@>@; @~ break;
  3292.     case implicit_hd: @<CASES for |implicit_hd| (R)@>@; @~ break;
  3293.     case assign_like: @<CASES for |assign_like| (R)@>@; @~ break;
  3294.     case define_like: @<CASES for |define_like| (R)@>@; @~ break;
  3295.     case built_in: @<CASES for |built_in| (R)@>@; @~ break;
  3296.     case no_order: @<CASES for |no_order| (R)@>@; @~ break;
  3297.     case newline: @<CASES for |newline| (R)@>@; @~ break;
  3298.     case COMMA: @<CASES for |COMMA| (C)@>@; @~ break;
  3299.  
  3300.   }
  3301. }
  3302.  
  3303. @
  3304. @<CASES for |expr| (R)@>=
  3305. #if FCN_CALLS
  3306.     R_expr();
  3307. #else
  3308.     @<Cases for |expr| (R)@>@;
  3309. #endif
  3310.  
  3311. @
  3312. @<Part 2@>=
  3313. #if FCN_CALLS
  3314.     @[SRTN R_expr(VOID)
  3315.         {
  3316.         @<Cases for |expr| (R)@>@;
  3317.         }
  3318. #endif
  3319.  
  3320. @
  3321. @<Cases for |expr| (R)@>=
  3322. {
  3323. if (cat1==unop) SQUASH(pp,2,expr,-2,2);
  3324. else if ((cat1==binop || cat1==unorbinop || cat1==colon) && cat2==expr)
  3325. /* Here we have to worry about constructions such as `|@r #:0|'. */
  3326.     if(cat1==colon && (*pp->trans)[1]==(sixteen_bits)@'#')
  3327.         {
  3328.         b_app1(pp);
  3329.         APP_STR("\\Colon");
  3330.         b_app1(pp+2);
  3331.         REDUCE(pp,3,expr,-2,3333);
  3332.         }
  3333.     else SQUASH(pp,3,expr,-2,3); /* ``|@r x = y|'' or ``|@r x + y|'' or
  3334.                 ``|@r dimension a(0:100)|'' */ 
  3335. else if (cat1==comma && (cat2==expr || cat2==end_like))  /* Note |end_like|;
  3336.                     keyword in I/O. */
  3337.     {
  3338.       b_app2(pp);
  3339.     OPT9;
  3340.     b_app1(pp+2); REDUCE(pp,3,expr,-2,4);
  3341.     }
  3342. else if (cat1==expr)  SQUASH(pp,2,expr,-2,5); /* ``|@r f(x)|'' */
  3343. else if (cat1==semi) SQUASH(pp,2,stmt,-2,6); /* ``|@r x=y;|'' */
  3344. else if (cat1==colon && cat2==unorbinop &&
  3345.         (cat3==rpar || (active_brackets && cat3==rbracket)))
  3346.     SQUASH(pp,3,expr,-2,299);  /* ``|@r 0:*|'' */
  3347. else if (cat1==colon && cat2!= lpar) /* label */
  3348.     {
  3349.       make_underlined (pp);  SQUASH(pp,2,tag,0,7);
  3350.     }
  3351. else if (cat1==comma && cat2==int_like) /* For macro usage. */
  3352.     {
  3353.       b_app2(pp);
  3354.     OPT9;
  3355.     b_app1(pp+2); REDUCE(pp,3,int_like,-2,4444);
  3356.     }
  3357. }
  3358.  
  3359. @ This route may be unused now.
  3360. @<CASES for |key_wd| (R)@>=
  3361. #if FCN_CALLS
  3362.     R_key_wd();
  3363. #else
  3364.     @<Cases for |key_wd| (R)@>@;
  3365. #endif
  3366.  
  3367. @
  3368. @<Part 2@>=
  3369. #if FCN_CALLS
  3370.     @[SRTN R_key_wd(VOID)
  3371.         {
  3372.         @<Cases for |key_wd| (R)@>@;
  3373.         }
  3374. #endif
  3375.  
  3376. @
  3377. @<Cases for |key_wd| (R)@>=
  3378. {
  3379. SQUASH(pp,1,expr,-2,4445);
  3380. }
  3381.  
  3382. @ Exponentiation. We have to watch out for constructions like \.{x\^(a+b)},
  3383. which must be typeset |@r x^(a+b)|, and also the construction
  3384. \.{x\^y(z)}, which must be typeset |@r x^y(z)|.
  3385.  
  3386. @<CASES for |exp_op| (R)@>=
  3387. #if FCN_CALLS
  3388.     R_exp_op();
  3389. #else
  3390.     @<Cases for |exp_op| (R)@>@;
  3391. #endif
  3392.  
  3393. @
  3394. @<Part 2@>=
  3395. #if FCN_CALLS
  3396.     @[SRTN R_exp_op(VOID)
  3397.         {
  3398.         @<Cases for |exp_op| (R)@>@;
  3399.         }
  3400. #endif
  3401.  
  3402. @
  3403. @<Cases for |exp_op| (R)@>=
  3404. {
  3405. if(cat1==lpar) SQUASH(pp,1,exp_op,PLUS 1,2995); /* ``|@r x^(a+b)|'' */
  3406. else if(cat1==expr)
  3407.     if(cat2==lpar) SQUASH(pp,1,exp_op,PLUS 2,2996); /* Expand array
  3408. argument. */
  3409.     else if(cat2==expr) SQUASH(pp,1,exp_op,PLUS 1,2997); /* The expr is
  3410. the result of expanding the array argument. */
  3411.     else
  3412.         { /* It's now of the form |@r x^expr|; insert braces around
  3413. argument so \TeX\ understands. */ 
  3414.         b_app1(pp);
  3415.         b_app(@'{'); @~ b_app1(pp+1); @~ b_app(@'}');
  3416.         REDUCE(pp,2,expr,-1,2998);
  3417.         }
  3418. }
  3419.  
  3420. @ Keep track of where we are in the nested hierarchy of \Fortran\ program
  3421. units; for helping with |@r9 contains|.
  3422. @<Glob...@>=
  3423.  
  3424. IN_PROD int fcn_level PSET(0);
  3425.  
  3426. @ When we recognize the beginning of a program unit, we increment a counter.
  3427. @<CASES for |program_like| (R)@>=
  3428. #if FCN_CALLS
  3429.     R_program_like();
  3430. #else
  3431.     @<Cases for |program_like| (R)@>@;
  3432. #endif
  3433.  
  3434. @
  3435. @<Part 2@>=
  3436. #if FCN_CALLS
  3437.     @[SRTN R_program_like(VOID)
  3438.         {
  3439.         @<Cases for |program_like| (R)@>@;
  3440.         }
  3441. #endif
  3442.  
  3443. @
  3444. @<Cases for |program_like| (R)@>=
  3445.  
  3446. if(is_FORTRAN_(language))
  3447.     {
  3448.     if(cat1==expr && cat2==semi)
  3449.         {
  3450.         fcn_level++;
  3451.         b_app1(pp); @~ b_app(@' ');
  3452.         b_app(indent); @~ b_app2(pp+1); @~ b_app(outdent);
  3453.         defined_at(make_underlined(pp+1));
  3454.         REDUCE(pp,3,fcn_hd,-1,2999);
  3455.         }
  3456.     else if(cat1==no_order)
  3457.         { // |@r block data|
  3458.         PP_PP(1,1);
  3459.         REDUCE(pp,2,program_like,0,2997);
  3460.         }
  3461.     else if(cat1==semi)
  3462.         { // |@r block data;|
  3463.         fcn_level++;
  3464.         b_app1(pp);
  3465.         REDUCE(pp,2,fcn_hd,-1,2996);
  3466.         }
  3467.     }
  3468. else
  3469.     {
  3470.     fcn_level++;
  3471.     SQUASH(pp,1,int_like,-1,2998);
  3472.     }
  3473.  
  3474. @
  3475. @<CASES for |fcn_hd| (R)@>=
  3476. #if FCN_CALLS
  3477.     R_fcn_hd();
  3478. #else
  3479.     @<Cases for |fcn_hd| (R)@>@;
  3480. #endif
  3481.  
  3482. @
  3483. @<Part 2@>=
  3484. #if FCN_CALLS
  3485.     @[SRTN R_fcn_hd(VOID)
  3486.         {
  3487.         @<Cases for |fcn_hd| (R)@>@;
  3488.         }
  3489. #endif
  3490.  
  3491. @
  3492. @<Cases for |fcn_hd| (R)@>=
  3493. {
  3494. if(cat1==END_stmt)
  3495.     {
  3496.     b_app1(pp); @~ b_app(force);
  3497.     b_app1(pp+1);
  3498.     REDUCE(pp,2,functn,-1,7172);
  3499.     }
  3500. else if(cat1==stmt && cat2==END_stmt)
  3501.     {
  3502.     b_app1(pp); @~ b_app(force);
  3503.     b_app(indent);
  3504.         b_app1(pp+1); /* Body */
  3505.  
  3506.         if(fcn_level==0)
  3507.             {
  3508.             if(containing) b_app(big_force);
  3509.             while(containing)
  3510.                 {
  3511. #if(0)
  3512.                 b_app(outdent);
  3513. #endif
  3514.                 containing--;
  3515.                 }
  3516.             }
  3517.  
  3518.     b_app(outdent);
  3519.     b_app(force);
  3520.  
  3521.     b_app1(pp+2);
  3522.     REDUCE(pp,3,functn,-1,7171);
  3523.     }
  3524. }
  3525.  
  3526. @ The |@r9 module procedure| statement doesn't have an |end| statement.
  3527. @<CASES for |proc_like| (R)@>=
  3528. #if FCN_CALLS
  3529.     R_proc_like();
  3530. #else
  3531.     @<Cases for |proc_like| (R)@>@;
  3532. #endif
  3533.  
  3534. @
  3535. @<Part 2@>=
  3536. #if FCN_CALLS
  3537.     @[SRTN R_proc_like(VOID)
  3538.         {
  3539.         @<Cases for |proc_like| (R)@>@;
  3540.         }
  3541. #endif
  3542.  
  3543. @
  3544. @<Cases for |proc_like| (R)@>=
  3545.  
  3546. if(fcn_level == 0) {/* Error message */}
  3547. else fcn_level--;
  3548.  
  3549. SQUASH(pp,1,int_like,-1,2989);
  3550.  
  3551. @ Here we handle Fortran--90's |@r9 private|, |@r9 public|, and |@r9
  3552. sequence| statements.
  3553. @<CASES for |private_like| (R)@>=
  3554. #if FCN_CALLS
  3555.     R_private_like();
  3556. #else
  3557.     @<Cases for |private_like| (R)@>@;
  3558. #endif
  3559.  
  3560. @
  3561. @<Part 2@>=
  3562. #if FCN_CALLS
  3563.     @[SRTN R_private_like(VOID)
  3564.         {
  3565.         @<Cases for |private_like| (R)@>@;
  3566.         }
  3567. #endif
  3568.  
  3569. @
  3570. @<Cases for |private_like| (R)@>=
  3571. {
  3572. if(cat1 == (eight_bits)(language==FORTRAN_90 ? semi : colon) )
  3573.     {
  3574.     app(backup);
  3575.     b_app2(pp);
  3576.     REDUCE(pp,2,decl,-1,2988);
  3577.     }
  3578. else SQUASH(pp,1,int_like,-2,2987);
  3579. }
  3580.  
  3581. @<CASES for |int_like| (R)@>=
  3582. #if FCN_CALLS
  3583.     R_int_like();
  3584. #else
  3585.     @<Cases for |int_like| (R)@>@;
  3586. #endif
  3587.  
  3588. @
  3589. @<Part 2@>=
  3590. #if FCN_CALLS
  3591.     @[SRTN R_int_like(VOID)
  3592.         {
  3593.         @<Cases for |int_like| (R)@>@;
  3594.         }
  3595. #endif
  3596.  
  3597. @
  3598. @<Cases for |int_like| (R)@>=
  3599. {
  3600. if(cat1==lbrace)
  3601.     {
  3602.     b_app(indent);
  3603.     b_app1(pp);
  3604.     REDUCE(pp,1,decl_hd,0,940); /* ``|@r block data{}|'' */
  3605.     }
  3606. else if(cat1==unorbinop && cat2==expr) /* ``|@r character*(*)|'' */
  3607.     {
  3608.     b_app1(pp);
  3609.     b_app(@'{'); @~ b_app2(pp+1); @~ b_app(@'}');
  3610.     REDUCE(pp,3,int_like,-1,941);
  3611.     }
  3612. else if (cat1==int_like || cat1==no_order) /* ``|@r double precision|'' or
  3613.         F88 things like ``|@r integer, pointer|''; |no_order| takes
  3614.         care of \&{data} in |@r block data|. */ 
  3615.     {
  3616.     PP_PP(1,1);
  3617.     REDUCE(pp,2,cat0,0,40);
  3618.     }
  3619. else if(cat1==comma) 
  3620.     SQUASH(pp,2,int_like,0,9001); /* F88: ``|@r logical,|'' */
  3621. else if(cat1==binop) /* F88: ``|@r integer :: i|'' */
  3622.     {
  3623.     b_app2(pp);
  3624.     b_app(indent);
  3625.     REDUCE(pp,2,decl_hd,0,9002);
  3626.     }
  3627. else if(cat1==slashes)
  3628.     {
  3629.     b_app1(pp);
  3630.     b_app(@' ');
  3631.     b_app(indent);
  3632.     REDUCE(pp,1,decl_hd,0,9002);
  3633.     }
  3634. else if(cat1==expr && **indirect((pp+1)->trans)==@'(')
  3635.     {
  3636.     b_app1(pp); @~ @<Append thinspace@>@; @~ b_app1(pp+1);
  3637.     REDUCE(pp,2,int_like,0,9003); /* ``|@r integer (KIND=4)|'' */
  3638.     }
  3639. else if (cat1==expr || cat1==semi)
  3640.      {
  3641.       b_app1(pp); 
  3642.  
  3643.     if(cat1 != semi) b_app(@' '); 
  3644.  
  3645.     b_app(indent); /* Start long declaration. */
  3646.  
  3647.      REDUCE(pp,1,decl_hd,0,41); /* JAK: -1 changed to 0 */
  3648.     }
  3649. else if(cat1 == rbrace)
  3650.     SQUASH(pp, 1, decl, -1, 411); 
  3651.         /* See \.{ratfor} example |@r9 module procedure element;|. */
  3652. }
  3653.  
  3654. @
  3655. @<CASES for |struct_like| (R)@>=
  3656. #if FCN_CALLS
  3657.     R_struct_like();
  3658. #else
  3659.     @<Cases for |struct_like| (R)@>@;
  3660. #endif
  3661.  
  3662. @
  3663. @<Part 2@>=
  3664. #if FCN_CALLS
  3665.     @[SRTN R_struct_like(VOID)
  3666.         {
  3667.         @<Cases for |struct_like| (R)@>@;
  3668.         }
  3669. #endif
  3670.  
  3671. @
  3672. @<Cases for |struct_like| (R)@>=
  3673. if(cat1==lpar) 
  3674.     {
  3675.     b_app1(pp);
  3676. #if(0)
  3677.     @<Append thinspace@>@; /* Looks nicer with a bit of space. */
  3678. #endif
  3679.     REDUCE(pp,1,int_like,0,9075); /* \FORTRAN-88 declaration:
  3680. ``|@r9 type(triangle)|''. */
  3681.     }
  3682. else if(cat1==comma && cat2==int_like)
  3683.     {
  3684.     b_app2(pp); @~ b_app(@' '); @~ b_app1(pp+2);
  3685.     REDUCE(pp,3,struct_like,0,90750); /* ``|@r9 type, private|'' */
  3686.     }
  3687. else if(cat1==binop && **(pp+1)->trans != (sixteen_bits)@'/') 
  3688.     SQUASH(pp,2,struct_like,0,90751); /* ``|@r9 type, public::|''  The
  3689.         |!=| precluded the VAX |@n9 structure /stuff/| declaration. */
  3690. else if(cat1==expr || cat1==slashes || cat1==struct_like)
  3691.     { /* ``|@r9 type person|'', ``|@r9 type /vaxstruct/|'', or ``|@r9
  3692.             interface operator|'' */ 
  3693.     PP_PP(1,1);
  3694.     make_underlined(pp+1);
  3695.     REDUCE(pp,2,language==FORTRAN_90 ? struct_hd : struct_like,0,9076);
  3696.     }
  3697. else if(cat1==semi) 
  3698.     SQUASH(pp,1,struct_hd,0,9077); /* |@r9 interface| */
  3699. else if (cat1==lbrace)  /* ``|@r9 type person {integer i;};|'' */
  3700.     {
  3701.     b_app1(pp); @~ indent_force;    
  3702.     b_app1(pp+1); REDUCE(pp,2,struct_hd,0,100);
  3703.     }
  3704.  
  3705. @
  3706. @<CASES for |struct_hd| (R)@>=
  3707. #if FCN_CALLS
  3708.     R_str_hd();
  3709. #else
  3710.     @<Cases for |struct_hd| (R)@>@;
  3711. #endif
  3712.  
  3713. @
  3714. @<Part 2@>=
  3715. #if FCN_CALLS
  3716.     @[SRTN R_str_hd(VOID)
  3717.         {
  3718.         @<Cases for |struct_hd| (R)@>@;
  3719.         }
  3720. #endif
  3721.  
  3722. @
  3723. @<Cases for |struct_hd| (R)@>=
  3724. if(is_FORTRAN_(language))
  3725.  {
  3726. if(cat1==expr)
  3727.     {
  3728.     b_app1(pp); @~ @<Append thinspace@>@; b_app1(pp+1); /* ``|@r9
  3729. interface operator(.not.)|'' */
  3730.     REDUCE(pp,2,struct_hd,0,90760);
  3731.     }
  3732. else if(cat1==semi)
  3733.     {
  3734.     fcn_level++;
  3735.     b_app2(pp);
  3736.     b_app(indent);
  3737.     REDUCE(pp,2,struct_hd,0,90770);
  3738.     }
  3739. else if(cat1==decl || cat1==functn)
  3740.     {
  3741.     b_app1(pp);
  3742.     b_app(force);
  3743.     b_app1(pp+1);
  3744.     REDUCE(pp,2,struct_hd,0,9078);
  3745.     }
  3746. else if(cat1==END_stmt)
  3747.     {
  3748.     b_app1(pp);
  3749.     b_app(outdent);
  3750.     b_app(force);
  3751.     b_app1(pp+1);
  3752.     REDUCE(pp,2,decl,-1,9079);
  3753.     }
  3754.  }
  3755. else @<Cases for |struct_hd| (C)@>@;
  3756.  
  3757. @
  3758. @<CASES for |op_like| (R)@>=
  3759. #if FCN_CALLS
  3760.     R_op_like();
  3761. #else
  3762.     @<Cases for |op_like| (R)@>@;
  3763. #endif
  3764.  
  3765. @
  3766. @<Part 2@>=
  3767. #if FCN_CALLS
  3768.     @[SRTN R_op_like(VOID)
  3769.         {
  3770.         @<Cases for |op_like| (R)@>@;
  3771.         }
  3772. #endif
  3773.  
  3774. @
  3775. @<Cases for |op_like| (R)@>=
  3776. @{
  3777. short n;
  3778.  
  3779. if(cat1==lpar)
  3780.     { /* We'll search for the obligatory right paren that terminates
  3781. the list. */
  3782.     scrap_pointer q;
  3783.     int k; /* Counter. */
  3784.  
  3785. /* If the paren is missing, we could end up appending the entire rest of
  3786. the code, so we limit the search. */
  3787.     for(q=pp+2; q <= scrp_ptr && q-pp < MAX_OP_TOKENS; q++)
  3788.         if(q->cat == rpar) break;
  3789.  
  3790.     n = (q->cat == rpar) ? PTR_DIFF(short, q, pp) : 0;
  3791.  
  3792.     if(n > 0)
  3793.         {
  3794.         b_app1(pp); @~ b_app(@' '); /* |@r9 operator| */
  3795.         b_app1(pp+1); /* Left paren. */
  3796.         b_app(@'{');
  3797.         APP_STR("\\optrue");
  3798.  
  3799.         for(k=2; k<n; k++)
  3800.             b_app1(pp+k);
  3801.  
  3802.         APP_STR("\\opfalse"); /* We need this here in case we
  3803. encounter an operator that \FWEAVE\ doesn't know how to overload. */
  3804.         b_app(@'}');
  3805.         b_app1(pp+k);
  3806.  
  3807.         REDUCE(pp,n+1,expr,-2,6667);
  3808.         }
  3809.     }
  3810. }
  3811.     
  3812. @<CASES for |decl_hd| (R)@>=
  3813. #if FCN_CALLS
  3814.     R_dcl_hd();
  3815. #else
  3816.     @<Cases for |decl_hd| (R)@>@;
  3817. #endif
  3818.  
  3819. @
  3820. @<Part 2@>=
  3821. #if FCN_CALLS
  3822.     @[SRTN R_dcl_hd(VOID)
  3823.         {
  3824.         @<Cases for |decl_hd| (R)@>@;
  3825.         }
  3826. #endif
  3827.  
  3828. @
  3829. @<Cases for |decl_hd| (R)@>=
  3830. if (cat1==comma)
  3831.     { /* ``|@r integer i,j|'' */
  3832.       b_app2(pp); b_app(@' '); REDUCE(pp,2,decl_hd,0,54);
  3833.     }
  3834. else if (cat1==expr)
  3835.     {
  3836.     make_underlined(pp+1);
  3837.  
  3838.     if(**(pp+2)->trans == (sixteen_bits)@'=') 
  3839.         { // Initialization coming up.
  3840.         SQUASH(pp,1,decl_hd,PLUS 1,55);
  3841.         }
  3842.     else
  3843.         {
  3844.         SQUASH(pp,2,decl_hd,0,56); 
  3845.         }
  3846.     }
  3847. else if(cat1==slashes)
  3848.     {  /* |@r integer i/1/| */
  3849.     SQUASH(pp,2,decl_hd,0,57);
  3850.     }
  3851. @#if 0
  3852. else if(cat1==binop && cat2==expr && (cat3==comma || cat3==semi))
  3853.     {
  3854.     PP_PP(1,2);
  3855.     REDUCE(pp,3,decl_hd,-1,5660); /* Initialization */
  3856.     }
  3857. @#endif
  3858. else if (cat1==lbrace || cat1==int_like || cat1==implicit_like) 
  3859.     /* |@r subroutine f {}| or |@r function f(x) real x;| or |@r
  3860. program main implicit none;|  */
  3861.     {
  3862.     b_app1(pp);
  3863.     b_app(outdent); /* Turn off |indent|. */
  3864.     defined_at(FIRST_ID(pp));
  3865.     REDUCE(pp,1,fn_decl,0,58);
  3866.     }
  3867. else if (cat1==semi && (!auto_semi || (auto_semi && cat2 != lbrace))) 
  3868.     {
  3869.     b_app2(pp);
  3870.     b_app(outdent); /* Finish long declaration. */
  3871.     REDUCE(pp,2,
  3872.         (eight_bits)(intermingle ? (intermingle=NO,ignore_scrap) : decl),
  3873.         -1,59); 
  3874.     }
  3875. else if(cat1==built_in)
  3876.     { /* |@r9 use a, only| */
  3877.     PP_PP(1,1);
  3878.     REDUCE(pp,2,decl_hd,0,5901);
  3879.     }
  3880. #if(0)
  3881. else if(cat1==lpar && cat2==expr) make_underlined(pp+2); /* For
  3882.                         |$decl_hd|. */
  3883. #endif
  3884.  
  3885. @<CASES for |decl| (R)@>=
  3886. #if FCN_CALLS
  3887.     R_decl();
  3888. #else
  3889.     @<Cases for |decl| (R)@>@;
  3890. #endif
  3891.  
  3892. @
  3893. @<Part 2@>=
  3894. #if FCN_CALLS
  3895.     @[SRTN R_decl(VOID)
  3896.         {
  3897.         @<Cases for |decl| (R)@>@;
  3898.         }
  3899. #endif
  3900.  
  3901. @
  3902. @<Cases for |decl| (R)@>=
  3903. if(is_FORTRAN_(language) && cat1==END_like) SQUASH(pp,1,stmt,-1,960); 
  3904.         /* `` |@r program main; end;|'' */
  3905. else if (cat1==decl) 
  3906.     {
  3907.       b_app1(pp); @~ b_app(force); 
  3908.     b_app1(pp+1);
  3909.       REDUCE(pp,2,decl,-1,60);
  3910.     }
  3911. else if (cat1==stmt || cat1==functn) 
  3912.     {
  3913.       b_app1(pp); @~ b_app(big_force); 
  3914.       b_app1(pp+1); REDUCE(pp,2,cat1,-1,61);
  3915.     }
  3916.  
  3917. @ |@r subroutine f1{} subroutine f2{}|.
  3918. @<CASES for |functn| (R)@>=
  3919. #if FCN_CALLS
  3920.     R_functn();
  3921. #else
  3922.     @<Cases for |functn| (R)@>@;
  3923. #endif
  3924.  
  3925. @
  3926. @<Part 2@>=
  3927. #if FCN_CALLS
  3928.     @[SRTN R_functn(VOID)
  3929.         {
  3930.         @<Cases for |functn| (R)@>@;
  3931.         }
  3932. #endif
  3933.  
  3934. @
  3935. @<Cases for |functn| (R)@>=
  3936.  
  3937. if (cat1==functn || (is_RATFOR_(language) && (cat1==decl || cat1==stmt)))
  3938.      {
  3939.     b_app1(pp); @~ b_app(big_force); 
  3940.     b_app1(pp+1); REDUCE(pp,2,cat1,0,80);
  3941.     }
  3942. #if(0)
  3943. else if(cat1==END_like) 
  3944.     {
  3945.     b_app1(pp);
  3946.     REDUCE(pp,1,stmt,-1,9050);
  3947.     }
  3948. #endif
  3949.  
  3950. @<CASES for |lpar| (R)@>=
  3951. #if FCN_CALLS
  3952.     R_lpar();
  3953. #else
  3954.     @<Cases for |lpar| (R)@>@;
  3955. #endif
  3956.  
  3957. @
  3958. @<Part 2@>=
  3959. #if FCN_CALLS
  3960.     @[SRTN R_lpar(VOID)
  3961.         {
  3962.         @<Cases for |lpar| (R)@>@;
  3963.         }
  3964. #endif
  3965.  
  3966. @
  3967. @<Cases for |lpar| (R)@>=
  3968.  
  3969. if (cat1==expr && cat2==rpar) SQUASH(pp,3,expr,-2,120); /* ``|@r (x)|'' */
  3970. else if(cat1==expr && cat2==colon && cat3==rpar) /* ``|@r (lower:)|'' */
  3971.     {
  3972.     b_app3(pp); @~ @<Append thinspace@>; @~ b_app1(pp+3);
  3973.     REDUCE(pp,4,expr,-2,9120);
  3974.     }
  3975. else if(cat1==colon && cat2 != comma) /* ``|@r (:x)|''; watch out for
  3976.             deferred-shape-spec-lists.  */
  3977.     {
  3978.     b_app1(pp); @~ @<Append thinspace@>; @~ b_app1(pp+1);
  3979.     REDUCE(pp,2,lpar,0,9121);
  3980.     }
  3981. else if (cat1==rpar) /* ``|@r ()|'' */
  3982.     {
  3983.       b_app1(pp); @~ @<Append thinspace@>; @~ b_app1(pp+1);
  3984.       REDUCE(pp,2,expr,-2,121);
  3985.     }
  3986. else if (cat1==stmt) /* `` |@r for(x;y;z)|'' */
  3987.     {
  3988.       b_app2(pp); b_app(@' '); REDUCE(pp,2,lpar,0,123);
  3989.     }
  3990.  
  3991. @<CASES for |colon| (R)@>=
  3992. #if FCN_CALLS
  3993.     R_colon();
  3994. #else
  3995.     @<Cases for |colon| (R)@>@;
  3996. #endif
  3997.  
  3998. @
  3999. @<Part 2@>=
  4000. #if FCN_CALLS
  4001.     @[SRTN R_colon(VOID)
  4002.         {
  4003.         @<Cases for |colon| (R)@>@;
  4004.         }
  4005. #endif
  4006.  
  4007. @
  4008. @<Cases for |colon| (R)@>=
  4009.  
  4010. if(cat1==expr || cat1==unorbinop) SQUASH(pp,2,expr,-2,9500); /* ``|@r
  4011. (:upper)|'' */
  4012. else if(cat1==comma && cat2==colon) SQUASH(pp,3,expr,-2,9502);
  4013.     /* Deferred-shape-spec-list: |@r (:,:)| */
  4014. else SQUASH(pp,1,expr,0,9501); /* |@r (:)| */
  4015.  
  4016. @<CASES for |lbrace| (R)@>=
  4017. #if FCN_CALLS
  4018.     R_lbrace();
  4019. #else
  4020.     @<Cases for |lbrace| (R)@>@;
  4021. #endif
  4022.  
  4023. @
  4024. @<Part 2@>=
  4025. #if FCN_CALLS
  4026.     @[SRTN R_lbrace(VOID)
  4027.         {
  4028.         @<Cases for |lbrace| (R)@>@;
  4029.         }
  4030. #endif
  4031.  
  4032. @
  4033. @<Cases for |lbrace| (R)@>=
  4034. if (cat1==rbrace) /* ``|@r {}|'' */
  4035.     {
  4036.       b_app1(pp); @~ @<Append thinspace@>; @~ b_app1(pp+1); 
  4037.       REDUCE(pp,2,stmt,-2,130);
  4038.     }
  4039. else if ((cat1==stmt || cat1==decl) && cat2==rbrace)  /* ``|@r {x;}|'' */
  4040.     {
  4041.       b_app(force);
  4042.       b_app1(pp);  @~  b_app(force);
  4043.       b_app1(pp+1); @~ b_app(force); 
  4044.       b_app1(pp+2); 
  4045.        REDUCE(pp,3,stmt,-2,131);
  4046.     }
  4047.  
  4048. @<CASES for |unop| (R)@>=
  4049. #if FCN_CALLS
  4050.     R_unop();
  4051. #else
  4052.     @<Cases for |unop| (R)@>@;
  4053. #endif
  4054.  
  4055. @
  4056. @<Part 2@>=
  4057. #if FCN_CALLS
  4058.     @[SRTN R_unop(VOID)
  4059.         {
  4060.         @<Cases for |unop| (R)@>@;
  4061.         }
  4062. #endif
  4063.  
  4064. @
  4065. @<Cases for |unop| (R)@>=
  4066.  
  4067. if (cat1==expr) SQUASH(pp,2,expr,-2,33); /* ``|@r !flag|'' */
  4068.  
  4069. @<CASES for |unorbinop| (R)@>=
  4070. #if FCN_CALLS
  4071.     R_unorbinop();
  4072. #else
  4073.     @<Cases for |unorbinop| (R)@>@;
  4074. #endif
  4075.  
  4076. @
  4077. @<Part 2@>=
  4078. #if FCN_CALLS
  4079.     @[SRTN R_unorbinop(VOID)
  4080.         {
  4081.         @<Cases for |unorbinop| (R)@>@;
  4082.         }
  4083. #endif
  4084.  
  4085. @
  4086. @<Cases for |unorbinop| (R)@>=
  4087.  
  4088. if (cat1==expr) /* ``|@r +1.0|'' */
  4089.     {
  4090.       b_app(@'{'); @~ b_app1(pp); @~ b_app(@'}'); 
  4091.     b_app1(pp+1); 
  4092.     REDUCE(pp,2,expr,-2,140);
  4093.     }
  4094. else if(cat1==binop) @<Reduce cases like |*=|@>@;
  4095. else if (cat1== comma || cat1==rpar) SQUASH(pp,1,expr,-2,141); /* ``|@r
  4096. *,|'' or ``|@r *)|'' */
  4097.  
  4098. @<Append thinspace@>=
  4099. {
  4100. b_app(@'\\'); @~ b_app(@',');
  4101. }
  4102.  
  4103. @<Append thickspace@>=
  4104. {
  4105. b_app(@'\\'); @~ b_app(@';');
  4106. }
  4107.  
  4108. @
  4109. @<CASES for |slash_like| (R)@>=
  4110. #if FCN_CALLS
  4111.     R_slash_like();
  4112. #else
  4113.     @<Cases for |slash_like| (R)@>@;
  4114. #endif
  4115.  
  4116. @
  4117. @<Part 2@>=
  4118. #if FCN_CALLS
  4119.     @[SRTN R_slash_like(VOID)
  4120.         {
  4121.         @<Cases for |slash_like| (R)@>@;
  4122.         }
  4123. #endif
  4124.  
  4125. @
  4126. @<Cases for |slash_like| (R)@>=
  4127. if(cat1==slash_like)
  4128.     { // The slash already has braces around it (appended by \FWEAVE).ac
  4129.     b_app1(pp);
  4130.     @<Append thinspace@>;
  4131.     b_app1(pp+1);
  4132.     REDUCE(pp,2,slashes,-1,1801);
  4133.     }
  4134. else if(cat1==expr && cat2==slash_like)
  4135.     SQUASH(pp,3,slashes,-1,1802);
  4136.  
  4137. @<CASES for |binop| (R)@>=
  4138. #if FCN_CALLS
  4139.     R_binop();
  4140. #else
  4141.     @<Cases for |binop| (R)@>@;
  4142. #endif
  4143.  
  4144. @
  4145. @<Part 2@>=
  4146. #if FCN_CALLS
  4147.     @[SRTN R_binop(VOID)
  4148.         {
  4149.         @<Cases for |binop| (R)@>@;
  4150.         }
  4151. #endif
  4152.  
  4153. @
  4154. @<Cases for |binop| (R)@>=
  4155.  
  4156. if(cat1==binop) /* ``|@r / /|'' */
  4157.     {
  4158.     sixteen_bits tok;
  4159.  
  4160.     tok = **pp->trans;
  4161.  
  4162.     if(tok == (sixteen_bits)@'/' && (**(pp+1)->trans == tok) )
  4163.         @<Append empty slashes@>@;
  4164.     else @<Reduce cases like |+=|@>@;
  4165.     }
  4166. else if(cat1==expr && cat2==binop) /* ``|@r /dia/|'' */
  4167.     {
  4168.     sixteen_bits tok;
  4169.  
  4170.     tok = **pp->trans;
  4171.  
  4172.     if(tok == (sixteen_bits)@'/' && (**(pp+2)->trans == tok) )
  4173.         @<Append full slashes@>@;
  4174.     }
  4175.  
  4176. @
  4177. @<Append empty slashes@>=
  4178. {
  4179. b_app(@'{');
  4180. b_app1(pp); @~ @<Append thinspace@>; @~ b_app1(pp+1);
  4181. b_app(@'}');
  4182. REDUCE(pp,2,slashes,-1,180);
  4183. }
  4184.  
  4185. @
  4186. @<Append full slashes@>=
  4187. {
  4188. b_app(@'{');
  4189. b_app1(pp);    /* |'/'| */
  4190. b_app(@'}');
  4191.  
  4192. make_underlined(pp+1);    /* Index common block name. */
  4193. b_app1(pp+1); /* expr */
  4194.  
  4195. b_app(@'{');    
  4196. b_app1(pp+2); /* |'/'| */
  4197. b_app(@'}');
  4198.  
  4199. REDUCE(pp,3,slashes,-1,9181);
  4200. }
  4201.  
  4202. @<Glob...@>=
  4203.  
  4204. IN_PROD text_pointer label_text_ptr[50];
  4205.  
  4206. @ Follow translations until one gets down to the actual tokens.
  4207.  
  4208. @<Part 2@>=@[
  4209.  
  4210. text_pointer 
  4211. indirect FCN((t))
  4212.     text_pointer t C1("")@;
  4213. {
  4214. Token tok_value;
  4215.  
  4216. if(t==NULL) return t;
  4217.  
  4218. tok_value = **t;
  4219.  
  4220. if(tok_value <= tok_flag) return t;
  4221.  
  4222. if(tok_value > inner_tok_flag) tok_value -= (inner_tok_flag - tok_flag);
  4223.  
  4224. if(tok_value > tok_flag)
  4225.     do
  4226.         {
  4227.         Token tok_value0 = tok_value;
  4228.  
  4229.         t = tok_start + (int)(tok_value - tok_flag);
  4230.         tok_value = **t;
  4231.  
  4232.         if(tok_value == tok_value0) return t; /* Emergency return;
  4233. otherwise infinite loop. */
  4234.         }
  4235.     while(tok_value > tok_flag);
  4236.  
  4237. return t;
  4238. }
  4239.  
  4240. @ The following compares the texts of two translations, and is needed for
  4241. labeled loops in Fortran.
  4242. @<Part 2@>=@[
  4243. boolean 
  4244. compare_text FCN((t0,t1))
  4245.     text_pointer t0 C0("")@;
  4246.     text_pointer t1 C1("")@;
  4247. {
  4248. token_pointer p0,p0_end,p1;
  4249.  
  4250. if(t0==NULL || t1==NULL) return NO;
  4251.  
  4252. t0 = indirect(t0); t1 = indirect(t1);
  4253.  
  4254. p0 = *t0; @~ p0_end = *(t0+1);
  4255. p1 = *t1;
  4256.  
  4257. while(p0 < p0_end)
  4258.     {
  4259.     if(*p0 == @':') return YES; /* Ends label */
  4260.     if(*p0++ != *p1++) return NO;
  4261.     }
  4262.  
  4263. return YES;
  4264. }
  4265.  
  4266. @ Return the value of a token that may be buried deep in indirection chains.
  4267. @<Part 2@>=@[
  4268. sixteen_bits 
  4269. tok_val FCN((p))
  4270.     scrap_pointer p C1("")@;
  4271. {
  4272. sixteen_bits tok_value;
  4273.  
  4274. tok_value = **(p->trans);
  4275.  
  4276. if(tok_value > inner_tok_flag)
  4277.     tok_value -= (inner_tok_flag- tok_flag);
  4278.  
  4279. if(tok_value > tok_flag)
  4280.     do
  4281.         {
  4282.         tok_value = **(tok_start + (int)(tok_value - tok_flag)); 
  4283.         }
  4284.     while(tok_value > tok_flag);
  4285.  
  4286. return tok_value;
  4287. }
  4288.  
  4289. @<CASES for |Rdo_like| (R)@>=
  4290. #if FCN_CALLS
  4291.     R_Rdo_like();
  4292. #else
  4293.     @<Cases for |Rdo_like| (R)@>@;
  4294. #endif
  4295.  
  4296. @
  4297. @<Part 2@>=
  4298. #if FCN_CALLS
  4299.     @[SRTN R_Rdo_like(VOID)
  4300.         {
  4301.         @<Cases for |Rdo_like| (R)@>@;
  4302.         }
  4303. #endif
  4304.  
  4305. @
  4306. @<Cases for |Rdo_like| (R)@>=
  4307.  
  4308. if(is_FORTRAN_(language))
  4309.   {
  4310.   if(cat1==for_like)  /* \&{do} \&{while} */
  4311.     {
  4312.     PP_PP(1,1);
  4313.     REDUCE(pp,2,Rdo_like,0,9600);
  4314.     }
  4315.   else if(cat1==expr && ( (cat2==expr && cat3==binop) || cat2==if_like) )
  4316. /* ``|@r do 10 i=@e|'' */
  4317.     {
  4318.     label_text_ptr[indent_level] = (pp+1)->trans; /* Pointer to
  4319.             a |token_pointer|---namely, index into |tok_start|. */
  4320.     b_app1(pp);
  4321.     b_app(@' ');
  4322.     b_app1(pp+1);     /* Loop number. */
  4323.     REDUCE(pp,2,Rdo_like,0,9601); /* Swallow only the loop number. */
  4324.     }
  4325.   else if(cat1==stmt) /* ``|@r do i=1,10;|'' */
  4326.     {
  4327.     loop_num[indent_level++] = ++max_loop_num;
  4328.  
  4329.     b_app1(pp); /* \&{do} */
  4330.     b_app(@' ');
  4331.     b_app1(pp+1); /* $i=1,10;$ */
  4332.     app_loop_num(max_loop_num);
  4333.  
  4334.     b_app(indent);
  4335.     REDUCE(pp,2,stmt,-2,9602);
  4336.     }
  4337.   }
  4338. /* \Ratfor. */
  4339. else if(cat1==stmt || (cat1==expr && cat2==lbrace)) /* ``|@r do i=1,10;|''
  4340. or ``|@r do i=1,10{|'' */
  4341.     {
  4342.     PP_PP(1,1);
  4343.     REDUCE(pp,2,for_hd,0,9603);
  4344.     }
  4345.  
  4346. @ The following flag handles the option |@r until| in a ``|@r
  4347. repeat{}until|'' construction.
  4348.  
  4349. @<Glob...@>=
  4350.  
  4351. IN_PROD boolean found_until PSET(NO);
  4352.  
  4353. @ We have to be slightly tricky here, because in ``|@r repeat{}until|'' the
  4354. \&{until} is optional. 
  4355. @<CASES for |do_like| (R)@>=
  4356. #if FCN_CALLS
  4357.     R_do_like();
  4358. #else
  4359.     @<Cases for |do_like| (R)@>@;
  4360. #endif
  4361.  
  4362. @
  4363. @<Part 2@>=
  4364. #if FCN_CALLS
  4365.     @[SRTN R_do_like(VOID)
  4366.         {
  4367.         @<Cases for |do_like| (R)@>@;
  4368.         }
  4369. #endif
  4370.  
  4371. @
  4372. @<Cases for |do_like| (R)@>=
  4373.  
  4374. if(cat1==stmt)
  4375.     {
  4376.     if(cat2==until_like) 
  4377.         {
  4378.         found_until = YES;
  4379.         SQUASH(pp,1,do_like,PLUS 2,9190); /* ``|@r repeat
  4380. {} until @e@;|''; expand the \&{until}. */
  4381.         }
  4382.     else 
  4383.         {
  4384.           b_app1(pp); 
  4385.           indent_force;
  4386.            b_app1(pp+1);
  4387.           b_app(outdent);
  4388.           b_app(force);
  4389.  
  4390.         if(found_until && cat2==stmt) /* Get here by expanding the
  4391. \&{until}. */ 
  4392.             { 
  4393.             found_until = NO;
  4394.             b_app1(pp+2); REDUCE(pp,3,stmt,-2,9191);
  4395.             }
  4396.         else REDUCE(pp,2,stmt,-2,9192); /* ``|@r repeat {}|'';
  4397. no bottom. */
  4398.         }
  4399.     }
  4400.  
  4401. @ Get here from above by expanding the |@r until|.
  4402. @<CASES for |until_like| (R)@>=
  4403. #if FCN_CALLS
  4404.     R_until_like();
  4405. #else
  4406.     @<Cases for |until_like| (R)@>@;
  4407. #endif
  4408.  
  4409. @
  4410. @<Part 2@>=
  4411. #if FCN_CALLS
  4412.     @[SRTN R_until_like(VOID)
  4413.         {
  4414.         @<Cases for |until_like| (R)@>@;
  4415.         }
  4416. #endif
  4417.  
  4418. @
  4419. @<Cases for |until_like| (R)@>=
  4420.  
  4421. SQUASH(pp,1,for_like,0,9195);
  4422.  
  4423. @<Glob...@>=
  4424.  
  4425. IN_PROD int indent_level PSET(0); // Indent level.
  4426. IN_PROD int loop_num[50], max_loop_num PSET(0);
  4427.  
  4428. @<CASES for |if_like| (R)@>=
  4429. #if FCN_CALLS
  4430.     R_if_like();
  4431. #else
  4432.     @<Cases for |if_like| (R)@>@;
  4433. #endif
  4434.  
  4435. @
  4436. @<Part 2@>=
  4437. #if FCN_CALLS
  4438.     @[SRTN R_if_like(VOID)
  4439.         {
  4440.         @<Cases for |if_like| (R)@>@;
  4441.         }
  4442. #endif
  4443.  
  4444. @
  4445. @<Cases for |if_like| (R)@>=
  4446.  
  4447. if(cat1==CASE_like)
  4448.     {
  4449.     PP_PP(1,1);    /* |@r9 select case| */
  4450.     REDUCE(pp,2,if_like,0,9196);
  4451.     }
  4452. else
  4453. if(is_FORTRAN_(language))
  4454.   {
  4455.  if(cat1==expr)
  4456.   {
  4457.   boolean if_form;
  4458.  
  4459.   if( (if_form=BOOLEAN(cat2==built_in && cat3==semi)) || cat2==semi) 
  4460.     { /* ``|@n if(x) then;|''  or ``|@n where(x); |'' */ 
  4461.     short n; /* Number to append. Things are annoying because the |@n if|
  4462. and |@n where| statements aren't completely symmetrical. */
  4463.  
  4464.     loop_num[indent_level++] = ++max_loop_num;
  4465.  
  4466.     b_app1(pp);    /* \&{if} */
  4467.     @<Append thinspace@>;
  4468.     b_app1(pp+1); /* $(x)$ */
  4469.     b_app(@' ');
  4470.     
  4471.     if(if_form)
  4472.         {
  4473.         n = 4;
  4474.         b_app2(pp+2); /* \&{then}; */
  4475.         }
  4476.     else
  4477.         { /* |@n where| */
  4478.         n = 3;
  4479.         b_app1(pp+2); /* semi */
  4480.         }
  4481.  
  4482.     app_loop_num(max_loop_num);
  4483.     b_app(indent);
  4484.     REDUCE(pp,n,stmt,-2,9800);
  4485.     }
  4486.   else if(cat2==stmt) /* ``|@n if(x) a=b;|'' */
  4487.     {
  4488.     b_app1(pp); /* \&{if} */
  4489.     @<Append thinspace@>;
  4490.     b_app1(pp+1); /* $(x)$ */
  4491.     app(@' ');
  4492.     b_app(cancel);
  4493.     b_app1(pp+2); /* Statement */
  4494.     REDUCE(pp,3,stmt,-2,9801);
  4495.     }
  4496.   else 
  4497.     {
  4498.     b_app1(pp);
  4499.     @<Append thinspace@>;
  4500.     b_app1(pp+1);
  4501.     REDUCE(pp,2,if_hd,0,9802);
  4502.     }
  4503.   }
  4504.  }
  4505. /* RATFOR\ */
  4506. else @<Cases for |if_like| (C)@>@;
  4507.  
  4508.  
  4509. @ Attach a comment with the loop number.
  4510.  
  4511. @<Part 2@>=@[
  4512.  
  4513. SRTN 
  4514. app_loop_num FCN((n))
  4515.     int n C1("Loop number.")@;
  4516. {
  4517. char loop_id[100];
  4518.  
  4519. if(!block_nums) return; // We're not supposed to number the blocks/loops.
  4520.  
  4521. sprintf(loop_id,"\\Wblock{%d}",n); /* Output the block number. */
  4522. @.\\Wc@>
  4523. APP_STR(loop_id);
  4524. }
  4525.  
  4526. @ For the |@r go| keyword, we just have to handle optional white space.
  4527. @<CASES for |go_like| (R)@>=
  4528. #if FCN_CALLS
  4529.     R_go_like();
  4530. #else
  4531.     @<Cases for |go_like| (R)@>@;
  4532. #endif
  4533.  
  4534. @
  4535. @<Part 2@>=
  4536. #if FCN_CALLS
  4537.     @[SRTN R_go_like(VOID)
  4538.         {
  4539.         @<Cases for |go_like| (R)@>@;
  4540.         }
  4541. #endif
  4542.  
  4543. @
  4544. @<Cases for |go_like| (R)@>=
  4545.  
  4546. if(cat1==built_in) /* ``|@r go to|'' */
  4547.     {
  4548.     b_app1(pp); /* \&{go} */
  4549.     b_app(@' ');
  4550.     b_app1(pp+1); /* \&{to} */
  4551.     REDUCE(pp,2,case_like,0,9850); /* \&{goto} */
  4552.     }
  4553. else SQUASH(pp,1,expr,-2,9851);
  4554.  
  4555. @ The keyword |@r end| has two possible meanings: end a loop, or end a
  4556. function. 
  4557. @<CASES for |end_like| (R)@>=
  4558. #if FCN_CALLS
  4559.     R_end_like();
  4560. #else
  4561.     @<Cases for |end_like| (R)@>@;
  4562. #endif
  4563.  
  4564. @
  4565. @<Part 2@>=
  4566. #if FCN_CALLS
  4567.     @[SRTN R_end_like(VOID)
  4568.         {
  4569.         @<Cases for |end_like| (R)@>@;
  4570.         }
  4571. #endif
  4572.  
  4573. @
  4574. @<Cases for |end_like| (R)@>=
  4575. if(cat1==Rdo_like || cat1==if_like) /* ``|@r end do|'' or ``|@r end if|'' */
  4576.     {
  4577.     b_app1(pp); /* \&{end} */
  4578.     b_app(@' ');
  4579.     b_app1(pp+1); /* \&{do} or \&{if} */
  4580.     REDUCE(pp,2,endif_like,0,9860); /* Now turned into \&{enddo} or
  4581. \&{endif} */ 
  4582.     }
  4583. else 
  4584.     {
  4585.     fcn_level--;
  4586.     SQUASH(pp,1,END_like,-1,9861); /* \&{end} of function. */
  4587.     }
  4588.  
  4589. @  \Fortran-90??
  4590.  
  4591. @<CASES for |END_like| (R)@>=
  4592. #if FCN_CALLS
  4593.     R_END();
  4594. #else
  4595.     @<Cases for |END_like| (R)@>@;
  4596. #endif
  4597.  
  4598. @
  4599. @<Part 2@>=
  4600. #if FCN_CALLS
  4601.     @[SRTN R_END(VOID)
  4602.         {
  4603.         @<Cases for |END_like| (R)@>@;
  4604.         }
  4605. #endif
  4606.  
  4607. @
  4608. @<Cases for |END_like| (R)@>=
  4609. {
  4610. if(cat1==program_like || cat1==struct_like)
  4611.     {
  4612.     PP_PP(1,1);
  4613.     
  4614.     if(cat2==expr)
  4615.         {
  4616.         b_app(@' '); @~ b_app1(pp+2);
  4617.         REDUCE(pp,3,END_like,0,9860);
  4618.         }
  4619.     else 
  4620.         REDUCE(pp,2,END_like,0,9861);
  4621.     }
  4622. else if(cat1==semi) 
  4623.     SQUASH(pp,2,END_stmt,-2,9862);
  4624. }
  4625.  
  4626. @ Handle end of loop. Note that in \Fortran-90, the \It{if-construct-name}
  4627. is optional.
  4628.  
  4629. @<CASES for |endif_like| (R)@>=
  4630. #if FCN_CALLS
  4631.     R_endif_like();
  4632. #else
  4633.     @<Cases for |endif_like| (R)@>@;
  4634. #endif
  4635.  
  4636. @
  4637. @<Part 2@>=
  4638. #if FCN_CALLS
  4639.     @[SRTN R_endif_like(VOID)
  4640.         {
  4641.         @<Cases for |endif_like| (R)@>@;
  4642.         }
  4643. #endif
  4644.  
  4645. @
  4646. @<Cases for |endif_like| (R)@>=
  4647. {
  4648. short n;
  4649. boolean no_construct_name;
  4650.  
  4651. if((no_construct_name=BOOLEAN(cat1==semi)) || (cat1==expr && cat2==semi) )
  4652.     {
  4653.     b_app(outdent);
  4654.     b_app(force);
  4655.  
  4656.     if(no_construct_name)
  4657.         {
  4658.         n = 2;
  4659.         b_app2(pp); /* \&{endif}; or \&{enddo}; */
  4660.         }
  4661.     else
  4662.         { /* Include \It{if-construct-name} */
  4663.         n = 3;
  4664.         PP_PP(1,2);
  4665.         }
  4666.  
  4667.     if(--indent_level < 0)
  4668.         indent_level = 0;
  4669.  
  4670.     app_loop_num(loop_num[indent_level]);
  4671.     REDUCE(pp,n,stmt,-2,9880);
  4672.     }
  4673. }
  4674.  
  4675. @<CASES for |if_hd| (R)@>=
  4676. #if FCN_CALLS
  4677.     R_if_hd();
  4678. #else
  4679.     @<Cases for |if_hd| (R)@>@;
  4680. #endif
  4681.  
  4682. @
  4683. @<Part 2@>=
  4684. #if FCN_CALLS
  4685.     @[SRTN R_if_hd(VOID)
  4686.         {
  4687.         @<Cases for |if_hd| (R)@>@;
  4688.         }
  4689. #endif
  4690.  
  4691. @
  4692. @<Cases for |if_hd| (R)@>=
  4693.  
  4694. if(is_FORTRAN_(language))
  4695.     {
  4696.     if (cat1==stmt) 
  4697.         {
  4698.         b_app1(pp); @~ b_app(break_space); @~ b_app1(pp+1);
  4699.         REDUCE(pp,2,stmt,-2,9900);
  4700.         }
  4701.     }
  4702. else @<Cases for |if_hd| (C)@>@;
  4703.  
  4704. @<CASES for |else_like| (R)@>=
  4705. #if FCN_CALLS
  4706.     R_else_like();
  4707. #else
  4708.     @<Cases for |else_like| (R)@>@;
  4709. #endif
  4710.  
  4711. @
  4712. @<Part 2@>=
  4713. #if FCN_CALLS
  4714.     @[SRTN R_else_like(VOID)
  4715.         {
  4716.         @<Cases for |else_like| (R)@>@;
  4717.         }
  4718. #endif
  4719.  
  4720. @
  4721. @<Cases for |else_like| (R)@>=
  4722.  
  4723. if(is_FORTRAN_(language))
  4724.    {
  4725.    if(cat1==if_like) /* ``|@n else if|'' */
  4726.     {
  4727.     b_app1(pp); /* \&{else} */
  4728.     b_app(@' ');
  4729.     b_app1(pp+1); /* \&{if} */
  4730.     REDUCE(pp,2,else_like,0,9910); /* \&{elseif} */
  4731.     }
  4732.    else if(cat1==semi) /* \&{else}; */
  4733.     {
  4734.     b_app(outdent);
  4735.     b_app(force);
  4736.     b_app2(pp); /* \&{else} or \&{elseif} */
  4737.     app_loop_num(loop_num[indent_level-1]);
  4738.     b_app(indent);
  4739.     REDUCE(pp,2,stmt,-2,9911);
  4740.     }
  4741.    else if(cat1==expr && cat2==built_in && cat3==semi)  /* ``|@n else if(x)
  4742. then;|'' */
  4743.     {
  4744.     b_app(outdent);
  4745.     b_app(force);
  4746.  
  4747.     b_app1(pp);    /* \&{elseif} */
  4748.     @<Append thinspace@>;
  4749.     b_app1(pp+1); /* $(x)$ */
  4750.     b_app(@' ');
  4751.     b_app2(pp+2); /* \&{then}; */
  4752.     app_loop_num(loop_num[indent_level-1]);
  4753.  
  4754.     b_app(indent);
  4755.     REDUCE(pp,4,stmt,-2,9912);
  4756.     }
  4757.   }
  4758. /* \Ratfor\ */
  4759. else @<Cases for |else_like| (C)@>@;
  4760.  
  4761. @<CASES for |stmt| (R)@>=
  4762. #if FCN_CALLS
  4763.     R_stmt();
  4764. #else
  4765.     @<Cases for |stmt| (R)@>@;
  4766. #endif
  4767.  
  4768. @
  4769. @<Part 2@>=
  4770. #if FCN_CALLS
  4771.     @[SRTN R_stmt(VOID)
  4772.         {
  4773.         @<Cases for |stmt| (R)@>@;
  4774.         }
  4775. #endif
  4776.  
  4777. @
  4778. @<Cases for |stmt| (R)@>=
  4779.  
  4780. if(is_FORTRAN_(language) && cat1==program_like) SQUASH(pp,1,functn,
  4781.     PLUS 1,9960); 
  4782. @#if 0
  4783. else 
  4784. if(is_FORTRAN_(language) && (cat1==END_like && cat2==semi) ) /* Finally
  4785. recognized a function. */
  4786.     SQUASH(pp,1,stmt,-1,99661);
  4787.         {
  4788. #if(0)
  4789.         b_app(indent); /* The function body will be indented. */
  4790.         b_app(backup); /* But not the first line of function. */
  4791. #endif
  4792.         b_app1(pp); /* The body. */
  4793.  
  4794.         if(fcn_level==0)
  4795.             {
  4796.             if(containing) b_app(big_force);
  4797.             while(containing)
  4798.                 {
  4799. #if(0)
  4800.                 b_app(outdent);
  4801. #endif
  4802.                 containing--;
  4803.                 }
  4804.             }
  4805.  
  4806. /* The \&{end} statement. */
  4807.         b_app(force);    
  4808.         b_app(outdent);
  4809.         b_app2(pp+1);
  4810.  
  4811.         REDUCE(pp,3,functn,-1,9961);
  4812.         }
  4813. @#endif
  4814. else if (cat1==stmt) 
  4815.     {
  4816.   b_app1(pp); 
  4817.  b_app(break_space);
  4818.   b_app(force);
  4819.  
  4820.    b_app1(pp+1); REDUCE(pp,2,stmt,-2,250);
  4821.     }
  4822. else if (cat1==functn)
  4823.     {
  4824.     b_app1(pp); @~ b_app(big_force);
  4825.     b_app1(pp+1);
  4826.     REDUCE(pp,2,stmt,-2,251);
  4827.     }
  4828.  
  4829. @
  4830. @<CASES for |CASE_like| (R)@>=
  4831. #if FCN_CALLS
  4832.     R_CASE();
  4833. #else
  4834.     @<Cases for |CASE_like| (R)@>@;
  4835. #endif
  4836.  
  4837. @
  4838. @<Part 2@>=
  4839. #if FCN_CALLS
  4840.     @[SRTN R_CASE(VOID)
  4841.         {
  4842.         @<Cases for |CASE_like| (R)@>@;
  4843.         }
  4844. #endif
  4845.  
  4846. @
  4847. @<Cases for |CASE_like| (R)@>=
  4848.  
  4849. if(is_FORTRAN_(language))
  4850.     {
  4851.     b_app(backup);
  4852.     b_app1(pp);
  4853.     REDUCE(pp,1,case_like,0,9258);
  4854.     }
  4855. else SQUASH(pp,1,case_like,0,9259);
  4856.  
  4857. @<CASES for |case_like| (R)@>=
  4858. #if FCN_CALLS
  4859.     R_case_like();
  4860. #else
  4861.     @<Cases for |case_like| (R)@>@;
  4862. #endif
  4863.  
  4864. @
  4865. @<Part 2@>=
  4866. #if FCN_CALLS
  4867.     @[SRTN R_case_like(VOID)
  4868.         {
  4869.         @<Cases for |case_like| (R)@>@;
  4870.         }
  4871. #endif
  4872.  
  4873. @
  4874. @<Cases for |case_like| (R)@>=
  4875. if(cat1==read_like) /* ``|@r call open|'' */
  4876.     {
  4877.     b_app1(pp);    /* \&{call} */
  4878.     b_app(@' ');
  4879.     b_app1(pp+1); /* \&{close}, \&{open}, etc. */
  4880.     REDUCE(pp,2,case_like,0,9260);
  4881.     }
  4882. else if (cat1==semi) SQUASH(pp,2,stmt,-2,260); /* ``|@r return;|'' */
  4883. else if (cat1==colon) @<Append an ordinary colon@>@;
  4884. else if (cat1==expr && cat2==semi)
  4885.     { /* ``|@r return 1;|'' */
  4886.     PP_PP(1,2);
  4887.     REDUCE(pp,3,stmt,-2,262);
  4888.     }
  4889. else if ((cat1==expr || cat1==label) && cat2==colon)
  4890.     { /* ``|@r case 1:|'' */
  4891.     PP_PP(1,1);
  4892.     APP_STR("\\Colon\\ ");
  4893.     REDUCE(pp,3,tag,-1,263);
  4894.     }
  4895.  
  4896. @
  4897. @<Append an ordinary colon@>=
  4898. {
  4899. b_app1(pp); @~ APP_STR("\\Colon\\ ");
  4900. REDUCE(pp,2,tag,-1,261);
  4901. }
  4902.  
  4903. @<CASES for |tag| (R)@>=
  4904. #if FCN_CALLS
  4905.     R_tag();
  4906. #else
  4907.     @<Cases for |tag| (R)@>@;
  4908. #endif
  4909.  
  4910. @
  4911. @<Part 2@>=
  4912. #if FCN_CALLS
  4913.     @[SRTN R_tag(VOID)
  4914.         {
  4915.         @<Cases for |tag| (R)@>@;
  4916.         }
  4917. #endif
  4918.  
  4919. @
  4920. @<Cases for |tag| (R)@>=
  4921.  
  4922. if (cat1==tag) /* ``|@r case 1: case 2:|'' */
  4923.     {
  4924.   b_app1(pp); @~  b_app(force);
  4925.   b_app(backup);
  4926.    b_app1(pp+1); REDUCE(pp,2,tag,-1,270);
  4927.     }
  4928. else if (cat1==stmt || cat1==END_like) /* ``|@r 10 continue;|'' */
  4929.     {
  4930.     boolean end_of_loop;
  4931.  
  4932.     end_of_loop = NO;
  4933.  
  4934. /* Unwind indent levels for labeled loops. */
  4935.     while(indent_level > 0 && 
  4936.            compare_text(pp->trans,label_text_ptr[indent_level-1]) )
  4937.         {
  4938.         --indent_level;
  4939.         b_app(outdent);
  4940.         end_of_loop = YES;
  4941.         }
  4942.  
  4943.     if(is_FORTRAN_(language) && Fortran_label) 
  4944.         { /* ``|@n EXIT: continue@;|'' */
  4945.         b_app(force);
  4946.         APP_STR("\\Wlbl{"); @~    b_app1(pp); @~ app(@'}'); 
  4947. @.\\Wlbl@>
  4948.         }
  4949.     else
  4950.         { /* Label on separate line. */
  4951.         b_app(big_force);
  4952.         b_app(backup);
  4953.         b_app1(pp);     /* Tag (Includes colon.) */
  4954.         b_app(force);
  4955.         }
  4956.  
  4957.     b_app1(pp+1); /* Stmt. */
  4958.  
  4959.     if(end_of_loop) 
  4960.         app_loop_num(loop_num[indent_level]);
  4961.  
  4962.     REDUCE(pp,2,cat1,-2,271);
  4963. }
  4964.  
  4965.  
  4966. @<CASES for |label| (R)@>=
  4967. #if FCN_CALLS
  4968.     R_label();
  4969. #else
  4970.     @<Cases for |label| (R)@>@;
  4971. #endif
  4972.  
  4973. @
  4974. @<Part 2@>=
  4975. #if FCN_CALLS
  4976.     @[SRTN R_label(VOID)
  4977.         {
  4978.         @<Cases for |label| (R)@>@;
  4979.         }
  4980. #endif
  4981.  
  4982. @
  4983. @<Cases for |label| (R)@>=
  4984. if(cat1==colon)
  4985.     {
  4986.     b_app1(pp);
  4987.     REDUCE(pp,2,label,0,9270); /* Swallow the colon. (Numerical
  4988. statement labels won't have any.) Then, for all labels, we put a colon in
  4989. during the next block. */
  4990.     }
  4991. else if(cat1==stmt || cat1==END_like)
  4992.     {
  4993.     b_app1(pp); @~ APP_STR("\\Colon\\ ");
  4994.  
  4995.     if(is_FORTRAN_(language) && Fortran_label) 
  4996.         b_app(cancel);
  4997.  
  4998.     REDUCE(pp,1,tag,0,9271); /* Convert the label into a tag. Don't
  4999.                     swallow the statement. */
  5000.     }
  5001.  
  5002. @<CASES for |semi| (R)@>=
  5003. #if FCN_CALLS
  5004.     R_semi();
  5005. #else
  5006.     @<Cases for |semi| (R)@>@;
  5007. #endif
  5008.  
  5009. @
  5010. @<Part 2@>=
  5011. #if FCN_CALLS
  5012.     @[SRTN R_semi(VOID)
  5013.         {
  5014.         @<Cases for |semi| (R)@>@;
  5015.         }
  5016. #endif
  5017.  
  5018. @
  5019. @<Cases for |semi| (R)@>=
  5020. if(is_RATFOR_(language) && auto_semi)
  5021.     { /* Just throw away semi. */
  5022.     text_pointer t;
  5023.  
  5024.     t = indirect(pp->trans);
  5025.  
  5026.     if(**t == @';') **t = 0;
  5027.     SQUASH(pp,1,ignore_scrap,-1,9280);
  5028.     }
  5029. else
  5030.     {
  5031.     b_app(@' '); b_app1(pp); REDUCE(pp,1,stmt,-2,280);
  5032.     }
  5033.  
  5034. @<CASES for |common_like| (R)@>=
  5035. #if FCN_CALLS
  5036.     R_common_like();
  5037. #else
  5038.     @<Cases for |common_like| (R)@>@;
  5039. #endif
  5040.  
  5041. @
  5042. @<Part 2@>=
  5043. #if FCN_CALLS
  5044.     @[SRTN R_common_like(VOID)
  5045.         {
  5046.         @<Cases for |common_like| (R)@>@;
  5047.         }
  5048. #endif
  5049.  
  5050. @
  5051. @<Cases for |common_like| (R)@>=
  5052. if(cat1==expr || cat1==slashes || cat1==semi) 
  5053.         /* ``|@r common x| or |@r common/dia/|'' */
  5054.     {
  5055.     b_app1(pp);
  5056.     if(cat1 != semi) b_app(@' ');
  5057.     b_app(indent);
  5058.     REDUCE(pp,1,common_hd,0,9950);
  5059.     }
  5060.  
  5061. @<CASES for |common_hd| (R)@>=
  5062. #if FCN_CALLS
  5063.     R_cmn_hd();
  5064. #else
  5065.     @<Cases for |common_hd| (R)@>@;
  5066. #endif
  5067.  
  5068. @
  5069. @<Part 2@>=
  5070. #if FCN_CALLS
  5071.     @[SRTN R_cmn_hd(VOID)
  5072.         {
  5073.         @<Cases for |common_hd| (R)@>@;
  5074.         }
  5075. #endif
  5076.  
  5077. @
  5078. @<Cases for |common_hd| (R)@>=
  5079.  
  5080. if(cat1== expr) SQUASH(pp,2,common_hd,0,9951); /* ``|@r common x|'' */
  5081. else if(cat1==slashes) /* ``|@r common/dia/|'' */
  5082.     {
  5083.     b_app1(pp);
  5084.     b_app(@' ');
  5085.     b_app1(pp+1);
  5086.     b_app(@' ');
  5087.     REDUCE(pp,2,common_hd,0,9952);
  5088.     }
  5089. else if(cat1==comma) /* ``|@r common x,y|'' */
  5090.     {
  5091.     b_app2(pp);
  5092.     b_app(@' ');
  5093.     REDUCE(pp,2,common_hd,0,9953);
  5094.     }
  5095. else if(cat1==semi) 
  5096.     {
  5097.     b_app2(pp);
  5098.     b_app(outdent);
  5099.     REDUCE(pp,2,decl,-1,9954); /* ``|@r common x;|'' */
  5100.     }
  5101.  
  5102. @<CASES for |read_like| (R)@>=
  5103. #if FCN_CALLS
  5104.     R_read_like();
  5105. #else
  5106.     @<Cases for |read_like| (R)@>@;
  5107. #endif
  5108.  
  5109. @
  5110. @<Part 2@>=
  5111. #if FCN_CALLS
  5112.     @[SRTN R_read_like(VOID)
  5113.         {
  5114.         @<Cases for |read_like| (R)@>@;
  5115.         }
  5116. #endif
  5117.  
  5118. @
  5119. @<Cases for |read_like| (R)@>=
  5120.  
  5121. if(cat1==lpar && cat2==expr && cat3==rpar) /* |@r read(6,100)| */
  5122.     {
  5123.     b_app1(pp);
  5124.     @<Append thinspace@>;
  5125.     b_app3(pp+1);
  5126.     b_app(@' ');
  5127.     REDUCE(pp,4,read_hd,0,9960);
  5128.     }
  5129. else if(cat1==expr && cat2==comma) /* ``|@r TYPE 100, i@;|'' */
  5130.     {
  5131.     b_app1(pp);
  5132.     b_app(@' ');
  5133.     b_app2(pp+1);
  5134.     b_app(@' ');
  5135.     REDUCE(pp,3,read_hd,0,9961);
  5136.     }
  5137. else if(cat1==expr || cat1==unorbinop) /* ``|@r TYPE *|'' */
  5138.     {
  5139.     PP_PP(1,1);
  5140.  
  5141.     if(cat2==expr) b_app(@' '); /* Takes care of |"TYPE 100 i"|. */
  5142.  
  5143.     REDUCE(pp,2,read_hd,0,9962);
  5144.     }
  5145. else if(cat1==semi) SQUASH(pp,1,read_hd,0,9963);
  5146.  
  5147.  
  5148. @<CASES for |read_hd| (R)@>=
  5149. #if FCN_CALLS
  5150.     R_rd_hd();
  5151. #else
  5152.     @<Cases for |read_hd| (R)@>@;
  5153. #endif
  5154.  
  5155. @
  5156. @<Part 2@>=
  5157. #if FCN_CALLS
  5158.     @[SRTN R_rd_hd(VOID)
  5159.         {
  5160.         @<Cases for |read_hd| (R)@>@;
  5161.         }
  5162. #endif
  5163.  
  5164. @
  5165. @<Cases for |read_hd| (R)@>=
  5166. if(cat1==comma)  /* ``|@r read(6,100),|'' */
  5167.     {
  5168.     b_app2(pp);
  5169.     b_app(@' ');
  5170.     REDUCE(pp,2,read_hd,0,9965);
  5171.     }
  5172. else if(cat1==expr)
  5173.     {
  5174.     if(cat2==comma || cat2==semi)
  5175.         SQUASH(pp,2,read_hd,0,9966); /* ``|@r write(6,100) i,j@;|'' */
  5176.     }
  5177. else if(cat1==semi && cat2==read_like) /* Two I/O statements back-to-back. */
  5178.     {
  5179.     b_app1(pp);
  5180. @#if 0
  5181.     b_app(big_cancel);
  5182. @#endif
  5183.     b_app1(pp+1);
  5184.     b_app(force);
  5185.     b_app1(pp+2);
  5186.     REDUCE(pp,3,read_like,0,9967);
  5187.     }
  5188. else if(cat1==semi)
  5189.     {
  5190.     b_app1(pp);
  5191. @#if 0
  5192.     b_app(big_cancel); /* Supposed to kill off preceding blanks. */
  5193. @#endif
  5194.     b_app1(pp+1);
  5195.     REDUCE(pp,2,stmt,-2,9968);
  5196.     }
  5197.  
  5198.  
  5199. @f implicit_none implicit
  5200.  
  5201. @<CASES for |implicit_like| (R)@>=
  5202. #if FCN_CALLS
  5203.     R_implicit_like();
  5204. #else
  5205.     @<Cases for |implicit_like| (R)@>@;
  5206. #endif
  5207.  
  5208. @
  5209. @<Part 2@>=
  5210. #if FCN_CALLS
  5211.     @[SRTN R_implicit_like(VOID)
  5212.         {
  5213.         @<Cases for |implicit_like| (R)@>@;
  5214.         }
  5215. #endif
  5216.  
  5217. @
  5218. @<Cases for |implicit_like| (R)@>=
  5219. if(cat1==int_like || cat1==expr) /* ``|@r implicit integer|'' or 
  5220.                     ``|@r implicit none|'' */
  5221.     {
  5222.     b_app1(pp);
  5223.     b_app(@' ');
  5224.     b_app(indent); /* Start possible long declaration. */
  5225.     REDUCE(pp,1,implicit_hd,0,9970);
  5226.     }
  5227. else if(cat1==semi) /* ``|@r implicit_none;|''. */
  5228.     {
  5229.     b_app1(pp);
  5230.     b_app(indent);
  5231.     REDUCE(pp,1,implicit_hd,0,99700);
  5232.     }
  5233.  
  5234. @<CASES for |implicit_hd| (R)@>=
  5235. #if FCN_CALLS
  5236.     R_imp_hd();
  5237. #else
  5238.     @<Cases for |implicit_hd| (R)@>@;
  5239. #endif
  5240.  
  5241. @
  5242. @<Part 2@>=
  5243. #if FCN_CALLS
  5244.     @[SRTN R_imp_hd(VOID)
  5245.         {
  5246.         @<Cases for |implicit_hd| (R)@>@;
  5247.         }
  5248. #endif
  5249.  
  5250. @
  5251. @<Cases for |implicit_hd| (R)@>=
  5252. if(cat1==unorbinop && cat2==expr) 
  5253.     { /* ``|@r implicit real*8|'' */
  5254.     b_app1(pp);
  5255.     b_app(@'{'); @~ b_app2(pp+1); @~ b_app(@'}');
  5256.     @<Append thinspace@>;
  5257.     REDUCE(pp,3,implicit_hd,0,9971);
  5258.     }
  5259. else if(cat1==expr) SQUASH(pp,2,implicit_hd,0,9972); /* ``|@r implicit
  5260.     integer(a-h)|'' */
  5261. else if(cat1==comma || cat1==int_like)
  5262.     {
  5263.     b_app2(pp);
  5264.  
  5265.     if(cat2 != unorbinop)
  5266.         if(cat2==int_like) b_app(@' '); /* ``|@r implicit real x,
  5267. integer i|'' */
  5268.         else @<Append thinspace@>;
  5269.  
  5270.     REDUCE(pp,2,implicit_hd,0,9973);
  5271.     }
  5272. else if(cat1==semi) SQUASH(pp,1,decl_hd,0,9974); /* ``|@r implicit
  5273.     integer(a-h);|'' */
  5274.     
  5275. @<CASES for |assign_like| (R)@>=
  5276. #if FCN_CALLS
  5277.     R_assign_like();
  5278. #else
  5279.     @<Cases for |assign_like| (R)@>@;
  5280. #endif
  5281.  
  5282. @
  5283. @<Part 2@>=
  5284. #if FCN_CALLS
  5285.     @[SRTN R_assign_like(VOID)
  5286.         {
  5287.         @<Cases for |assign_like| (R)@>@;
  5288.         }
  5289. #endif
  5290.  
  5291. @
  5292. @<Cases for |assign_like| (R)@>=
  5293. if(cat1==expr && cat2==built_in && cat3==expr) /* ``|@r assign 100 to k|'' */
  5294.     {
  5295.     b_app1(pp);
  5296.     b_app(@' ');
  5297.     b_app1(pp+1);
  5298.     b_app(@' ');
  5299.     b_app1(pp+2);
  5300.     b_app(@' ');
  5301.     b_app1(pp+3);
  5302.     REDUCE(pp,4,expr,0,9980);
  5303.     }
  5304.  
  5305. @ The following flag is used  in \FORTRAN-90 to determine whether a |@r9
  5306. contains| is in force, and what level in the block structure we're in.
  5307.  
  5308. @<Glob...@>=
  5309.  
  5310. IN_PROD int containing PSET(0);
  5311.  
  5312. @<CASES for |entry_like| (R)@>=
  5313. #if FCN_CALLS
  5314.     R_entry_like();
  5315. #else
  5316.     @<Cases for |entry_like| (R)@>@;
  5317. #endif
  5318.  
  5319. @
  5320. @<Part 2@>=
  5321. #if FCN_CALLS
  5322.     @[SRTN R_entry_like(VOID)
  5323.         {
  5324.         @<Cases for |entry_like| (R)@>@;
  5325.         }
  5326. #endif
  5327.  
  5328. @
  5329. @<Cases for |entry_like| (R)@>=
  5330. if(cat1==expr && cat2==semi) /* ``|@r entry E(x);|'' */
  5331.     {
  5332.     b_app(big_force);
  5333.     b_app(backup); @~ PP_PP(1,2); @~ b_app(force);
  5334.     REDUCE(pp,3,stmt,-2,9990);
  5335.     }
  5336. else if(cat1== (eight_bits)(language==FORTRAN_90 ? semi : colon)) 
  5337.     { /* ``|@r9 contains:|'' */
  5338.     b_app(big_force);
  5339.     b_app(backup); @~ b_app2(pp); @~ b_app(force);
  5340.  
  5341.     containing++; 
  5342. #if(0)
  5343.     b_app(indent);
  5344. #endif
  5345.     REDUCE(pp,2,stmt,-2,9991);
  5346.     }
  5347.  
  5348. @<CASES for |define_like| (R)@>=
  5349. #if FCN_CALLS
  5350.     R_define_like();
  5351. #else
  5352.     @<Cases for |define_like| (R)@>@;
  5353. #endif
  5354.  
  5355. @
  5356. @<Part 2@>=
  5357. #if FCN_CALLS
  5358.     @[SRTN R_define_like(VOID)
  5359.         {
  5360.         @<Cases for |define_like| (R)@>@;
  5361.         }
  5362. #endif
  5363.  
  5364. @
  5365. @<Cases for |define_like| (R)@>=
  5366. if(cat1==expr)
  5367.     {
  5368.     b_app(force);
  5369.     b_app(backup); @~ b_app2(pp); @~ b_app(force);
  5370.     REDUCE(pp,2,ignore_scrap,-1,9995);
  5371.     }
  5372.  
  5373. @ \&{data} statements can be intermixed with everything. (VAX). For such
  5374. statements, we raise a flag.
  5375.  
  5376. @<CASES for |no_order| (R)@>=
  5377. #if FCN_CALLS
  5378.     R_no_order();
  5379. #else
  5380.     @<Cases for |no_order| (R)@>@;
  5381. #endif
  5382.  
  5383. @
  5384. @<Part 2@>=
  5385. #if FCN_CALLS
  5386.     @[SRTN R_no_order(VOID)
  5387.         {
  5388.         @<Cases for |no_order| (R)@>@;
  5389.         }
  5390. #endif
  5391.  
  5392. @
  5393. @<Cases for |no_order| (R)@>=
  5394. intermingle = YES;
  5395. b_app(force);
  5396. b_app1(pp); @~ b_app(@' ');
  5397. REDUCE(pp,1,int_like,0,9996);
  5398.  
  5399.  
  5400. @<CASES for |built_in| (R)@>=
  5401. #if FCN_CALLS
  5402.     R_built_in();
  5403. #else
  5404.     @<Cases for |built_in| (R)@>@;
  5405. #endif
  5406.  
  5407. @
  5408. @<Part 2@>=
  5409. #if FCN_CALLS
  5410.     @[SRTN R_built_in(VOID)
  5411.         {
  5412.         @<Cases for |built_in| (R)@>@;
  5413.         }
  5414. #endif
  5415.  
  5416. @
  5417. @<Cases for |built_in| (R)@>=
  5418. {
  5419. b_app1(pp);
  5420. @<Append thinspace@>;
  5421. REDUCE(pp,1,expr,-2,9998);
  5422. }
  5423.  
  5424. @<CASES for |newline| (R)@>=
  5425. #if FCN_CALLS
  5426.     R_newline();
  5427. #else
  5428.     @<Cases for |newline| (R)@>@;
  5429. #endif
  5430.  
  5431. @
  5432. @<Part 2@>=
  5433. #if FCN_CALLS
  5434.     @[SRTN R_newline(VOID)
  5435.         {
  5436.         @<Cases for |newline| (R)@>@;
  5437.         }
  5438. #endif
  5439.  
  5440. @
  5441. @<Cases for |newline| (R)@>=
  5442. SQUASH(pp,1,ignore_scrap,-1,9999);
  5443.  
  5444. @* PRODUCTIONS for LITERAL.
  5445. @<Part 2@>=@[
  5446. SRTN 
  5447. V_productions(VOID)
  5448. {
  5449. switch(pp->cat)
  5450.     {
  5451.     case expr: @<Cases for |expr| (M)@>@; @~ break;
  5452.     case stmt: @<Cases for |stmt| (M)@>@; @~ break;
  5453.     }
  5454. }
  5455.  
  5456. @
  5457. @<Cases for |expr| (M)@>=
  5458.  
  5459. @
  5460. @<Cases for |stmt| (M)@>=
  5461.  
  5462. @* PRODUCTIONS for TEX. The productions have been made into individual
  5463. functions to accomodate memory-starved pc's.
  5464. @<Part 2@>=@[
  5465. SRTN 
  5466. X_productions(VOID)
  5467. {
  5468. switch (pp->cat) 
  5469.     {
  5470.     case expr: @<Cases for |expr| (X)@>@; @~ break;
  5471.     case stmt: @<Cases for |stmt| (X)@>@; @~ break;
  5472.     }
  5473. }
  5474.  
  5475. @
  5476. @<Cases for |expr| (X)@>=
  5477. {
  5478. if(cat1==expr) SQUASH(pp,2,expr,0,5);
  5479. else if(cat1==semi) 
  5480.     {
  5481.     b_app1(pp);
  5482.     REDUCE(pp,2,stmt,-1,6);
  5483.     }
  5484. }
  5485.  
  5486. @
  5487. @<Cases for |stmt| (X)@>=
  5488. {
  5489. if(cat1==stmt)
  5490.     {
  5491.     b_app1(pp); 
  5492.     b_app(force);
  5493.     b_app1(pp+1);
  5494.     REDUCE(pp,2,stmt,-1,250);
  5495.     }
  5496. }
  5497.  
  5498. @* CHANGING the SCRAP LIST; APPLYING the PRODUCTIONS.
  5499. The `|reduce|' procedure makes the appropriate changes to the scrap list. 
  5500.  
  5501. @<Typed...@>=
  5502.  
  5503. typedef unsigned long RULE_NO; // Rule number for the productions.
  5504.  
  5505. @
  5506. @d REDUCE(j,k,c,d,n) reduce(j,k,(eight_bits)(c),d,(RULE_NO)(n))
  5507. @<Part 2@>=@[ 
  5508. SRTN 
  5509. reduce FCN((j,k,c,d,n))
  5510.     scrap_pointer j C0("")@;
  5511.     short k C0("Number of items to be reduced.")@;
  5512.     eight_bits c C0("Reduce to this type.")@;
  5513.     short d C0("Move by this amount.")@;
  5514.     RULE_NO n C1("Rule number.")@;
  5515. {
  5516.   scrap_pointer i, i1; /* Pointers into scrap memory */
  5517.  
  5518. /* Store the translation. */
  5519.   j->cat=c; j->trans=text_ptr;
  5520.   j->mathness= (eight_bits)(4*last_mathness+ini_mathness);
  5521.   freeze_text;
  5522.  
  5523. /* More stuff to the left, overwriting the $k$~items that have been
  5524. reduced. */
  5525.   if (k>1) 
  5526.     {
  5527.     for (i=j+k, i1=j+1; i<=lo_ptr; i++, i1++) 
  5528.         {
  5529.           i1->cat=i->cat; i1->trans=i->trans;
  5530.           i1->mathness=i->mathness;
  5531.             }
  5532.  
  5533.         lo_ptr=lo_ptr-k+1;
  5534.       }
  5535.  
  5536.   @<Change |pp| to $\max(|scrp_base|,|pp+d|)$@>;
  5537.  
  5538. #ifdef DEBUG
  5539.   @<Print a snapshot of the scrap list if debugging @>;
  5540. #endif /* |DEBUG| */
  5541.  
  5542.   pp--; /* we next say |pp++| */
  5543. }
  5544.  
  5545. @<Change |pp| to $\max...@>=
  5546.  
  5547. if (pp+d>=scrp_base) pp=pp+d;
  5548. else pp=scrp_base;
  5549.  
  5550. @ The |squash| procedure takes advantage of the simplification that occurs
  5551. when |k=1|.
  5552.  
  5553. @d SQUASH(j,k,c,d,n) squash(j,k,c,d,(RULE_NO)(n))
  5554.  
  5555. @<Part 2@>=@[ 
  5556. SRTN 
  5557. squash FCN((j,k,c,d,n))
  5558.     scrap_pointer j C0("")@;
  5559.     short k C0("Number to be squashed.")@;
  5560.     eight_bits c C0("Make it this type.")@;
  5561.     short d C0("Move by this amount.")@;
  5562.     RULE_NO n C1("Rule number.")@;
  5563. {
  5564.   scrap_pointer i; /* pointers into scrap memory */
  5565.  
  5566.   if (k==1) 
  5567.     {
  5568.         j->cat=c; @<Change |pp|...@>;
  5569.  
  5570. #ifdef DEBUG
  5571.         @<Print a snapshot...@>;
  5572. #endif /* |DEBUG| */
  5573.  
  5574.         pp--; /* we next say |pp++| */
  5575.         return;
  5576.       }
  5577.  
  5578.   for (i=j; i<j+k; i++) b_app1(i);
  5579.  
  5580.   reduce(j,k,c,d,n);
  5581. }
  5582.  
  5583. @ Here now is the code that applies productions as long as possible. It
  5584. requires two local labels (|found| and |done|), as well as a local
  5585. variable~(|i|).
  5586.  
  5587. @<Reduce the scraps using the productions until no more rules apply@>=
  5588. {
  5589. in_prototype = indented = NO;
  5590.  
  5591. WHILE()
  5592.     {
  5593.       @<Make sure the entries |pp| through |pp+3| of |cat| are defined@>;
  5594.  
  5595.       if (tok_ptr+8>tok_m_end)
  5596.         {
  5597.             if (tok_ptr>mx_tok_ptr) mx_tok_ptr=tok_ptr;
  5598.             OVERFLW("tokens","tw");
  5599.         }
  5600.  
  5601.     if(text_ptr+4>tok_end) 
  5602.         {
  5603.             if (text_ptr>mx_text_ptr) mx_text_ptr=text_ptr;
  5604.             OVERFLW("texts",ABBREV(max_texts));
  5605.           }
  5606.  
  5607.       if(pp>lo_ptr) 
  5608.         break;
  5609.  
  5610.       @<Match a production...@>;
  5611.       ini_mathness=cur_mathness=last_mathness=maybe_math;
  5612.     }
  5613. }
  5614.  
  5615. @ If we get to the end of the scrap list, category codes equal to zero are
  5616. stored, since zero does not match anything in a production.
  5617.  
  5618. @<Make sure the entries...@>=
  5619.  
  5620. if (lo_ptr<pp+3) 
  5621.     {
  5622.       while (hi_ptr<=scrp_ptr && lo_ptr!=pp+3) 
  5623.         {
  5624.         (++lo_ptr)->cat=hi_ptr->cat; lo_ptr->mathness=(hi_ptr)->mathness;
  5625.         lo_ptr->trans=(hi_ptr++)->trans;
  5626.           }
  5627.  
  5628.       for (i=lo_ptr+1;i<=pp+3;i++) i->cat=0;
  5629.     }
  5630.  
  5631. @
  5632. @d MAX_CYCLES 500
  5633. @<Check for infinite loop@>=
  5634. {
  5635. static RULE_NO last_rule = ULONG_MAX;
  5636. static int ncycles = 0;
  5637.  
  5638. if(n && n == last_rule)
  5639.     {
  5640.     if(ncycles++ > MAX_CYCLES)
  5641.         {
  5642.         outer_char temp[MAX_CYCLES];
  5643.         
  5644.         SPRINTF(MAX_CYCLES, temp, 
  5645.             `"Infinite production loop, rule %lu", n`);
  5646.         CONFUSION("reduce", temp);
  5647.         }
  5648.     }
  5649. else
  5650.     {
  5651.     last_rule = n;
  5652.     ncycles = 0;
  5653.     }
  5654. }
  5655.  
  5656. @<Print a snapsh...@>= 
  5657. @{
  5658.   scrap_pointer k; /* pointer into |scrap_info| */
  5659.  
  5660. @b
  5661. @<Check for infinite loop@>@;
  5662.  
  5663.   if (tracing==2) 
  5664.     {
  5665.     printf("%5lu",n); // The rule number.
  5666.  
  5667.     if(in_prototype)
  5668.         printf(".%i", in_prototype);
  5669.  
  5670.     printf(": ");
  5671.  
  5672.     for (k=scrp_base; k<=lo_ptr; k++) 
  5673.         {
  5674.           if (k==pp) putxchar('*'); else putxchar(' ');
  5675.  
  5676.           if (k->mathness %4 ==  yes_math) putxchar('+');
  5677.           else if (k->mathness %4 ==  no_math) putxchar('-');
  5678.  
  5679.           prn_cat(k->cat);
  5680.  
  5681.           if (k->mathness /4 ==  yes_math) putxchar('+');
  5682.           else if (k->mathness /4 ==  no_math) putxchar('-');
  5683.         }
  5684.  
  5685.         if (hi_ptr<=scrp_ptr) printf("..."); /* indicate that more is
  5686.             coming */ 
  5687.  
  5688.         @<Print the last translation@>@;
  5689.  
  5690.     }
  5691. }
  5692.  
  5693. @ For debugging, it's helpful to see the translation of the last several scraps
  5694. that's printed explicitly.
  5695. @<Print the last trans...@>=
  5696. {
  5697. printf(" ==\""); 
  5698. if(lo_ptr > scrp_base) 
  5699.     { // The second-to-last scrap.
  5700.     prn_text(indirect((lo_ptr-1)->trans));
  5701.     printf("\" \"");
  5702.     }
  5703. prn_text(indirect(lo_ptr->trans)); // Last scrap.
  5704. puts("\"");
  5705. }
  5706.  
  5707. @ The |translate| function assumes that scraps have been stored in
  5708. positions |scrp_base| through |scrp_ptr| of |cat| and |trans|. It appends
  5709. a |terminator| scrap and begins to apply productions as much as possible.
  5710. The result is a token list containing the translation of the given sequence
  5711. of scraps.
  5712.  
  5713. After calling |translate|, we will have |text_ptr+3<=max_texts| and
  5714. |tok_ptr+6<=max_toks|, so it will be possible to create up to three token
  5715. lists with up to six tokens without checking for overflow. Before calling
  5716. |translate|, we should have |text_ptr<max_texts| and
  5717. |scrp_ptr<max_scraps|, since |translate| might add a new text and a new
  5718. scrap before it checks for overflow.
  5719.  
  5720. @<Part 2@>=@[ 
  5721. text_pointer 
  5722. translate FCN((mode0))
  5723.     PARSING_MODE mode0 C1("")@;
  5724. {
  5725. LANGUAGE saved_language = language;
  5726. scrap_pointer i, /* index into |cat| */
  5727.       j; /* runs through final scraps */
  5728.  
  5729. translate_mode = mode0;
  5730.  
  5731. pp=scrp_base; lo_ptr=pp-1; hi_ptr=pp;
  5732. @<If tracing, print an indication of where we are@>;
  5733. @<Reduce the scraps...@>@;
  5734. @<Combine the irreducible scraps that remain@>;
  5735.  
  5736. language = saved_language;
  5737. return text_ptr-1;
  5738. }
  5739.  
  5740. @ If the initial sequence of scraps does not reduce to a single scrap, we
  5741. concatenate the translations of all remaining scraps, separated by blank
  5742. spaces, with dollar signs surrounding the translations of scraps whose
  5743. category code is |max_math| or less.
  5744.  
  5745. @<Combine the irreducible...@>= 
  5746. {
  5747. EXTERN int math_flag;
  5748.  
  5749.   @<If semi-tracing, show the irreducible scraps@>;
  5750.  
  5751.   for (j=scrp_base; j<=lo_ptr; j++) 
  5752.     {
  5753.         if (j!=scrp_base) app(@' '); // Separate scraps by blanks.
  5754.  
  5755.         if ((j->mathness % 4 == yes_math) && math_flag==NO) app(@'$');
  5756.  
  5757.         if ((j->mathness % 4 == no_math) && math_flag==YES) 
  5758.         {app(@' '); app(@'$');}
  5759.  
  5760.         app1(j);
  5761.  
  5762.         if ((j->mathness / 4 == yes_math) && math_flag==NO) app(@'$');
  5763.  
  5764.         if ((j->mathness / 4 == no_math) && math_flag==YES) 
  5765.             {app(@'$');   app(@' ');}
  5766.  
  5767.         if (tok_ptr+6>tok_m_end) OVERFLW("tokens","tw");
  5768.       }
  5769.  
  5770.   freeze_text; 
  5771. }
  5772.  
  5773. @<If semi-tracing, show the irreducible scraps@>=
  5774.  
  5775. #ifdef DEBUG
  5776. {
  5777. scrap_pointer scrap0 = scrp_base;
  5778.  
  5779. while(scrap0->cat == ignore_scrap) scrap0++;
  5780.  
  5781. if (lo_ptr>scrap0 && tracing==1) 
  5782.     {
  5783.     CLR_PRINTF(warning,
  5784.         ("\nIrreducible scrap sequence in %s:", 
  5785.             MOD_TRANS(module_count)));
  5786.     mfree();
  5787.       mark_harmless;
  5788.  
  5789.       for (j=scrap0; j<=lo_ptr; j++) 
  5790.         {
  5791.             printf(" "); prn_cat(j->cat);
  5792.           }
  5793.     }
  5794. }
  5795. #endif /* |DEBUG| */
  5796.  
  5797. @ Print a header for each section of translated code.
  5798. @d OUT_WIDTH 40
  5799. @<If tracing,...@>=
  5800.  
  5801. #ifdef DEBUG
  5802. if (tracing==2) 
  5803.     {
  5804.     CLR_PRINTF(warning,
  5805.         ("\nTracing after l. %u (language = %s):  ",
  5806.             cur_line,languages[lan_num(language)])); 
  5807.     mark_harmless;
  5808.  
  5809.       if (loc>=cur_buffer+OUT_WIDTH) 
  5810.         {
  5811.         printf("...");
  5812.         ASCII_write(loc-OUT_WIDTH,OUT_WIDTH);
  5813.         }
  5814.       else ASCII_write(cur_buffer,loc-cur_buffer);
  5815.  
  5816.     puts("");
  5817.     }
  5818. #endif /* |DEBUG| */
  5819.  
  5820. @* INDEX.
  5821.