📄 getsym.c
字号:
/*
* skip_space() - this routine skips whitespace characters.
*/
static void skip_space P0 (void)
{
for (;;) {
while (is_space (*bufcur)) {
if (*bufcur == (CHAR) '\n') {
new_line ();
} else {
bufcur++;
}
}
if (bufcur < buflimit) {
break;
}
if (end_of_file) {
break;
}
symstart = bufcur;
nextline ();
}
}
/*
* Process a pragma string
*/
static void pragma_options P1 (const CHAR *, str)
{
options (str, TRUE);
}
/*
* Handle the new C99 _Pragma operator
*/
static void process_pragma_operator P0 (void)
{
needpunc (kw_pragma);
needpunc (tk_openpa);
if (lastst == tk_sconst) {
pragma_options (lastsym);
needpunc (tk_sconst);
}
needpunc (tk_closepa);
}
/*
* preprocessor_directive() - handling of pre-processor directives.
*
* The line starts with #, so it is assumed to be a pre-processor
* directive.
*
* #<num>
* #line <num>
* #line <num> <filename>
* is treated as a line number re-synchronisation directive
* and analysed further. For compatibility with the DECUS
* pre-processor, # which is followed by a number is treated as
* equivalent to the #line directive.
*
* This directive is expected to be followed by the line number. A
* filename can also optionally be present (if omitted it is assumed
* that the filename has not changed since the last #line directive).
*
* #file
* the line is ignored
*
* #ident
* the line is ignored
*
* #pragma
* an appropriate message output and the line is ignored.
*
* Any other directive is treated as an error, an appropriate error
* message is output and the line ignored.
*/
static void preprocessor_directive P0 (void)
{
unsigned i;
SIZE len;
const CHAR *ptr;
symstart = bufcur;
nextch (); /* consume # */
skip_space ();
switch (*bufcur) {
default:
symstart = bufcur;
while (is_idch (*bufcur)) {
nextch ();
}
len = (SIZE) (bufcur - symstart);
ptr = found (symstart, len, FALSE);
if (ptr == pp_pragma) {
/*
* #pragma
*/
while ((*bufcur == (CHAR) ' ') || (*bufcur == (CHAR) '\t')) {
nextch (); /* remove leading white space */
}
symstart = bufcur;
while (*bufcur) {
if (*bufcur == (CHAR) '\n') {
*bufcur = (CHAR) '\0';
pragma_options (symstart);
*bufcur = (CHAR) '\n';
break;
}
nextch ();
}
return;
}
if (ptr == pp_ident) {
/*
* #ident
*/
while (*bufcur) {
if (*bufcur == (CHAR) '\n') {
break;
}
nextch ();
}
return;
}
if (ptr == pp_file) {
/*
* #file
*/
while (*bufcur) {
if (*bufcur == (CHAR) '\n') {
break;
}
nextch ();
}
return;
}
#ifndef SYNTAX_CORRECT
if (ptr != pp_line) {
message (ERR_PREPROC);
return;
}
#endif /* SYNTAX_CORRECT */
/*
* #line line-number [filename]
*/
skip_space ();
#ifndef SYNTAX_CORRECT
if (!is_digit (*bufcur)) {
message (ERR_PREPROC);
return;
}
#endif /* SYNTAX_CORRECT */
/*lint -fallthrough */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/*
* #line-number [ filename]
*/
for (i = 0, act_line = (LINE) 0; is_digit (*bufcur); nextch ()) {
i = radix36 (*bufcur);
act_line = ((LINE) 10 * act_line) + (LINE) i;
}
/*
* scan file name
*
* If present it is assumed to be surrounded by double quotes.
* As a safety measure, end-of-line will also terminate the filename.
*
* DECUS cpp suppresses the name if it has not changed
* in this case, and then we keep the old name
*/
while (*bufcur == (CHAR) ' ')
nextch ();
switch (*bufcur) {
case '"':
nextch (); /* step over the initial quote */
/*lint -fallthrough */
default:
for (symstart = bufcur; *bufcur; nextch ()) {
if (*bufcur == (CHAR) '"' || *bufcur == (CHAR) '\n') {
break;
}
}
len = (SIZE) (bufcur - symstart);
/*
* Allocate the name into the spelling table.
*/
act_file = found (symstart, len, FALSE);
/*
* Ignore the rest of the line
*/
while (*bufcur != (CHAR) '\n' && *bufcur != END_OF_BUFFER)
nextch ();
break;
case '\n':
break;
}
act_line--;
return;
}
}
/*
* nextch() - basic get character routine.
*/
static void nextch P0 (void)
{
bufcur++;
if (*bufcur == END_OF_BUFFER) {
nextline ();
}
}
/*
* getid() - get an identifier.
*
* Identifiers are any is_idch conglomerate that doesn't start
* with a numeric character. This set INCLUDES keywords.
*/
static void getid P0 (void)
{
register SIZE len;
if ((lang_option >= LANG_C90) && *bufcur == (CHAR) 'L') {
/* Grrr!! ANSI - wide character constants start with 'L' */
nextch ();
switch (*bufcur) {
case '\'':
nextch ();
symstart = bufcur;
ival = (UVAL) (int) getsch (FALSE); /* get a string char */
if (*bufcur == (CHAR) '\'') {
nextch ();
#ifndef SYNTAX_CORRECT
} else {
message (ERR_CHARCONST);
#endif /* SYNTAX_CORRECT */
}
lastst = tk_wconst;
return;
case '\"':
len = (SIZE) 0;
do {
nextch ();
for (;; ++len) {
int j;
if ((j = getsch (TRUE)) == END_STRING) {
break;
}
symstart[len] = (CHAR) j;
}
if (*bufcur == (CHAR) '\"') {
nextch ();
#ifndef SYNTAX_CORRECT
} else {
message (ERR_STRINGCONST);
#endif /* SYNTAX_CORRECT */
}
skip_space ();
} while (*bufcur == (CHAR) '\"');
/*
* By looking up the string in the spelling table we ensure
* that the same strings will return the same pointer ... thus
* removing the necessity for comparing strings elsewhere in
* the compiler.
*/
lastsym = found (symstart, len, FALSE);
lastsymlen = len;
lastst = tk_wsconst;
return;
default:
break;
}
}
for (;;) {
while (is_idch (*bufcur)) {
bufcur++;
}
if (bufcur < buflimit) {
break;
}
/*
* The input buffer ran out ... get more input!
*/
nextline ();
}
len = (SIZE) (bufcur - symstart);
lastsym = found (symstart, len, TRUE);
}
/*
* getsch() - get a character in a quoted string.
*
* This routine handles all of the escape mechanisms for characters
* in strings and character constants.
* is_string is FALSE, if a character constant is being scanned,
* is_string is TRUE, if a string constant is being scanned
*/
static int getsch P1 (BOOL, is_string)
{
register int i;
unsigned j;
/*
* if we scan a string constant, stop if '"' is seen
*/
switch (*bufcur) {
case '\n':
return END_STRING;
case '"':
if (is_string) {
return END_STRING;
}
/*lint -fallthrough */
case '\0':
if (bufcur >= buflimit) {
/*
* The input buffer ran out ... get more input!
*/
nextline ();
return getsch (is_string);
}
/*lint -fallthrough */
default:
i = (int) ((*bufcur) & 0377);
nextch ();
/* signed characters lie in the range -128..127 */
if (!uchar_option && (i >= 128)) {
i -= 256;
}
return i;
case '\\':
nextch (); /* get an escaped character */
switch (*bufcur) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
i = 0;
for (j = 0; (j < 3) && is_octal (*bufcur); ++j) {
i = 8 * i + (int) radix36 (*bufcur);
nextch ();
}
/*
* constraint: The value of an octal escape sequence shall be
* in the range of representable values for the type
* unsigned char for an integer character constant, or
* an the unsigned type corresponding to wchar_t for a
* wide character constant.
*/
#ifndef SYNTAX_CORRECT
if (i > 256) {
message (ERR_ESCRANGE);
}
#endif /* SYNTAX_CORRECT */
i &= 0377;
/* signed characters lie in the range -128..127 */
if (!uchar_option && (i >= 128)) {
i -= 256;
}
return i;
case 'x':
nextch ();
/* get hexadecimal character */
i = 0;
for (j = 0; is_hex (*bufcur); j++) {
i = 16 * i + (int) radix36 (*bufcur);
nextch ();
}
#ifndef SYNTAX_CORRECT
if (j == 0) {
message (WARN_NOHEX);
}
#endif /* SYNTAX_CORRECT */
/*
* constraint: The value of a hexadecimal escape sequence shall be
* in the range of representable values for the type
* unsigned char for an integer character constant, or
* an the unsigned type corresponding to wchar_t for a
* wide character constant.
*/
#ifndef SYNTAX_CORRECT
if (i > 256) {
message (ERR_ESCRANGE);
}
#endif /* SYNTAX_CORRECT */
i &= 0377;
/* signed characters lie in the range -128..127 */
if (!uchar_option && (i >= 128)) {
i -= 256;
}
return i;
default:
i = (int) *bufcur;
nextch ();
switch (i) {
case '\n':
return getsch (1);
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
#if 0
case 'a':
return '\a';
case 'v':
return '\v';
#else
case 'a':
return '\007';
case 'v':
return '\013';
#endif
default:
if (lang_option >= LANG_C99) {
switch (i) {
case '?':
return i;
default:
#ifndef SYNTAX_CORRECT
message (WARN_ESCAPECH, i);
#endif /* SYNTAX_CORRECT */
break;
}
}
/*lint -fallthrough */
case '\\':
case '\'':
case '\"':
return i;
}
}
}
}
/*
* radix36() - return the numeric value for a character
*
* This function makes assumptions about the character codes.
*/
static unsigned radix36 P1 (CHAR, c)
{
if (c >= (CHAR) '0' && c <= (CHAR) '9') {
return ((int) c) - '0';
}
if (c >= (CHAR) 'a' && c <= (CHAR) 'z') {
return ((int) c - 'a') + 10;
}
if (c >= (CHAR) 'A' && c <= (CHAR) 'Z') {
return ((int) c - 'A') + 10;
}
return 0;
}
/*
* test_int() - Test on long or unsigned constants.
*
* The type of integer constants depends on its value, representation
* and suffixes:
*
* unsuffixed decimals are of type int, long int, unsigned long int
* unsuffixed octals or hexadecimals are int, unsigned int, long int
* or unsigned long int
*
* constants with suffix U are unsigned int or unsigned long int
* constants with suffix L are long int or unsigned long int
* constants with suffixes L and U are unsigned long int
* (X3.159-1989 3.1.3.2)
*
* The variable rep is a bitmask describing the representation of
* the constant.
*/
#define H 1U /* hex or octal (this is passed in from caller) */
#define U 2U /* U suffix */
#define L 4U /* L suffix */
#define LL 8U /* LL suffix */
#define S 16U /* ints are short */
static void test_int P1 (unsigned, rep)
{
static struct
{
UVAL minval;
unsigned repmask;
TOKEN type;
const char *msg;
} typetab[] =
{
#ifdef LONGLONG
{ /* U and LL */
0x0UL, U | L | LL, tk_ullconst, (const char *) NULL}
#ifdef LONGLONG_BOOTSTRAP
, { /* L >63 bits */
0x0UL, L, tk_llconst, "unsigned long long"}
, { /* LL >63 bits */
0x0UL, L | LL, tk_llconst, "unsigned long long"}
, { /* U >32 bits */
0x0UL, U, tk_llconst, "unsigned long long"}
, { /* >63 bits */
0x0UL, 0, tk_llconst, "unsigned long long"}
#else
, { /* L >63 bits */
0x8000000000000000UL, L, tk_llconst, "unsigned long long"}
, { /* LL >63 bits */
0x8000000000000000UL, L | LL, tk_llconst, "unsigned long long"}
, { /* U >32 bits */
0x100000000UL, U, tk_llconst, "unsigned long long"}
, { /* >63 bits */
0x8000000000000000UL, 0, tk_llconst, "unsigned long long"}
#endif /* LONGLONG_BOOTSTRAP */
, { /* LL */
0x0UL, L | LL, tk_llconst, (const char *) NULL}
, { /* L >31 bits */
Ox80000000UL, U | L, tk_ulconst, (const char *) NULL}
, { /* L >31 bits */
Ox80000000UL, L, tk_llconst, "long long"}
, { /* >31 bits */
Ox80000000UL, 0, tk_llconst, "long long"}
,
#endif /* LONGLONG */
{ /* U and L */
Ox0UL, U | L, tk_ulconst, (const char *) NULL}
, { /* >31 bits, short int */
Ox80000000UL, S, tk_ulconst, "unsigned long"}
, { /* U */
Ox0UL, U, tk_uconst, (const char *) NULL}
, { /* LU >31 bits */
Ox80000000UL, L, tk_ulconst, "unsigned long"}
, { /* >31 bits */
Ox80000000UL, 0, tk_uconst, "unsigned"}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -