home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / rtt / rttlex.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  19KB  |  434 lines

  1. /*
  2.  * This lexical analyzer uses the preprocessor to convert text into tokens.
  3.  *  The lexical anayser discards white space, checks to see if identifiers
  4.  *  are reserved words or typedef names, makes sure single characters
  5.  *  are valid tokens, and converts preprocessor constants into the
  6.  *  various C constants.
  7.  */
  8. #include <ctype.h>
  9. #include "rtt.h"
  10.  
  11. /*
  12.  * Prototype for static function.
  13.  */
  14. hidden int int_suffix Params((char *s));
  15.  
  16. int lex_state = DfltLex;
  17.  
  18. char *ident = "ident";
  19.  
  20. /*
  21.  * Characters are used as token id's for single character tokens. The
  22.  *  following table indicates which ones can be valid for RTL.
  23.  */
  24. #if EBCDIC
  25. #define GoodChar(c) (good_char[c])
  26. static int good_char[256] = {
  27.    0  /* \000 */,   0  /* \001 */,   0  /* \002 */,   0  /* \003 */,
  28.    0  /* \004 */,   0  /* \005 */,   0  /* \006 */,   0  /* \007 */,
  29.    0  /* \010 */,   0  /* \011 */,   0  /* \012 */,   0  /* \013 */,
  30.    0  /* \014 */,   0  /* \015 */,   0  /* \016 */,   0  /* \017 */,
  31.    0  /* \020 */,   0  /* \021 */,   0  /* \022 */,   0  /* \023 */,
  32.    0  /* \024 */,   0  /* \025 */,   0  /* \026 */,   0  /* \027 */,
  33.    0  /* \030 */,   0  /* \031 */,   0  /* \032 */,   0  /* \033 */,
  34.    0  /* \034 */,   0  /* \035 */,   0  /* \036 */,   0  /* \037 */,
  35.    0  /* \040 */,   0  /* \041 */,   0  /* \042 */,   0  /* \043 */,
  36.    0  /* \044 */,   0  /* \045 */,   0  /* \046 */,   0  /* \047 */,
  37.    0  /* \050 */,   0  /* \051 */,   0  /* \052 */,   0  /* \053 */,
  38.    0  /* \054 */,   0  /* \055 */,   0  /* \056 */,   0  /* \057 */,
  39.    0  /* \060 */,   0  /* \061 */,   0  /* \062 */,   0  /* \063 */,
  40.    0  /* \064 */,   0  /* \065 */,   0  /* \066 */,   0  /* \067 */,
  41.    0  /* \070 */,   0  /* \071 */,   0  /* \072 */,   0  /* \073 */,
  42.    0  /* \074 */,   0  /* \075 */,   0  /* \076 */,   0  /* \077 */,
  43.    0  /*      */,   0  /* \101 */,   0  /* \102 */,   0  /* \103 */,
  44.    0  /* \104 */,   0  /* \105 */,   0  /* \106 */,   0  /* \107 */,
  45.    0  /* \110 */,   0  /* \111 */,   0  /* \112 */,   1  /*  .   */,
  46.    1  /*  <   */,   1  /*  (   */,   1  /*  +   */,   1  /*  |   */,
  47.    1  /*  &   */,   0  /* \121 */,   0  /* \122 */,   0  /* \123 */,
  48.    0  /* \124 */,   0  /* \125 */,   0  /* \126 */,   0  /* \127 */,
  49.    0  /* \130 */,   0  /* \131 */,   1  /*  !   */,   0  /*  $   */,
  50.    1  /*  *   */,   1  /*  )   */,   1  /*  ;   */,   1  /*  ^   */,
  51.    1  /*  -   */,   1  /*  /   */,   0  /* \142 */,   0  /* \143 */,
  52.    0  /* \144 */,   0  /* \145 */,   0  /* \146 */,   0  /* \147 */,
  53.    0  /* \150 */,   0  /* \151 */,   0  /* \152 */,   1  /*  ,   */,
  54.    1  /*  %   */,   0  /*  _   */,   1  /*  >   */,   1  /*  ?   */,
  55.    0  /* \160 */,   0  /* \161 */,   0  /* \162 */,   0  /* \163 */,
  56.    0  /* \164 */,   0  /* \165 */,   0  /* \166 */,   0  /* \167 */,
  57.    0  /* \170 */,   0  /*  `   */,   1  /*  :   */,   0  /*  #   */,
  58.    0  /*  @   */,   0  /*  '   */,   1  /*  =   */,   0  /*  "   */,
  59.    0  /* \200 */,   0  /*  a   */,   0  /*  b   */,   0  /*  c   */,
  60.    0  /*  d   */,   0  /*  e   */,   0  /*  f   */,   0  /*  g   */,
  61.    0  /*  h   */,   0  /*  i   */,   0  /* \212 */,   0  /* \213 */,
  62.    0  /* \214 */,   0  /* \215 */,   0  /* \216 */,   0  /* \217 */,
  63.    0  /* \220 */,   0  /*  j   */,   0  /*  k   */,   0  /*  l   */,
  64.    0  /*  m   */,   0  /*  n   */,   0  /*  o   */,   0  /*  p   */,
  65.    0  /*  q   */,   0  /*  r   */,   0  /* \232 */,   0  /* \233 */,
  66.    0  /* \234 */,   0  /* \235 */,   0  /* \236 */,   0  /* \237 */,
  67.    0  /* \240 */,   1  /*  ~   */,   0  /*  s   */,   0  /*  t   */,
  68.    0  /*  u   */,   0  /*  v   */,   0  /*  w   */,   0  /*  x   */,
  69.    0  /*  y   */,   0  /*  z   */,   0  /* \252 */,   0  /* \253 */,
  70.    0  /* \254 */,   1  /*  [   */,   0  /* \256 */,   0  /* \257 */,
  71.    0  /* \260 */,   0  /* \261 */,   0  /* \262 */,   0  /* \263 */,
  72.    0  /* \264 */,   0  /* \265 */,   0  /* \266 */,   0  /* \267 */,
  73.    0  /* \270 */,   0  /* \271 */,   0  /* \272 */,   0  /* \273 */,
  74.    0  /* \274 */,   1  /*  ]   */,   0  /* \276 */,   0  /* \277 */,
  75.    1  /*  {   */,   0  /*  A   */,   0  /*  B   */,   0  /*  C   */,
  76.    0  /*  D   */,   0  /*  E   */,   0  /*  F   */,   0  /*  G   */,
  77.    0  /*  H   */,   0  /*  I   */,   0  /* \312 */,   0  /* \313 */,
  78.    0  /* \314 */,   0  /* \315 */,   0  /* \316 */,   0  /* \317 */,
  79.    1  /*  }   */,   0  /*  J   */,   0  /*  K   */,   0  /*  L   */,
  80.    0  /*  M   */,   0  /*  N   */,   0  /*  O   */,   0  /*  P   */,
  81.    0  /*  Q   */,   0  /*  R   */,   0  /* \332 */,   0  /* \333 */,
  82.    0  /* \334 */,   0  /* \335 */,   0  /* \336 */,   0  /* \337 */,
  83.    1  /*  \\  */,   0  /* \341 */,   0  /*  S   */,   0  /*  T   */,
  84.    0  /*  U   */,   0  /*  V   */,   0  /*  W   */,   0  /*  X   */,
  85.    0  /*  Y   */,   0  /*  Z   */,   0  /* \352 */,   0  /* \353 */,
  86.    0  /* \354 */,   0  /* \355 */,   0  /* \356 */,   0  /* \357 */,
  87.    0  /*  0   */,   0  /*  1   */,   0  /*  2   */,   0  /*  3   */,
  88.    0  /*  4   */,   0  /*  5   */,   0  /*  6   */,   0  /*  7   */,
  89.    0  /*  8   */,   0  /*  9   */,   0  /* \372 */,   0  /* \373 */,
  90.    0  /* \374 */,   0  /* \375 */,   0  /* \376 */,   0  /* \377 */,
  91.    };
  92.  
  93. #else                    /* EBCDIC */
  94.  
  95. #define GoodChar(c) ((c) < 127 && good_char[c])
  96. static int good_char[128] = {
  97.    0  /* \000 */,   0  /* \001 */,   0  /* \002 */,   0  /* \003 */,
  98.    0  /* \004 */,   0  /* \005 */,   0  /* \006 */,   0  /* \007 */,
  99.    0  /*  \b  */,   0  /*  \t  */,   0  /*  \n  */,   0  /*  \v  */,
  100.    0  /*  \f  */,   0  /*  \r  */,   0  /* \016 */,   0  /* \017 */,
  101.    0  /* \020 */,   0  /* \021 */,   0  /* \022 */,   0  /* \023 */,
  102.    0  /* \024 */,   0  /* \025 */,   0  /* \026 */,   0  /* \027 */,
  103.    0  /* \030 */,   0  /* \031 */,   0  /* \032 */,   0  /*  \e  */,
  104.    0  /* \034 */,   0  /* \035 */,   0  /* \036 */,   0  /* \037 */,
  105.    0  /*      */,   1  /*  !   */,   0  /*  \   */,   0  /*  #   */,
  106.    0  /*  $   */,   1  /*  %   */,   1  /*  &   */,   0  /*  '   */,
  107.    1  /*  (   */,   1  /*  )   */,   1  /*  *   */,   1  /*  +   */,
  108.    1  /*  ,   */,   1  /*  -   */,   1  /*  .   */,   1  /*  /   */,
  109.    0  /*  0   */,   0  /*  1   */,   0  /*  2   */,   0  /*  3   */,
  110.    0  /*  4   */,   0  /*  5   */,   0  /*  6   */,   0  /*  7   */,
  111.    0  /*  8   */,   0  /*  9   */,   1  /*  :   */,   1  /*  ;   */,
  112.    1  /*  <   */,   1  /*  =   */,   1  /*  >   */,   1  /*  ?   */,
  113.    0  /*  @   */,   0  /*  A   */,   0  /*  B   */,   0  /*  C   */,
  114.    0  /*  D   */,   0  /*  E   */,   0  /*  F   */,   0  /*  G   */,
  115.    0  /*  H   */,   0  /*  I   */,   0  /*  J   */,   0  /*  K   */,
  116.    0  /*  L   */,   0  /*  M   */,   0  /*  N   */,   0  /*  O   */,
  117.    0  /*  P   */,   0  /*  Q   */,   0  /*  R   */,   0  /*  S   */,
  118.    0  /*  T   */,   0  /*  U   */,   0  /*  V   */,   0  /*  W   */,
  119.    0  /*  X   */,   0  /*  Y   */,   0  /*  Z   */,   1  /*  [   */,
  120.    1  /*  \\  */,   1  /*  ]   */,   1  /*  ^   */,   0  /*  _   */,
  121.    0  /*  `   */,   0  /*  a   */,   0  /*  b   */,   0  /*  c   */,
  122.    0  /*  d   */,   0  /*  e   */,   0  /*  f   */,   0  /*  g   */,
  123.    0  /*  h   */,   0  /*  i   */,   0  /*  j   */,   0  /*  k   */,
  124.    0  /*  l   */,   0  /*  m   */,   0  /*  n   */,   0  /*  o   */,
  125.    0  /*  p   */,   0  /*  q   */,   0  /*  r   */,   0  /*  s   */,
  126.    0  /*  t   */,   0  /*  u   */,   0  /*  v   */,   0  /*  w   */,
  127.    0  /*  x   */,   0  /*  y   */,   0  /*  z   */,   1  /*  {   */,
  128.    1  /*  |   */,   1  /*  }   */,   1  /*  ~   */,   0  /*  \d  */
  129.    };
  130. #endif                    /* EBCDIC */
  131.  
  132. /*
  133.  * init_lex - initialize lexical analyzer.
  134.  */
  135. novalue init_lex()
  136.    {
  137.    struct sym_entry *sym;
  138.    int i;
  139.    static int first_time = 1;
  140.  
  141.    if (first_time) {
  142.       first_time = 0;
  143.       ident = spec_str(ident);  /* install ident in string table */
  144.       /*
  145.        * install C keywords into the symbol table
  146.        */
  147.       sym_add(Auto,          spec_str("auto"),          OtherDcl, 0);
  148.       sym_add(Break,         spec_str("break"),         OtherDcl, 0);
  149.       sym_add(Case,          spec_str("case"),          OtherDcl, 0);
  150.       sym_add(Char,          spec_str("char"),          OtherDcl, 0);
  151.       sym_add(Const,         spec_str("const"),         OtherDcl, 0);
  152.       sym_add(Continue,      spec_str("continue"),      OtherDcl, 0);
  153.       sym_add(Default,       spec_str("default"),       OtherDcl, 0);
  154.       sym_add(Do,            spec_str("do"),            OtherDcl, 0);
  155.       sym_add(Doubl,         spec_str("double"),        OtherDcl, 0);
  156.       sym_add(Else,          spec_str("else"),          OtherDcl, 0);
  157.       sym_add(Enum,          spec_str("enum"),          OtherDcl, 0);
  158.       sym_add(Extern,        spec_str("extern"),        OtherDcl, 0);
  159.       sym_add(Float,         spec_str("float"),         OtherDcl, 0);
  160.       sym_add(For,           spec_str("for"),           OtherDcl, 0);
  161.       sym_add(Goto,          spec_str("goto"),          OtherDcl, 0);
  162.       sym_add(If,            spec_str("if"),            OtherDcl, 0);
  163.       sym_add(Int,           spec_str("int"),           OtherDcl, 0);
  164.       sym_add(Long,          spec_str("long"),          OtherDcl, 0);
  165.       sym_add(Register,      spec_str("register"),      OtherDcl, 0);
  166.       sym_add(Return,        spec_str("return"),        OtherDcl, 0);
  167.       sym_add(Short,         spec_str("short"),         OtherDcl, 0);
  168.       sym_add(Signed,        spec_str("signed"),        OtherDcl, 0);
  169.       sym_add(Sizeof,        spec_str("sizeof"),        OtherDcl, 0);
  170.       sym_add(Static,        spec_str("static"),        OtherDcl, 0);
  171.       sym_add(Struct,        spec_str("struct"),        OtherDcl, 0);
  172.       sym_add(Switch,        spec_str("switch"),        OtherDcl, 0);
  173.       sym_add(Typedef,       spec_str("typedef"),       OtherDcl, 0);
  174.       sym_add(Union,         spec_str("union"),         OtherDcl, 0);
  175.       sym_add(Unsigned,      spec_str("unsigned"),      OtherDcl, 0);
  176.       sym_add(Void,          spec_str("void"),          OtherDcl, 0);
  177.       sym_add(Volatile,      spec_str("volatile"),      OtherDcl, 0);
  178.       sym_add(While,         spec_str("while"),         OtherDcl, 0);
  179.  
  180.       /*
  181.        * Install keywords from run-time interface language.
  182.        */
  183.       sym_add(Abstract,      spec_str("abstract"),      OtherDcl, 0);
  184.       sym_add(All_fields,    spec_str("all_fields"),    OtherDcl, 0);
  185.       sym_add(Any_value,     spec_str("any_value"),     OtherDcl, 0);
  186.       sym_add(Arith_case,    spec_str("arith_case"),    OtherDcl, 0);
  187.       sym_add(Body,          spec_str("body"),          OtherDcl, 0);
  188.       sym_add(C_Double,      spec_str("C_double"),      OtherDcl, 0);
  189.       sym_add(C_Integer,     spec_str("C_integer"),     OtherDcl, 0);
  190.       sym_add(C_String,      spec_str("C_string"),      OtherDcl, 0);
  191.       sym_add(Cnv,           spec_str("cnv"),           OtherDcl, 0);
  192.       sym_add(Constant,      spec_str("constant"),      OtherDcl, 0);
  193.       sym_add(Declare,       spec_str("declare"),       OtherDcl, 0);
  194.       sym_add(Def,           spec_str("def"),           OtherDcl, 0);
  195.       sym_add(Empty_type,    spec_str("empty_type"),    OtherDcl, 0);
  196.       sym_add(End,           spec_str("end"),           OtherDcl, 0);
  197.       sym_add(Errorfail,     spec_str("errorfail"),     OtherDcl, 0);
  198.       sym_add(Exact,         spec_str("exact"),         OtherDcl, 0);
  199.       sym_add(Fail,          spec_str("fail"),          OtherDcl, 0);
  200.       sym_add(Function,      spec_str("function"),      OtherDcl, 0);
  201.       sym_add(Inline,        spec_str("inline"),        OtherDcl, 0);
  202.       sym_add(Is,            spec_str("is"),            OtherDcl, 0);
  203.       sym_add(Keyword,       spec_str("keyword"),       OtherDcl, 0);
  204.       sym_add(Len_case,      spec_str("len_case"),      OtherDcl, 0);
  205.       sym_add(Named_var,     spec_str("named_var"),     OtherDcl, 0);
  206.       sym_add(New,           spec_str("new"),           OtherDcl, 0);
  207.       sym_add(Of,            spec_str("of"),            OtherDcl, 0);
  208.       sym_add(Operator,      spec_str("operator"),      OtherDcl, 0);
  209.       str_rslt = spec_str("result");
  210.       sym_add(Runerr,        spec_str("runerr"),        OtherDcl, 0);
  211.       sym_add(Store,         spec_str("store"),         OtherDcl, 0);
  212.       sym_add(Struct_var,    spec_str("struct_var"),    OtherDcl, 0);
  213.       sym_add(Suspend,       spec_str("suspend"),       OtherDcl, 0);
  214.       sym_add(Tended,        spec_str("tended"),        OtherDcl, 0);
  215.       sym_add(Then,          spec_str("then"),          OtherDcl, 0);
  216.       sym_add(Tmp_cset,      spec_str("tmp_cset"),      OtherDcl, 0);
  217.       sym_add(Tmp_string,    spec_str("tmp_string"),    OtherDcl, 0);
  218.       sym_add(Type,          spec_str("type"),          OtherDcl, 0);
  219.       sym_add(Type_case,     spec_str("type_case"),     OtherDcl, 0);
  220.       sym_add(Underef,       spec_str("underef"),       OtherDcl, 0);
  221.       sym_add(Variable,      spec_str("variable"),      OtherDcl, 0);
  222.  
  223.       for (i = 0; i < num_typs; ++i) {
  224.          icontypes[i].id = spec_str(icontypes[i].id);
  225.          sym = sym_add(IconType, icontypes[i].id, OtherDcl, 0);
  226.          sym->u.typ_indx = i;
  227.          }
  228.  
  229.       for (i = 0; i < num_cmpnts; ++i) {
  230.          typecompnt[i].id = spec_str(typecompnt[i].id);
  231.          sym = sym_add(Component, typecompnt[i].id, OtherDcl, 0);
  232.          sym->u.typ_indx = i;
  233.          }
  234.       }
  235.    }
  236.  
  237. /*
  238.  * int_suffix - we have reached the end of what seems to be an integer
  239.  *  constant. check for a valid suffix.
  240.  */
  241. static int int_suffix(s)
  242. char *s;
  243.    {
  244.    int tok_id;
  245.  
  246.    if (*s == 'u' || *s == 'U') {
  247.       ++s;
  248.       if (*s == 'l' || *s == 'L') {
  249.          ++s;
  250.          tok_id = ULIntConst;  /* unsigned long */
  251.          }
  252.       else
  253.          tok_id  = UIntConst;  /* unsigned */
  254.       }
  255.    else if (*s == 'l' || *s == 'L') {
  256.       ++s;
  257.       if (*s == 'u' || *s == 'U') {
  258.          ++s;
  259.          tok_id = ULIntConst;  /* unsigned long */
  260.          }
  261.       else
  262.          tok_id = LIntConst;   /* long */
  263.       }
  264.    else
  265.       tok_id = IntConst;       /* plain int */
  266.    if (*s != '\0')
  267.       errt2(yylval.t, "invalid integer constant: ", yylval.t->image);
  268.    return tok_id;
  269.    }
  270.  
  271. /*
  272.  * yylex - lexical analyzer, called by yacc-generated parser.
  273.  */
  274. int yylex()
  275.    {
  276.    register char *s;
  277.    struct sym_entry *sym;
  278.    struct token *lk_ahead = NULL;
  279.    int is_float;
  280.    struct str_buf *sbuf;
  281.  
  282.    /*
  283.     * See if the last call to yylex() left a token from looking ahead.
  284.     */
  285.    if (lk_ahead == NULL)
  286.       yylval.t = preproc();
  287.    else {
  288.       yylval.t = lk_ahead;
  289.       lk_ahead = NULL;
  290.       }
  291.  
  292.    /*
  293.     * Skip white space, then check for end-of-input.
  294.     */
  295.    while (yylval.t != NULL && yylval.t->tok_id == WhiteSpace) {
  296.       free_t(yylval.t);
  297.       yylval.t = preproc();
  298.       }
  299.    if (yylval.t == NULL)
  300.       return 0;
  301.  
  302.    /*
  303.     * The rtt recognizes ** as an operator in abstract type computations.
  304.     *  The parsing context is indicated by lex_state.
  305.     */
  306.    if (lex_state == TypeComp && yylval.t->tok_id == '*') {
  307.       lk_ahead = preproc();
  308.       if (lk_ahead != NULL && lk_ahead->tok_id == '*') {
  309.          free_t(lk_ahead);
  310.          lk_ahead = NULL;
  311.          yylval.t->tok_id = Intersect;
  312.          yylval.t->image = spec_str("**");
  313.          }
  314.       }
  315.  
  316.    /*
  317.     * Some tokens are passed along without change, but some need special
  318.     *  processing: identifiers, numbers, PpKeep tokens, and single
  319.     *  character tokens.
  320.     */
  321.    if (yylval.t->tok_id == Identifier) {
  322.       /*
  323.        * See if this is an identifier, a reserved word, or typedef name.
  324.        */
  325.       sym = sym_lkup(yylval.t->image);
  326.       if (sym != NULL)
  327.          yylval.t->tok_id = sym->tok_id;
  328.       }
  329.    else if (yylval.t->tok_id == PpNumber) {
  330.       /*
  331.        * Determine what kind of numeric constant this is.
  332.        */
  333.       s = yylval.t->image;
  334.       if (*s == '0' && (*++s == 'x' || *s == 'X')) {
  335.          /*
  336.           * Hex integer constant.
  337.           */
  338.          ++s;
  339.          while (isxdigit(*s))
  340.             ++s;
  341.          yylval.t->tok_id = int_suffix(s);
  342.          }
  343.       else {
  344.          is_float = 0;
  345.          while (isdigit(*s))
  346.              ++s;
  347.          if (*s == '.') {
  348.             is_float = 1;
  349.             ++s;
  350.             while (isdigit(*s))
  351.                ++s;
  352.             }
  353.          if (*s == 'e' || *s == 'E') {
  354.             is_float = 1;
  355.             ++s;
  356.             if (*s == '+' || *s == '-')
  357.                ++s;
  358.             while (isdigit(*s))
  359.                ++s;
  360.             }
  361.          if (is_float) {
  362.             switch (*s) {
  363.                case '\0':
  364.                   yylval.t->tok_id = DblConst;   /* double */
  365.                   break;
  366.                case 'f': case 'F':
  367.                    yylval.t->tok_id = FltConst;  /* float */
  368.                    break;
  369.                case 'l': case 'L':
  370.                    yylval.t->tok_id = LDblConst; /* long double */
  371.                    break;
  372.                default:
  373.                    errt2(yylval.t, "invalid float constant: ", yylval.t->image);
  374.                }
  375.             }
  376.          else {
  377.             /*
  378.              * This appears to be an integer constant. If it starts
  379.              *  with '0', it should be an octal constant.
  380.              */
  381.             if (yylval.t->image[0] == '0') {
  382.                s = yylval.t->image;
  383.                while (*s >= '0' && *s <= '7')
  384.                   ++s;
  385.                }
  386.             yylval.t->tok_id = int_suffix(s);
  387.             }
  388.          }
  389.       }
  390.    else if (yylval.t->tok_id == PpKeep) {
  391.       /*
  392.        * This is a non-standard preprocessor directive that must be
  393.        *  passed on to the output.
  394.        */
  395.       keepdir(yylval.t);
  396.       return yylex();
  397.       }
  398.    else if (lex_state == OpHead && yylval.t->tok_id != '}' &&
  399.      GoodChar(yylval.t->image[0])) {
  400.       /*
  401.        * This should be the operator symbol in the header of an operation
  402.        *  declaration. Concatenate all operator symbols into one token
  403.        *  of type OpSym.
  404.        */
  405.       sbuf = get_sbuf();
  406.       for (s = yylval.t->image; *s != '\0'; ++s)
  407.          AppChar(*sbuf, *s);
  408.       lk_ahead = preproc();
  409.       while (lk_ahead != NULL && GoodChar(lk_ahead->image[0])) {
  410.          for (s = lk_ahead->image; *s != '\0'; ++s)
  411.             AppChar(*sbuf, *s);
  412.          free_t(lk_ahead);
  413.          lk_ahead = preproc();
  414.          }
  415.       yylval.t->tok_id = OpSym;
  416.       yylval.t->image = str_install(sbuf);
  417.       rel_sbuf(sbuf);
  418.       }
  419.    else if (yylval.t->tok_id < 256) {
  420.       /*
  421.        * This is a one-character token, make sure it is valid.
  422.        */
  423.       if (!GoodChar(yylval.t->tok_id))
  424.          errt2(yylval.t, "invalid character: ", yylval.t->image);
  425.       }
  426.  
  427. #if EBCDIC
  428.    if (yylval.t->tok_id < 256)
  429.       return FromEBCDIC[yylval.t->tok_id];
  430. #endif
  431.  
  432.    return yylval.t->tok_id;
  433.    }
  434.