home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / CMTEX330 / SOURCE / EXPAND.C < prev    next >
C/C++ Source or Header  |  1992-02-19  |  10KB  |  527 lines

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