📄 token.c
字号:
/* Handle first non-zero digit */ if ((digit=digit_value[ch]) < radix) { value = digit; save_ch(ch); ch = next_ch(); /* Add digits until boundary case reached */ while((digit=digit_value[ch]) < radix && value < (MAX_ULONG / radix)) { value = value * radix + digit; save_ch(ch); ch = next_ch(); }; /* Scan remaining digits */ if ((digit=digit_value[ch]) < radix) { /* Examine boundary case --- * radix*(MAX_ULONG/radix) <= number <= MAX_ULONG */ if (value == (MAX_ULONG/radix) && digit <= MAX_ULONG%radix) value = value * radix + digit; else ++scale; /* Continue scanning digits, but can't store them */ save_ch(ch); ch = next_ch(); while(digit_value[ch] < radix) { ++scale; save_ch(ch); ch = next_ch(); } } } /* Store result */ r_value = (LONG) value; /* result is signed */ r_scale = scale; return(ch);} /* ------------------------------------------------------------------- * Complete a number; set token type and done flag. * Put current input character back, if it is not white space. */ /* Done: Radix Number */static int RADIX_NUMBER(ch) int ch;{ back_ch_not_white(ch); if (r_scale == 0) { tokenValue.integer = r_value; tokenType = TOKEN_INTEGER; } else { tokenType = TOKEN_NAME; } return(DONE);} /* Done: Integer */static int INTEGER(ch) int ch;{ back_ch_not_white(ch); if (m_scale == 0) { tokenValue.integer = m_value; tokenType = TOKEN_INTEGER; } else { tokenValue.real = (DOUBLE)(m_value) * Exp10(m_scale); tokenType = TOKEN_REAL; } return(DONE);} /* Done: Real */static int REAL(ch) int ch;{ DOUBLE temp; back_ch_not_white(ch); /* NOTE: ignore e_scale, since e_value alone will cause * exponent overflow if e_scale > 0. */ /* HAZARD: exponent overflow of intermediate result * (e.g., in 370 floating point); this should not be a problem * with IEEE floating point. Reduce exponent overflow hazard by * combining m_scale and e_value first, if they have different signs, * or multiplying m_value and one of the other factors, if both * m_scale and e_value are negative. */ if ((m_scale >= 0 && e_value <= 0) || (m_scale <= 0 && e_value >= 0)) { tokenValue.real = (DOUBLE)(m_value) * Exp10(m_scale + e_value); } else { temp = (DOUBLE)(m_value) * Exp10(m_scale); tokenValue.real = temp * Exp10(e_value); } tokenType = TOKEN_REAL; return(DONE);} /* ------------------------------------------------------------------- * Assemble a hex string; set token type and done flag. */ /* Done: Hex String */static int HEX_STRING(ch) int ch;{ int value; while(TRUE) { /* Process odd digit */ ch = next_ch(); if (!isHEX_DIGIT(ch)) { /* Skip white space */ while(isWHITE_SPACE(ch)) ch = next_ch(); /* Check for terminator */ if (!isHEX_DIGIT(ch)) { break; } } value = digit_value[ch] << 4; /* Process even digit */ ch = next_ch(); if (!isHEX_DIGIT(ch)) { /* Skip white space */ while(isWHITE_SPACE(ch)) ch = next_ch(); /* Check for terminator */ if (!isHEX_DIGIT(ch)) { save_ch(value); break; } } save_ch(value + digit_value[ch]); } /* Classify result, based on why loop ended */ if (ch == '>') tokenType = TOKEN_HEX_STRING; else { /* save the invalid character for error reporting */ save_ch(ch); tokenType = TOKEN_INVALID; } return(DONE);} /* ------------------------------------------------------------------- * Assemble a string; set token type and done flag */ /* Save a backslash-coded character in a string -- * * Store the proper character for special cases * "\b", "\f", "\n", "\r", and "\t". * * Decode and store octal-coded character, up to * three octal digits, "\o", "\oo", and "\ooo". * * The sequence "\<newline>" is a line continuation, * so consume both without storing anything. * * The sequence "\<EOF>" is an error; exit without * storing anything and let the caller handle it. * * For other characters, including the sequences * "\\", "\(", and "\)", simply store the second * character. */static void save_digraph(ch) int ch;{ int value; switch (ch) { case 'b': /* backspace */ ch = '\b'; break; case 'f': /* formfeed */ ch = '\f'; break; case 'n': /* newline */ ch = '\n'; break; case 'r': /* carriage return */ ch = '\r'; break; case 't': /* horizontal tab */ ch = '\t'; break; case '\n': /* line continuation -- consume it */ return; case '\r': /* carriage return -- consume it */ ch = next_ch(); /* look at next character, is it \n? */ if (ch == '\n') return; back_ch(ch); /* if not a line feed, then return it */ return; case EOF: /* end of file -- forget it */ return; default: /* scan up to three octal digits to get value */ if (isOCTAL_DIGIT(ch)) { value = digit_value[ch]; ch = next_ch(); if (isOCTAL_DIGIT(ch)) { value = (value << 3) + digit_value[ch]; ch = next_ch(); if (isOCTAL_DIGIT(ch)) value = (value << 3) + digit_value[ch]; else back_ch(ch); } else back_ch(ch); ch = value; } } /* Found a character to save */ save_ch(ch);} /* Done: String */static int STRING(ch) int ch;{ int nest_level = 1; tokenType = TOKEN_STRING; do { ch = next_ch(); while(!isSTRING_SPECIAL(ch)) { save_ch(ch); ch = next_ch(); }; switch (ch) { case '(': ++nest_level; save_ch(ch); break; case ')': if (--nest_level > 0) save_ch(ch); break; case '\\': save_digraph(next_ch()); break; case '\r': /* All carriage returns (\r) are turned into linefeeds (\n)*/ ch = next_ch(); /* get the next one, is it \n? */ if (ch != '\n') { /* if not, then put it back. */ back_ch(ch); } save_ch('\n'); /* in either case, save a linefeed */ break; case EOF: tokenType = TOKEN_INVALID; /* Unterminated string */ nest_level = 0; break; } } while(nest_level > 0); return(DONE);} /* ------------------------------------------------------------------- * Assemble a name; set token type and done flag. * Put current input character back, if it is not white space. */ /* Done: Name * (Safe version used to complete name tokens that * start out looking like something else). */ static int AAH_NAME(ch) int ch;{ do { save_ch(ch); ch = next_ch(); } while(isNAME(ch)); back_ch_not_white(ch); tokenType = TOKEN_NAME; return(DONE);} /* Done: Name */static int NAME(ch) int ch;{ save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); while(isNAME(ch)) { save_ch(ch); ch = next_ch(); } } } } } } } back_ch_not_white(ch); tokenType = TOKEN_NAME; return(DONE);} /* Done: Literal Name */static int LITERAL_NAME(ch) int ch;{ if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); while(isNAME(ch)) { save_ch(ch); ch = next_ch(); } } } } } } } back_ch_not_white(ch); tokenType = TOKEN_LITERAL_NAME; return(DONE);} /* Done: immediate Name */static int IMMED_NAME(ch) int ch;{ ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); if (isNAME(ch)) { save_unsafe_ch(ch); ch = next_ch(); while(isNAME(ch)) { save_ch(ch); ch = next_ch(); } } } } } } } back_ch_not_white(ch); tokenType = TOKEN_IMMED_NAME; return(DONE);} /* Done: Name found while looking for something else */static int OOPS_NAME(ch) int ch;{ back_ch_not_white(ch); tokenType = TOKEN_NAME; return(DONE);} /* ------------------------------------------------------------------- * Complete a miscellaneous token; set token type and done flag. */ /* Done: Unmatched Right Angle-Bracket */static int RIGHT_ANGLE(ch) int ch;{ tokenType = TOKEN_RIGHT_ANGLE; return(DONE);} /* Done: Unmatched Right Parenthesis */static int RIGHT_PAREN(ch) int ch;{ tokenType = TOKEN_RIGHT_PAREN; return(DONE);} /* Done: Left Brace */static int LEFT_BRACE(ch) int ch;{ tokenType = TOKEN_LEFT_BRACE; return(DONE);} /* Done: Right Brace */static int RIGHT_BRACE(ch) int ch;{ tokenType = TOKEN_RIGHT_BRACE; return(DONE);} /* Done: Left Bracket */static int LEFT_BRACKET(ch) int ch;{ save_unsafe_ch(ch); tokenType = TOKEN_LEFT_BRACKET; return(DONE);} /* Done: Right Bracket */static int RIGHT_BRACKET(ch) int ch;{ save_unsafe_ch(ch); tokenType = TOKEN_RIGHT_BRACKET; return(DONE);} /* Done: Break */static int BREAK_SIGNAL(ch) int ch;{ tokenType = TOKEN_BREAK; return(DONE);} /* Done: No Token Found */static int NO_TOKEN(ch) int ch;{ tokenType = TOKEN_EOF; return(DONE);} /* * ------------------------------------------------------------------- * scan_token -- scan one token from the input. It uses a simple * finite state machine to recognize token classes. * * The input is from a file. * * On entry -- * * inputP -> input PostScript object, a file. * tokenStartP -> buffer in VM for accumulating the token. * tokenMaxP -> last character in the token buffer * * On exit -- * * tokenLength = number of characters in the token * tokenTooLong = TRUE if the token did not fit in the buffer * tokenType = code for the type of token parsed. * tokenValue = converted value of a numeric token. * * * ------------------------------------------------------------------- */void scan_token(inputP) psobj *inputP;{ int ch; unsigned char *stateP = s0; unsigned char entry; int (*actionP)(); /* Define input source */ inputFileP = inputP->data.fileP; if (inputFileP == NULL) { tokenType = TOKEN_EOF; return; } /* Ensure enough space for most cases * (so we don't have to keep checking) * The length needs to cover the maximum number * of save_unsafe_ch() calls that might be executed. * That number is 11 (a sign and 10 decimal digits, e.g., * when scanning -2147483648), but use MAX_NAME_LEN * in case someone changes that without checking. */ if (vm_free_bytes() < (MAX_NAME_LEN)) { if (!(vm_init())) { tokenLength = 0; tokenTooLong = TRUE; tokenType = TOKEN_NONE; tokenValue.integer = 0; return; } } tokenStartP = vm_next_byte(); /* Reset token */ tokenCharP = tokenStartP; tokenTooLong = FALSE; /* Scan one token */ ch = next_ch(); do { entry = stateP[ch]; stateP = classActionTable[entry].nextStateP; actionP = classActionTable[entry].actionRoutineP; ch = (*actionP)(ch); } while(ch != DONE); /* Return results */ tokenLength = tokenCharP - tokenStartP;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -