home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / CMTEX330 / SOURCE / SCAN.C < prev    next >
C/C++ Source or Header  |  1992-04-21  |  19KB  |  1,019 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    cur_val;
  20. int    cur_val_level;
  21. int    cur_order;
  22. int    radix;
  23.  
  24. void
  25. scan_left_brace ()
  26. {
  27.     get_nbrx_token();
  28.     if (cur_cmd != LEFT_BRACE) {
  29.         print_err("Missing { inserted");
  30.         help_left();
  31.         back_error();
  32.         cur_tok = LEFT_BRACE_TOKEN;
  33.         cur_cmd = LEFT_BRACE;
  34.         cur_chr= '{';
  35.         incr(align_state);
  36.     }
  37. }
  38.  
  39. void
  40. scan_optional_equals ()
  41. {
  42.     get_nbx_token();
  43.     if (cur_tok != OTHER_TOKEN + '=') {
  44.         back_input();
  45.     }
  46. }
  47.  
  48. bool
  49. scan_keyword (s)
  50.     str    s;
  51. {
  52.     int    c;
  53.     ptr    h;
  54.     ptr    p;
  55.  
  56.     h = p = new_token();
  57.     token_link(p) = null;
  58.     c = *s;
  59.     while (c != NUL) {
  60.         get_x_token();
  61.         if (cur_cs == null_sym
  62.         && (cur_chr == c || cur_chr == c - 'a' + 'A')) {
  63.             p = token_link(p) = new_token();
  64.             token(p) = cur_tok;
  65.             c = *++s;
  66.         } else if (cur_cmd != SPACER || p != h) {
  67.             back_input();
  68.             if (p != h) {
  69.                 back_list(token_link(h));
  70.             }
  71.             free_token(h);
  72.             return FALSE;
  73.         }
  74.     }
  75.     flush_list(h);
  76.     return TRUE;
  77. }
  78.  
  79. void
  80. mu_error ()
  81. {
  82.     print_err("Incompatible glue units");
  83.     help_mu_error();
  84.     error();
  85. }
  86.  
  87. #define scanned_result(CV, CVL) \
  88.     (cur_val = (int) (CV)), (cur_val_level = (int) (CVL))
  89.  
  90. #define negate_glue() \
  91.     {glue_width(cur_val) = -glue_width(cur_val); \
  92.     stretch(cur_val) = -stretch(cur_val); \
  93.     shrink(cur_val) = -shrink(cur_val);}
  94.  
  95. void
  96. scan_something_internal (level, negative)
  97.     int    level;
  98.     bool    negative;
  99. {
  100.     int    m;
  101.  
  102.     m = cur_chr;
  103.     switch (cur_cmd)
  104.     {
  105.     case DEF_CODE:
  106.         scan_eight_bit_int();
  107.         switch (m)
  108.         {
  109.         case CAT_CODE:
  110.             scanned_result(cat_code(cur_val), INT_VAL);
  111.             break;
  112.  
  113.         case UC_CODE:
  114.             scanned_result(uc_code(cur_val), INT_VAL);
  115.             break;
  116.  
  117.         case LC_CODE:
  118.             scanned_result(lc_code(cur_val), INT_VAL);
  119.             break;
  120.  
  121.         case SF_CODE:
  122.             scanned_result(sf_code(cur_val), INT_VAL);
  123.             break;
  124.  
  125.         case MATH_CODE:
  126.             scanned_result(math_code(cur_val), INT_VAL);
  127.             break;
  128.  
  129.         case DEL_CODE:
  130.             scanned_result(del_code(cur_val), INT_VAL);
  131.             break;
  132.         }
  133.         break;
  134.  
  135.     case TOKS_REGISTER:
  136.     case ASSIGN_TOKS:
  137.         if (level != TOK_VAL) {
  138.             print_err("Missing number, treated as zero");
  139.             help_missing_number();
  140.             back_error();
  141.             scanned_result(0, DIMEN_VAL);
  142.         } else {
  143.             if (cur_cmd == TOKS_REGISTER)  {
  144.                 scan_eight_bit_int();
  145.                 m = TOK_PARS + cur_val;
  146.             }
  147.             m = (int) reg_equiv(toks_reg[m]);
  148.             scanned_result(m, TOK_VAL);
  149.         }
  150.         break;
  151.  
  152.     case DEF_FAMILY:
  153.     case SET_FONT:
  154.     case DEF_FONT:
  155.         if (level != TOK_VAL) {
  156.             print_err("Missing number, treated as zero");
  157.             help_missing_number();
  158.             back_error();
  159.             scanned_result(0, DIMEN_VAL);
  160.         } else {
  161.             back_input();
  162.             scan_font_ident();
  163.             scanned_result((int)font_id_base[cur_val], IDENT_VAL);
  164.         }
  165.         break;
  166.  
  167.     case ASSIGN_INT:
  168.         scanned_result(reg_equiv(int_reg[m]), INT_VAL);
  169.         break;
  170.  
  171.     case ASSIGN_DIMEN:
  172.         scanned_result(reg_equiv(dimen_reg[m]), DIMEN_VAL);
  173.         break;
  174.  
  175.     case ASSIGN_GLUE:
  176.         scanned_result(reg_equiv(skip_reg[m]), GLUE_VAL);
  177.         break;
  178.  
  179.     case ASSIGN_MU_GLUE:
  180.         scanned_result(reg_equiv(mu_skip_reg[m]), MU_VAL);
  181.         break;
  182.  
  183.     case SET_AUX:
  184.         if (abs(mode) != m) {
  185.             print_err("Improper ");
  186.             print_cmd_chr(SET_AUX, m);
  187.             help_aux();
  188.             error();
  189.             if (level != TOK_VAL) {
  190.                 scanned_result(0, DIMEN_VAL);
  191.             } else {
  192.                 scanned_result(0, INT_VAL);
  193.             }
  194.         } else if (m == VMODE) {
  195.             cur_val = prev_depth; 
  196.             cur_val_level = DIMEN_VAL;
  197.         } else {
  198.             cur_val = space_factor;
  199.             cur_val_level = INT_VAL;
  200.         }
  201.         break;
  202.  
  203.     case SET_PREV_GRAF: {
  204.         list    *p;
  205.  
  206.         if (mode == 0) {
  207.             scanned_result(0, INT_VAL);
  208.         } else {
  209.             *nest_ptr = cur_list;
  210.             p = nest_ptr;
  211.             while (abs(p->mode_field) != VMODE) {
  212.                 decr(p);
  213.             }
  214.             scanned_result(p->pg_field, INT_VAL);
  215.         }
  216.         break;
  217.     }
  218.  
  219.     case SET_PAGE_INT:
  220.         if (m == 0) {
  221.             cur_val = dead_cycles;
  222.         } else {
  223.             cur_val = insert_penalties;
  224.         }
  225.         cur_val_level = INT_VAL;
  226.         break;
  227.  
  228.     case SET_PAGE_DIMEN:
  229.         if (page_contents == EMPTY && !output_active) {
  230.             if (m == 0) {
  231.                 cur_val = MAX_DIMEN; 
  232.             } else {
  233.                 cur_val = 0;
  234.             }
  235.         } else {
  236.             cur_val = page_so_far[m];
  237.         }
  238.         cur_val_level = DIMEN_VAL;
  239.         break;
  240.     
  241.     case SET_SHAPE:
  242.         if (par_shape_ptr == null) {
  243.             cur_val = 0;
  244.         } else {
  245.             cur_val = info(par_shape_ptr);
  246.         }
  247.         cur_val_level = INT_VAL;
  248.         break;
  249.     
  250.     case SET_BOX_DIMEN:
  251.         scan_eight_bit_int();
  252.         if (box(cur_val) == null) {
  253.             cur_val = 0;
  254.         } else {
  255.             switch (m) {
  256.             case WD_CODE:
  257.                 cur_val = box_width(box(cur_val));
  258.                 break;
  259.             case HT_CODE:
  260.                 cur_val = box_height(box(cur_val));
  261.                 break;
  262.             case DP_CODE:
  263.                 cur_val = box_depth(box(cur_val));
  264.                 break;
  265.             }
  266.         }
  267.         cur_val_level = DIMEN_VAL;
  268.         break;
  269.     
  270.     case CHAR_GIVEN:
  271.     case MATH_GIVEN:
  272.         scanned_result(m, INT_VAL);
  273.         break;
  274.  
  275.     case ASSIGN_FONT_DIMEN: {
  276.         scal    *d;
  277.  
  278.         d = find_font_dimen(FALSE);
  279.         if (d == (scal *) 0) {
  280.             scanned_result(0, DIMEN_VAL); 
  281.         } else {
  282.             scanned_result(*d, DIMEN_VAL); 
  283.         }
  284.         break;
  285.     }
  286.     
  287.     case ASSIGN_FONT_INT:
  288.         scan_font_ident();
  289.         if (m == 0) {
  290.             scanned_result(hyphen_char(cur_val), INT_VAL);
  291.         } else {
  292.             scanned_result(skew_char(cur_val), INT_VAL);
  293.         }
  294.         break;
  295.  
  296.     case REGISTER:
  297.         scan_eight_bit_int();
  298.         switch (m) {
  299.         case INT_VAL: cur_val = count(cur_val); break; 
  300.         case DIMEN_VAL: cur_val = dimen(cur_val); break; 
  301.         case GLUE_VAL: cur_val = skip(cur_val); break; 
  302.         case MU_VAL: cur_val = mu_skip(cur_val); break;
  303.         }
  304.         cur_val_level = m;
  305.         break;
  306.  
  307.     case LAST_ITEM:
  308.         if (cur_chr > GLUE_VAL) {
  309.             if (cur_chr == INPUT_LINE_NO_CODE) {
  310.                 cur_val = line;
  311.             } else {
  312.                 cur_val = last_badness;
  313.             }
  314.             cur_val_level = INT_VAL;
  315.             break;
  316.         }
  317.         if (cur_chr == GLUE_VAL) {
  318.             cur_val = zero_glue;
  319.         } else {
  320.             cur_val = 0;
  321.         }
  322.         cur_val_level = cur_chr;
  323.         if (mode != 0 && tail != head && !is_char_node(tail)) {
  324.             switch (cur_chr)
  325.             {
  326.             case INT_VAL:
  327.                 if (type(tail) == PENALTY_NODE) {
  328.                     cur_val = penalty(tail);
  329.                 }
  330.                 break;
  331.  
  332.             case DIMEN_VAL:
  333.                 if (type(tail) == KERN_NODE) {
  334.                     cur_val = kern_width(tail);
  335.                 }
  336.                 break;
  337.  
  338.             case GLUE_VAL:
  339.                 if (type(tail) == GLUE_NODE) {
  340.                     cur_val = glue_ptr(tail); 
  341.                     if (subtype(tail) == MU_GLUE) {
  342.                         cur_val_level = MU_VAL;
  343.                     }
  344.                 }
  345.                 break;
  346.  
  347.             default:
  348.                 break;
  349.             }
  350.         } else if (mode == VMODE && tail == head) {
  351.             switch (cur_chr)
  352.             {
  353.             case INT_VAL:
  354.                 cur_val = last_penalty;
  355.                 break;
  356.  
  357.             case DIMEN_VAL:
  358.                 cur_val = last_kern;
  359.                 break;
  360.  
  361.             case GLUE_VAL:
  362.                 if (last_glue != null) {
  363.                     cur_val = last_glue;
  364.                 }
  365.                 break;
  366.             }
  367.         }
  368.         break;
  369.             
  370.     default:
  371.         print_err("You can't use `");
  372.         print_cmd_chr(cur_cmd, cur_chr);
  373.         print("' after ");
  374.         print_esc("the");
  375.         help_thee();
  376.         error();
  377.         if (level != TOK_VAL) {
  378.             scanned_result(0, DIMEN_VAL);
  379.         } else {
  380.             scanned_result(0, INT_VAL);
  381.         }
  382.         break;
  383.     }
  384.     while (cur_val_level > level) {
  385.         if (cur_val_level == GLUE_VAL) {
  386.             cur_val = glue_width(cur_val);
  387.         } else if (cur_val_level == MU_VAL) {
  388.             mu_error();
  389.         }
  390.         decr(cur_val_level);
  391.     }
  392.     if (negative) {
  393.         if (cur_val_level >= GLUE_VAL) {
  394.             cur_val = new_spec(cur_val);
  395.             negate_glue();
  396.         } else {
  397.             cur_val = -cur_val;
  398.         }
  399.     } else if (cur_val_level >= GLUE_VAL && cur_val_level <= MU_VAL) {
  400.         add_glue_ref(cur_val);
  401.     }
  402. }
  403.  
  404. void
  405. scan_eight_bit_int ()
  406. {
  407.     scan_int();
  408.     if (cur_val < 0 || cur_val > 255) {
  409.         print_err("Bad register code");
  410.         help_reg();
  411.         int_error(cur_val);
  412.         cur_val = 0;
  413.     }
  414. }
  415.  
  416. void
  417. scan_char_num ()
  418. {
  419.     scan_int();
  420.     if (cur_val < 0 || cur_val > 255) {
  421.         print_err("Bad character code");
  422.         help_char_num();
  423.         int_error(cur_val);
  424.         cur_val = 0;
  425.     }
  426. }
  427.  
  428. void
  429. scan_four_bit_int()
  430. {
  431.     scan_int();
  432.     if (cur_val < 0 || cur_val > 15) {
  433.         print_err("Bad number");
  434.         help_number();
  435.         int_error(cur_val);
  436.         cur_val = 0;
  437.     }
  438. }
  439.  
  440.  
  441. void
  442. scan_fifteen_bit_int ()
  443. {
  444.     scan_int();
  445.     if (cur_val < 0 || cur_val > 077777) {
  446.         print_err("Bad math code");
  447.         help_mathchar();
  448.         int_error(cur_val);
  449.         cur_val = 0;
  450.     }
  451. }
  452.  
  453. void
  454. scan_twenty_seven_bit_int ()
  455. {
  456.     scan_int();
  457.     if (cur_val < 0 || cur_val> 0777777777) {
  458.         print_err("Bad delimiter code");
  459.         help_del();
  460.         int_error(cur_val);
  461.         cur_val = 0;
  462.     }
  463. }
  464.  
  465. #define get_nbsx_token() \
  466.     {negative = FALSE; \
  467.     do { \
  468.         get_nbx_token(); \
  469.         if (cur_tok == MINUS_TOKEN) { \
  470.             negative = !negative; \
  471.             cur_tok = PLUS_TOKEN; \
  472.         } \
  473.     } while (cur_tok == PLUS_TOKEN);}
  474.  
  475. void
  476. scan_int ()
  477. {
  478.     int    d;
  479.     int    m;
  480.     sym    s;
  481.     bool    vacuous;
  482.     bool    negative;
  483.     bool    OK_so_far;
  484.  
  485.     radix = 0;
  486.     OK_so_far = TRUE;
  487.     get_nbsx_token();
  488.     if (cur_tok == ALPHA_TOKEN) {
  489.         get_token();
  490.         if (cur_tok < CS_TOKEN_FLAG) {
  491.             cur_val = cur_chr;
  492.             if (cur_cmd <= RIGHT_BRACE) {
  493.                 if (cur_cmd == RIGHT_BRACE) {
  494.                     incr(align_state);
  495.                 } else {
  496.                     decr(align_state);
  497.                 }
  498.             }
  499.         } else {
  500.             s = tok2sym(cur_tok);
  501.             if (length(s) == 1) {
  502.                 cur_val = textbyte(s);
  503.             } else {
  504.                 cur_val = 256;
  505.             }
  506.         }
  507.         if (cur_val > 255) {
  508.             print_err("Improper alphabetic constant");
  509.             help_char_const();
  510.             cur_val = 0;
  511.             back_error();
  512.         } else {
  513.             scan_optional_space();
  514.         }
  515.     } else if (cur_cmd >= MIN_INTERNAL && cur_cmd <= MAX_INTERNAL) {
  516.         scan_something_internal(INT_VAL, FALSE);
  517.     } else {
  518.         radix = 10;
  519.         m = 214748364;
  520.         if (cur_tok == OCTAL_TOKEN) {
  521.             radix = 8;
  522.             m = 02000000000;
  523.             get_x_token();
  524.         } else if (cur_tok == HEX_TOKEN) {
  525.             radix = 16;
  526.             m = 010000000000;
  527.             get_x_token();
  528.         }
  529.         vacuous = TRUE;
  530.         cur_val = 0;
  531.         loop {
  532.             if (cur_tok < ZERO_TOKEN + radix
  533.             && cur_tok >= ZERO_TOKEN
  534.             && cur_tok <= ZERO_TOKEN + 9) {
  535.                 d = cur_tok - ZERO_TOKEN;
  536.             } else if (radix == 16) {
  537.                 if (cur_tok <= A_TOKEN + 5
  538.                 && cur_tok >= A_TOKEN) {
  539.                     d = cur_tok - A_TOKEN + 10;
  540.                 } else if (cur_tok <= OTHER_A_TOKEN + 5
  541.                     && cur_tok >= OTHER_A_TOKEN) {
  542.                     d = cur_tok - OTHER_A_TOKEN + 10;
  543.                 } else {
  544.                     break;
  545.                 }
  546.             } else {
  547.                 break;
  548.             }
  549.             vacuous = FALSE;
  550.             if (cur_val >= m
  551.             && (cur_val > m || d > 7 || radix != 10)) {
  552.                 if (OK_so_far) {
  553.                     print_err("Number too big"); 
  554.                     help_big_num();
  555.                     error();
  556.                     cur_val = INFINITY;
  557.                     OK_so_far = FALSE;
  558.                 }
  559.             } else {
  560.                 cur_val = cur_val * radix + d;
  561.             }
  562.             get_x_token();
  563.         }
  564.         if (vacuous) {
  565.             print_err("Missing number, treated as zero");
  566.             help_missing_number();
  567.             back_error();
  568.         } else if (cur_cmd != SPACER) {
  569.             back_input();
  570.         }
  571.     }
  572.     if (negative) {
  573.         cur_val = -cur_val;
  574.     }
  575. }    
  576.     
  577. #define set_conversion(NUM, DENOM) (num = (NUM)), (denom = (DENOM))
  578.  
  579. void
  580. scan_dimen (mu, inf, shortcut)
  581.     bool    mu;
  582.     bool    inf;
  583.     bool    shortcut;
  584. {
  585.     scal    v;
  586.     int    f, k, kk;
  587.     ptr    p, q;
  588.     int    num, denom;
  589.     bool    negative;
  590.     int    save_cur_val;
  591.  
  592.     f = 0;
  593.     negative = FALSE;
  594.     arith_error = FALSE;
  595.     cur_order = NORMAL;
  596.     if (!shortcut) {
  597.         get_nbsx_token();
  598.         if (cur_cmd >= MIN_INTERNAL && cur_cmd <= MAX_INTERNAL)    {
  599.             if (mu) {
  600.                 scan_something_internal(MU_VAL, FALSE);
  601.                 if (cur_val_level >= GLUE_VAL) {
  602.                     v = glue_width(cur_val);
  603.                     delete_glue_ref(cur_val);
  604.                     cur_val = v;
  605.                 }
  606.                 if (cur_val_level == MU_VAL) {
  607.                     goto attach_sign;
  608.                 }
  609.                 if (cur_val_level != INT_VAL) {
  610.                     mu_error();
  611.                 }
  612.             } else {
  613.                 scan_something_internal(DIMEN_VAL, FALSE);
  614.                 if (cur_val_level == DIMEN_VAL)
  615.                     goto attach_sign;
  616.             }
  617.         } else {
  618.             back_input();
  619.             if (cur_tok == EURO_POINT_TOKEN) {
  620.                 cur_tok = POINT_TOKEN;
  621.             }
  622.             if (cur_tok != POINT_TOKEN) {
  623.                 scan_int();
  624.             } else {
  625.                 radix = 10;
  626.                 cur_val = 0;
  627.             }
  628.             if (cur_tok == EURO_POINT_TOKEN) {
  629.                 cur_tok = POINT_TOKEN;
  630.             }
  631.             if (radix == 10 && cur_tok == POINT_TOKEN) {
  632.                 k = 0;
  633.                 p = null;
  634.                 get_token();
  635.                 loop {
  636.                     get_x_token();
  637.                     if (cur_tok > ZERO_TOKEN + 9
  638.                     || cur_tok < ZERO_TOKEN) {
  639.                         break;
  640.                     }
  641.                     if (k < 17) {
  642.                         q = new_avail();
  643.                         link(q) = p;
  644.                         info(q) = cur_tok - ZERO_TOKEN;
  645.                         p = q;
  646.                         incr(k);
  647.                     }
  648.                 }
  649.                 for (kk = k; kk > 0; decr(kk)) {
  650.                     dig[kk - 1] = info(p);
  651.                     q = p;
  652.                     p = link(p);
  653.                     free_avail(q);
  654.                 }
  655.                 f = round_decimals(k);
  656.                 if (cur_cmd != SPACER) {
  657.                     back_input();
  658.                 }
  659.             }
  660.         }
  661.     }
  662.     if (cur_val < 0) {
  663.         negative = !negative;
  664.         cur_val = -cur_val;
  665.     }
  666.     if (inf) {
  667.         if (scan_keyword("fil")) {
  668.             cur_order = FIL;
  669.             while (scan_keyword("l")) {
  670.                 if (cur_order == FILLL) {
  671.                     print_err("Illegal unit of measure (");
  672.                     print("replaced by filll)");
  673.                     help_filll();
  674.                     error();
  675.                 } else {
  676.                     incr(cur_order);
  677.                 }
  678.             }
  679.             goto attach_fraction;
  680.         }
  681.     }
  682.     save_cur_val = cur_val;
  683.     get_nbx_token();
  684.     if (cur_cmd < MIN_INTERNAL || cur_cmd > MAX_INTERNAL) {
  685.         back_input();
  686.     } else {
  687.         if (mu) {
  688.             scan_something_internal(MU_VAL, FALSE);
  689.             if (cur_val_level >= GLUE_VAL) {
  690.                 v = glue_width(cur_val);
  691.                 delete_glue_ref(cur_val);
  692.                 cur_val = v;
  693.             }
  694.             if (cur_val_level != MU_VAL) {
  695.                 mu_error();
  696.             }
  697.         } else {    
  698.             scan_something_internal(DIMEN_VAL, FALSE);
  699.         }
  700.         v = cur_val;
  701.         goto found;
  702.     }
  703.     if (mu) {
  704.         goto not_found;
  705.     }
  706.     if (scan_keyword("em")) {
  707.         v = quad(cur_font);
  708.     } else if (scan_keyword("ex")) {
  709.         v = x_height(cur_font);
  710.     } else {
  711.         goto not_found;
  712.     }
  713.     scan_optional_space();
  714.  
  715. found:
  716.     cur_val = nx_plus_y(save_cur_val, v, xn_over_d(v, f, 0200000));
  717.     goto attach_sign;
  718.  
  719. not_found:
  720.     if (mu)  {
  721.         if (scan_keyword("mu")) {
  722.             goto attach_fraction;
  723.         } else {
  724.             print_err("Illegal unit of measure (");
  725.             print("mu inserted)");
  726.             help_mu();
  727.             error();
  728.             goto attach_fraction;
  729.         }
  730.     }
  731.     if (scan_keyword("true")) {
  732.         prepare_mag();
  733.         if (mag != 1000) {
  734.             cur_val = xn_over_d(cur_val, 1000, mag);
  735.             f = (1000 * f + 0200000 * remainder) / mag;
  736.             cur_val += f / 0200000;
  737.             f %= 0200000;
  738.         }
  739.     }
  740.     if (scan_keyword("pt")) {
  741.         goto attach_fraction;
  742.     }
  743.     if      (scan_keyword("in")) {set_conversion(7227, 100);}
  744.     else if (scan_keyword("pc")) {set_conversion(12, 1);}
  745.     else if (scan_keyword("cm")) {set_conversion(7227, 254);}
  746.     else if (scan_keyword("mm")) {set_conversion(7227, 2540);}
  747.     else if (scan_keyword("bp")) {set_conversion(7227, 7200);}
  748.     else if (scan_keyword("dd")) {set_conversion(1238, 1157);}
  749.     else if (scan_keyword("cc")) {set_conversion(14856, 1157);}
  750.     else if (scan_keyword("sp")) {goto done;}
  751.     else {
  752.         print_err("Illegal unit of measure (");
  753.         print("pt inserted)");
  754.         help_dimen();
  755.         error();
  756.         goto attach_fraction;
  757.     }
  758.     cur_val = xn_over_d(cur_val, num, denom);
  759.     f = (num * f + 0200000 * remainder) / denom;
  760.     cur_val += f / 0200000;
  761.     f %= 0200000;
  762.  
  763. attach_fraction:
  764.     if (cur_val >= 0400000) {
  765.         arith_error = TRUE;
  766.     } else {
  767.         cur_val = cur_val * UNITY + f;
  768.     }
  769.  
  770. done:
  771.     scan_optional_space();
  772.  
  773. attach_sign:
  774.     if (arith_error || abs(cur_val) >= 010000000000) {
  775.         print_err("Dimension too large");
  776.         help_big_dimen();
  777.         error();
  778.         cur_val = MAX_DIMEN;
  779.         arith_error = FALSE;
  780.     }
  781.     if (negative) {
  782.         cur_val = -cur_val;
  783.     }
  784. }
  785.  
  786. void
  787. scan_glue (level)
  788.     int    level;
  789. {
  790.     ptr    q;
  791.     bool    mu;
  792.     bool    negative;
  793.  
  794.     mu = (level == MU_VAL);
  795.     get_nbsx_token();
  796.     if (cur_cmd >= MIN_INTERNAL && cur_cmd <= MAX_INTERNAL) {
  797.         scan_something_internal(level, negative);
  798.         if (cur_val_level >= GLUE_VAL) {
  799.             if (cur_val_level != level) {
  800.                 mu_error();
  801.             }
  802.             return;
  803.         }
  804.         if (cur_val_level == INT_VAL) {
  805.             scan_dimen(mu, FALSE, TRUE);
  806.         } else if (level == MU_VAL) {
  807.             mu_error();
  808.         }
  809.     } else {
  810.         back_input();
  811.         scan_dimen(mu, FALSE, FALSE);
  812.         if (negative) {
  813.             cur_val = -cur_val;
  814.         }
  815.     }
  816.     q = new_spec(zero_glue);
  817.     glue_width(q) = cur_val;
  818.     if (scan_keyword("plus")) {
  819.         scan_dimen(mu, TRUE, FALSE);
  820.         stretch(q) = cur_val;
  821.         stretch_order(q) = cur_order;
  822.     }
  823.     if (scan_keyword("minus")) {
  824.         scan_dimen(mu, TRUE, FALSE);
  825.         shrink(q) = cur_val;
  826.         shrink_order(q) = cur_order;
  827.     }
  828.     cur_val = q;
  829. }
  830.  
  831. void
  832. scan_spec (c, three_codes)
  833.     int    c;
  834.     bool    three_codes;
  835. {
  836.     int    s;
  837.     int    spec_code;
  838.  
  839.     if (three_codes) {
  840.         s = saved(0);
  841.     }
  842.     if (scan_keyword("to")) {
  843.         spec_code = EXACTLY;
  844.     } else if (scan_keyword("spread")) {
  845.         spec_code = ADDITIONAL;
  846.     } else {
  847.         spec_code = ADDITIONAL;
  848.         cur_val = 0;
  849.         goto found;
  850.     }
  851.     scan_normal_dimen();
  852.  
  853. found:
  854.     if (three_codes) {
  855.         saved(0) = s;
  856.         incr(save_ptr);
  857.     }
  858.     saved(0) = spec_code;
  859.     saved(1) = cur_val;
  860.     save_ptr += 2;
  861.     new_save_level(c);
  862.     scan_left_brace();
  863. }
  864.  
  865. #define DEFAULT_RULE    26214
  866.  
  867. ptr
  868. scan_rule_spec ()
  869. {
  870.     ptr    q;
  871.  
  872.     q = new_rule();
  873.     if (cur_cmd == VRULE) {
  874.         rule_width(q) = DEFAULT_RULE;
  875.     } else {
  876.         rule_height(q) = DEFAULT_RULE;
  877.         rule_depth(q) = 0;
  878.     }
  879.  
  880. reswitch:
  881.     if (scan_keyword("width")) {
  882.         scan_normal_dimen();
  883.         rule_width(q) = cur_val;
  884.         goto reswitch;
  885.     }
  886.     if (scan_keyword("height")) {
  887.         scan_normal_dimen();
  888.         rule_height(q) = cur_val;
  889.         goto reswitch;
  890.     }
  891.     if (scan_keyword("depth")) {
  892.         scan_normal_dimen();
  893.         rule_depth(q) = cur_val;
  894.         goto reswitch;
  895.     }
  896.     return q;
  897. }
  898.  
  899. void
  900. _scan_init ()
  901. {
  902.     cur_val = 0;
  903.     cur_val_level = 0;
  904.     radix = 0;
  905. }
  906.  
  907. void
  908. _scan_init_once ()
  909. {
  910. }
  911.  
  912. /*
  913. **     Help text
  914. */
  915.  
  916. help_mathchar ()
  917. {
  918.     help2("A numeric math code must be between 0 and 32767.",
  919.     "I changed this one to zero.");
  920. }
  921.  
  922. help_number ()
  923. {
  924.     help2("Since I expected to read a number between 0 and 15,",
  925.     "I changed this one to zero.");
  926. }
  927.  
  928. help_char_num ()
  929. {
  930.     help2("A character number must be between 0 and 255.",
  931.     "I changed this one to zero.");
  932. }
  933.  
  934. help_char_const ()
  935. {
  936.     help2("A one-character control sequence belongs after a ` mark.",
  937.     "So I'm essentially inserting \\0 here.");
  938. }
  939.  
  940. help_big_num ()
  941. {
  942.     help2("I can only go up to 2147483647='17777777777=\"7FFFFFFF,",
  943.     "so I'm using that number instead of yours.");
  944. }
  945.  
  946. help_missing_number ()
  947. {
  948.     help3("A number should have been here; I inserted `0'.",
  949.     "(If you can't figure out why I needed to see a number,",
  950.     "look up `weird error' in the index to The TeXbook.)");
  951. }
  952.  
  953. help_filll ()
  954. {
  955.     help1("I dddon't go any higher than filll.");
  956. }
  957.  
  958. help_mu ()
  959. {
  960.     help4("The unit of measurement in math glue must be mu.",
  961.     "To recover gracefully from this error, it's best to",
  962.     "delete the erroneous units; e.g., type `2' to delete",
  963.     "two letters. (See Chapter 27 of The TeXbook.)");
  964. }
  965.  
  966. help_mu_error ()
  967. {
  968.     help1("I'm going to assume that 1mu=1pt when they're mixed.");
  969. }
  970.  
  971. help_dimen ()
  972. {
  973.     help6("Dimensions can be in units of em, ex, in, pt, pc,",
  974.     "cm, mm, dd, cc, bp, or sp; but yours is a new one!",
  975.     "I'll assume that you meant to say pt, for printer's points.",
  976.     "To recover gracefully from this error, it's best to",
  977.     "delete the erroneous units; e.g., type `2' to delete",
  978.     "two letters. (See Chapter 27 of The TeXbook.)");
  979. }
  980.  
  981. help_big_dimen ()
  982. {
  983.     help2("I can't work with sizes bigger than about 19 feet.",
  984.     "Continue and I'll use the largest value I can.");
  985. }
  986.  
  987. help_thee ()
  988. {
  989.     help1("I'm forgetting what you said and using zero instead.");
  990. }
  991.  
  992. help_left ()
  993. {
  994.     help4("A left brace was mandatory here, so I've put one in.",
  995.     "You might want to delete and/or insert some corrections",
  996.     "so that I will find a matching right brace soon.",
  997.     "(If you're confused by all this, try typing `I}' now.)")
  998. }
  999.  
  1000. help_aux ()
  1001. {
  1002.     help4("You can refer to \\spacefactor only in horizontal mode;",
  1003.     "you can refer to \\prevdepth only in vertical mode; and",
  1004.     "neither of these is meaningful inside \\write. So",
  1005.     "I'm forgetting what you said and using zero instead.");
  1006. }
  1007.  
  1008. help_del ()
  1009. {
  1010.     help2("A numeric delimiter code must be between 0 and 2^{27}-1.",
  1011.     "I changed this one to zero.");
  1012. }
  1013.  
  1014. help_reg ()
  1015. {
  1016.     help2("A register number must be between 0 and 255.",
  1017.     "I changed this one to zero.");
  1018. }
  1019.