home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Tex29 / StTeXsrc.zoo / src / expand.c < prev    next >
C/C++ Source or Header  |  1988-03-13  |  14KB  |  482 lines

  1.  
  2. /*
  3.  * @(#)expand.c 2.9 EPA
  4.  *
  5.  * Copyright 1987,1988 Pat J Monardo
  6.  *
  7.  * Redistribution of this file is permitted through
  8.  * the specifications in the file COPYING.
  9.  *
  10.  * 
  11.  */
  12.  
  13. #include "tex.h"
  14. #include "box.h"
  15. #include "tokenstack.h"
  16. #include "scan.h"
  17. #include "token.h"
  18. #include "tokenlists.h"
  19. #include "cond.h"
  20. #include "file.h"
  21. #include "expand.h"
  22.  
  23. int     long_state;
  24. ptr     pstack[9];
  25. ptr     cur_mark[5];
  26.  
  27. get_x_token ()
  28. {
  29. restart:
  30.     get_next();
  31.     if (cur_cmd <= MAX_COMMAND)
  32.         goto done;
  33.     if (cur_cmd >= CALL) {
  34.         if (cur_cmd < END_TEMPLATE) {
  35.             macro_call();
  36.         } else {
  37.             cur_cs = FROZEN_ENDV;
  38.             cur_cmd = ENDV;
  39.             goto done;
  40.         }
  41.     } else {
  42.         expand();
  43.     }
  44.     goto restart;
  45.  
  46. done:
  47.     if (cur_cs == 0)
  48.         cur_tok = cur_cmd * 0400 + cur_chr;
  49.     else cur_tok = CS_TOKEN_FLAG + cur_cs;
  50. }
  51.  
  52. expand ()
  53. {
  54.     int     j;
  55.     ptr     p;
  56.     ptr     q;
  57.     ptr     r;
  58.     tok     t;
  59.     val     save_scanner_status;
  60.     val     cv_backup = cur_val;
  61.     int     radix_backup = radix;
  62.     int     co_backup = cur_order;
  63.     int     cvl_backup = cur_val_level;
  64.     ptr     backup_backup = token_link(backup_tokens);  
  65.  
  66.     if (cur_cmd < CALL) {
  67.         if (tracing_commands > 1)
  68.             show_cur_cmd_chr();
  69.         switch (cur_cmd)
  70.         {
  71.         case TOP_BOT_MARK:
  72.             if (cur_mark[cur_chr] != NULL)
  73.                 begin_token_list(cur_mark[cur_chr], MARK_TEXT);
  74.             break;
  75.  
  76.         case EXPAND_AFTER: 
  77.             get_token();
  78.             t = cur_tok;
  79.             get_token();
  80.             if (cur_cmd > MAX_COMMAND)
  81.                 expand();
  82.             else back_input();
  83.             cur_tok = t;
  84.             back_input();
  85.             break;
  86.  
  87.         case NO_EXPAND:
  88.             save_scanner_status = scanner_status;
  89.             scanner_status = NORMAL;
  90.             get_token(); 
  91.             scanner_status = save_scanner_status;
  92.             t = cur_tok;
  93.             back_input();
  94.             if (t >= CS_TOKEN_FLAG) {
  95.                 p = new_token();
  96.                 token(p) = CS_TOKEN_FLAG + FROZEN_DONT_EXPAND;
  97.                 token_link(p) = loc;
  98.                 start = p;
  99.                 loc = p;
  100.             }
  101.             break;
  102.  
  103.         case CS_NAME:
  104.             p = r = new_token();
  105.             do {
  106.                 get_x_token();
  107.                 if (cur_cs == 0)
  108.                     store_new_token(cur_tok);
  109.             } while (cur_cs == 0);
  110.             if (cur_cmd != END_CS_NAME) {
  111.                 print_err("Missing ");
  112.                 print_esc("endcsname");
  113.                 print(" inserted");
  114.                 help_cs();
  115.                 back_error();
  116.             }
  117.             j = first;
  118.             p = token_link(r);
  119.             while (p != NULL) {
  120.                 if (j >= max_buf_stack) {
  121.                     max_buf_stack = j + 1;
  122.                     if (max_buf_stack == BUF_SIZE)
  123.                         overflow("buffer size", BUF_SIZE);
  124.                 }
  125.                 buffer[j] = token(p) % 0400;
  126.                 incr(j);
  127.                 p = token_link(p);
  128.             }
  129.             if (j > first + 1) {
  130.                 no_new_control_sequence = FALSE;
  131.                 cur_cs = id_lookup(first, j - first);
  132.                 no_new_control_sequence = TRUE;
  133.             } else if (j == first) {
  134.                 cur_cs = NULL_CS;
  135.             }
  136.             else cur_cs = SINGLE_BASE + buffer[first];
  137.             flush_list(r);
  138.             if (eq_type(cur_cs) == UNDEFINED_CS)
  139.                 eq_define(cur_cs, RELAX, 256);
  140.             cur_tok = cur_cs + CS_TOKEN_FLAG;
  141.             back_input();
  142.             break;
  143.         
  144.         case CONVERT:
  145.             conv_toks();
  146.             break;
  147.         
  148.         case THE:
  149.             ins_the_toks();
  150.             break;
  151.         
  152.         case IF_TEST:
  153.             conditional();
  154.             break;
  155.         
  156.         case FI_OR_ELSE:
  157.             if (cur_chr > if_limit) {
  158.                 if (if_limit == IF_CODE) {
  159.                     insert_relax();
  160.                 } else {
  161.                     print_err("Extra ");
  162.                     print_cmd_chr(FI_OR_ELSE, cur_chr);
  163.                     help_extra_if();
  164.                     error();
  165.                 }
  166.             } else {
  167.                 while (cur_chr != FI_CODE)
  168.                     pass_text();
  169.                 pop_cond();
  170.             }
  171.             break;
  172.  
  173.         case INPUT:
  174.             if (cur_chr > 0)
  175.                 force_eof = TRUE;
  176.             else if (name_in_progress)
  177.                 insert_relax();
  178.             else start_input();
  179.             break;
  180.         
  181.         default:
  182.             print_err("Undefined control sequence");
  183.             help_undefd();
  184.             error();
  185.             break;
  186.         }
  187.     } else if (cur_cmd < END_TEMPLATE) {
  188.         macro_call();
  189.     } else {
  190.         cur_tok = CS_TOKEN_FLAG + FROZEN_ENDV;
  191.         back_input();
  192.     }
  193.     cur_val = cv_backup;
  194.     cur_val_level = cvl_backup;
  195.     radix = radix_backup;
  196.     cur_order = co_backup;
  197.     token_link(backup_tokens) = backup_backup;
  198. }
  199.  
  200. insert_relax ()
  201. {
  202.     cur_tok = CS_TOKEN_FLAG + cur_cs;
  203.     back_input();
  204.     cur_tok = CS_TOKEN_FLAG + FROZEN_RELAX;
  205.     back_input();
  206.     token_type = INSERTED;
  207. }
  208.  
  209.  
  210. macro_call ()
  211. {
  212.     int     m;
  213.     int     n;
  214.     ptr     p;
  215.     ptr     q;
  216.     ptr     r;
  217.     ptr     s;
  218.     ptr     t;
  219.     ptr     u;
  220.     ptr     v;
  221.     ascii   match_chr;
  222.     ptr     ref_count;
  223.     ptr     rbrace_ptr;
  224.     ptr     save_warning_index;
  225.     val     save_scanner_status;
  226.     int     unbalance;
  227.  
  228.     n = 0;
  229.     ref_count = cur_chr;
  230.     r = token_link(ref_count);
  231.     save_scanner_status = scanner_status;
  232.     save_warning_index = warning_index;
  233.     warning_index = cur_cs;
  234.     if (tracing_macros > 0) {
  235.         begin_diagnostic();
  236.         print_ln();
  237.         print_cs(warning_index);
  238.         token_show(ref_count);
  239.         end_diagnostic(FALSE);
  240.     }
  241.     if (token(r) != END_MATCH_TOKEN) {
  242.         scanner_status = MATCHING;
  243.         unbalance = 0;
  244.         long_state = eq_type(cur_cs);
  245.         if (long_state >= OUTER_CALL)
  246.             long_state -= 2;
  247.         do {
  248.             if (token(r) > MATCH_TOKEN + 127 ||
  249.                 token(r) < MATCH_TOKEN) {
  250.                 s = NULL;
  251.             } else {
  252.                 match_chr = token(r) - MATCH_TOKEN;
  253.                 s = token_link(r);
  254.                 r = s;
  255.                 p = temp_toks;
  256.                 token_link(p) = NULL;
  257.                 m = 0;
  258.             }
  259.  
  260.         contin:
  261.             get_token();
  262.             if (cur_tok == token(r)) {
  263.                 r = token_link(r);
  264.                 if (token(r) >= MATCH_TOKEN &&
  265.                     token(r) <= END_MATCH_TOKEN) {
  266.                     if (cur_tok < LEFT_BRACE_LIMIT)
  267.                         decr(align_state);
  268.                     goto found;
  269.                 } else {
  270.                     goto contin;
  271.                 }
  272.             }
  273.             if (s != r) {
  274.                 if (s == NULL) {
  275.                     print_err("Use of ");
  276.                     sprint_cs(warning_index);
  277.                     print(" doesn't match its definition");
  278.                     help_match();
  279.                     error();
  280.                     goto local_exit;
  281.                 } else {
  282.                     t = s;
  283.                     do {
  284.                         store_new_token(token(t));
  285.                         incr(m);
  286.                         u = token_link(t);
  287.                         v = s;
  288.                         loop {
  289.                             if (u == r) {
  290.                                 if (cur_tok != token(v)) {
  291.                                     break;
  292.                                 } else {
  293.                                     r = token_link(v);
  294.                                     goto contin;
  295.                                 }
  296.                             }
  297.                             if (token(u) != token(v))
  298.                                 break;
  299.                             u = token_link(u);
  300.                             v = token_link(v);
  301.                         }
  302.                         t = token_link(t);
  303.                     } while (t != r);
  304.                     r = s;
  305.                 }
  306.             }
  307.             if (cur_tok == par_token && long_state != LONG_CALL) {
  308.                 runaway_arg(n);
  309.                 align_state -= unbalance; 
  310.                 goto local_exit;
  311.             }
  312.             if (cur_tok < RIGHT_BRACE_LIMIT) {
  313.                 if (cur_tok < LEFT_BRACE_LIMIT) {
  314.                     unbalance = 1;
  315.                     loop {
  316.                         fast_store_new_token(cur_tok);
  317.                         get_token();
  318.                         if (cur_tok == par_token && 
  319.                             long_state != LONG_CALL) {
  320.                             runaway_arg(n);
  321.                             align_state -= unbalance; 
  322.                             goto local_exit;
  323.                         }
  324.                         if (cur_tok < RIGHT_BRACE_LIMIT) {
  325.                             if (cur_tok < LEFT_BRACE_LIMIT) {
  326.                                 incr(unbalance);
  327.                             } else {
  328.                                 decr(unbalance);
  329.                                 if (unbalance == 0)
  330.                                     break;
  331.                             }
  332.                         }
  333.                     }
  334.                     rbrace_ptr = p;
  335.                     store_new_token(cur_tok);
  336.                 } else {
  337.                     back_input();
  338.                     print_err("Argument of ");
  339.                     sprint_cs(warning_index);
  340.                     print(" has an extra }");
  341.                     help_match_xtra();
  342.                     incr(align_state);
  343.                     long_state = CALL;
  344.                     cur_tok = par_token;
  345.                     ins_error();
  346.                 }
  347.             } else {
  348.                 if (cur_tok == SPACE_TOKEN &&
  349.                     token(r) <= END_MATCH_TOKEN &&
  350.                     token(r) >= MATCH_TOKEN)
  351.                     goto contin;
  352.                 store_new_token(cur_tok);
  353.             }
  354.             incr(m);
  355.             if (token(r) > END_MATCH_TOKEN || token(r) < MATCH_TOKEN)
  356.                 goto contin;
  357.  
  358.         found:
  359.             if (s != NULL) {
  360.                 if (m == 1 &&
  361.                     token(p) < RIGHT_BRACE_LIMIT &&
  362.                     p != temp_toks) {
  363.                     token_link(rbrace_ptr) = NULL;
  364.                     free_token(p);
  365.                     p = token_link(temp_toks);
  366.                     pstack[n] = token_link(p);
  367.                     free_token(p);
  368.                 } else {
  369.                     pstack[n] = token_link(temp_toks);
  370.                 }
  371.                 incr(n);
  372.                 if (tracing_macros > 0) {
  373.                     begin_diagnostic();
  374.                     print_nl("");
  375.                     print_char(match_chr);
  376.                     print_int(n);
  377.                     print("<-");
  378.                     show_token_list(pstack[n - 1], NULL, 1000L);
  379.                     end_diagnostic(FALSE);
  380.                 }
  381.             }
  382.         } while (token(r) != END_MATCH_TOKEN);
  383.     }
  384.     while (state == TOKEN_LIST && loc == NULL)
  385.         end_token_list();
  386.     begin_token_list(ref_count, MACRO);
  387.     name = warning_index;
  388.     loc = token_link(r);
  389.     if (n > 0) {
  390.         if (param_ptr + n > max_param_stack) {
  391.             max_param_stack = param_ptr + n;
  392.             if (max_param_stack >= PARAM_SIZE)
  393.                 overflow("parameter stack size", PARAM_SIZE);
  394.         }
  395.         for (m = 0; m < n; incr(m))
  396.             param_stack[param_ptr + m] = pstack[m];
  397.         param_ptr += n;
  398.     }
  399.  
  400. local_exit:
  401.     scanner_status = save_scanner_status; 
  402.     warning_index = save_warning_index; 
  403. }
  404.  
  405. runaway_arg (n) 
  406.     int     n;
  407. {
  408.     int     m;
  409.  
  410.     if (long_state == CALL) { 
  411.         runaway(); 
  412.         print_err("Paragraph ended before "); 
  413.         sprint_cs(warning_index); 
  414.         print(" was complete"); 
  415.         help_runaway(); 
  416.         back_error();
  417.     }
  418.     pstack[n] = token_link(temp_toks); 
  419.     for (m = 0; m <= n; incr(m))
  420.         flush_list(pstack[m]);
  421. }
  422.  
  423. x_token ()
  424. {
  425.     while (cur_cmd > MAX_COMMAND) {
  426.         expand();
  427.         get_next();
  428.     }
  429.     if (cur_cs == 0)
  430.         cur_tok = cur_cmd * 0400 + cur_chr;
  431.     else cur_tok = CS_TOKEN_FLAG + cur_cs;
  432. }
  433.  
  434. /*
  435.  *  Help text
  436.  */
  437.  
  438. help_runaway ()
  439. {
  440.     help3("I suspect you've forgotten a `}', causing me to apply this",
  441.     "control sequence to too much text. How can we recover?",
  442.     "My plan is to forget the whole thing and hope for the best.");
  443. }
  444.  
  445. help_match ()
  446. {
  447.     help4("If you say, e.g., `\\def\\a1{...}', then you must always",
  448.     "put `1' after `\\a', since control sequence names are",
  449.     "made up of letters only. The macro here has not been",
  450.     "followed by the required stuff, so I'm ignoring it.");
  451. }
  452.  
  453. help_match_xtra ()
  454. {
  455.     help6("I've run across a `}' that doesn't seem to match anything.",
  456.     "For example, `\\def\\a#1{...}' and `\\a}' would produce",
  457.     "this error. If you simply proceed now, the `\\par' that",
  458.     "I've just inserted will cause me to report a runaway",
  459.     "argument that might be the root of the problem. But if",
  460.     "your `}' was spurious, just type `2' and it will go away.");
  461. }
  462.  
  463. help_undefd ()
  464. {
  465.     help5("The control sequence at the end of the top line",
  466.     "of your error message was never \\def'ed. If you have",
  467.     "misspelled it (e.g., `\\hobx'), type `I' and the correct",
  468.     "spelling (e.g., `I\\hbox'). Otherwise just continue,",
  469.     "and I'll forget about whatever was undefined.");
  470. }
  471.  
  472. help_cs ()
  473. {
  474.     help2("The control sequence marked <to be read again> should",
  475.     "not appear between \\csname and \\endcsname.");
  476. }
  477.  
  478. help_extra_if ()
  479. {
  480.     help1("I'm ignoring this; it doesn't match any \\if.");
  481. }
  482.