📄 getsym.c
字号:
, { /* U and >16 bits, short int */
Ox00010000UL, S | U, tk_ulconst, "unsigned long"}
, { /* L */
Ox0UL, L, tk_lconst, (const char *) NULL}
, { /* >16 bits, short int */
Ox00010000UL, S, tk_lconst, "long"}
, { /* U */
Ox0UL, S | U, tk_uconst, (const char *) NULL}
, { /* >15 bits, hex/octal, short int */
Ox8000UL, S | H, tk_uconst, "unsigned"}
, { /* >15 bits, short int */
Ox8000UL, S, tk_lconst, "long"}
, { /* int */
Ox0UL, H, tk_iconst, (const char *) NULL}
, { /* int */
Ox0UL, 0, tk_iconst, (const char *) NULL}
}
, *typeptr;
assert (rep <= 1);
#ifdef LONGLONG
#ifdef LONGLONG_BOOTSTRAP
{
static int init_done = 0;
if (0 == init_done) {
UVAL uval;
uval = (UVAL) 1;
typetab[1].minval = uval << 63;
uval = (UVAL) 1;
typetab[2].minval = uval << 63;
uval = (UVAL) 1;
typetab[3].minval = uval << 32;
uval = (UVAL) 1;
typetab[4].minval = uval << 63;
init_done = 1;
}
}
#endif /* LONGLONG_BOOTSTRAP */
#endif /* LONGLONG */
#ifndef SYNTAX_CORRECT
if (overflow) {
message (ERR_REPRESENT, "");
}
#endif /* SYNTAX_CORRECT */
if (tp_int->size == tp_short->size) {
rep |= S;
}
/*
* first check suffixes.
* L, U, LL, and combinations are allowed.
*/
for (;;) {
if (*bufcur == (CHAR) 'l' || *bufcur == (CHAR) 'L') {
if (rep & L) {
if ((lang_option >= LANG_C99) && (rep & LL)) {
break;
}
rep |= LL;
}
rep |= L;
} else if (*bufcur == (CHAR) 'u' || *bufcur == (CHAR) 'U') {
if (rep & U) {
break;
}
rep |= U;
} else {
break;
}
nextch ();
}
/*
* now search table for first match
*/
#ifdef LONGLONG
if (is_debugging (DEBUG_LONGLONG)) {
VOIDCAST fprintf (stderr, "test_int: ival = %s\n",
longlongStr (ival));
}
#endif /* LONGLONG */
for (typeptr = typetab;; typeptr++) {
if ((rep & typeptr->repmask) != typeptr->repmask) {
continue;
}
#ifndef SYNTAX_CORRECT
#ifdef LONGLONG
if (is_debugging (DEBUG_LONGLONG)) {
VOIDCAST fprintf (stderr, "test_int: min = %s\n",
longlongStr (typeptr->minval));
}
#endif /* LONGLONG */
if (ival > typeptr->minval) {
if (typeptr->msg) {
message (WARN_CONSTANT, typeptr->msg);
}
break;
}
#endif /* SYNTAX_CORRECT */
if (ival == typeptr->minval) {
break;
}
}
#ifdef LONGLONG
if (is_debugging (DEBUG_LONGLONG)) {
VOIDCAST fprintf (stderr, "test_int: type = %d\n", typeptr->type);
VOIDCAST fprintf (stderr, "test_int: mask = 0x%x\n",
typeptr->repmask);
VOIDCAST fprintf (stderr, "test_int: min = %s\n",
longlongStr (typeptr->minval));
}
#endif /* LONGLONG */
lastst = typeptr->type;
}
/*
* test_int() - Test on float and double constants.
*/
static void test_real P0 (void)
{
switch (*bufcur) {
case 'f':
case 'F':
lastst = tk_fconst;
nextch ();
break;
case 'l':
case 'L':
lastst = tk_lrconst;
nextch ();
break;
default:
break;
}
}
/*
* getdecimal() - get integers
*
* rval is computed simultaneously - this handles floating point
* constants whose integer part is greater than INT_MAX correctly,
* e. g. 10000000000000000000000.0
*/
static void getdecimal P0 (void)
{
register UVAL i = (UVAL) 0;
register unsigned j;
UVAL old = (UVAL) 0;
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
register RVAL r = F_zero;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
while (is_digit (*bufcur)) {
j = radix36 (*bufcur);
i = ((UVAL) 10 * i) + (UVAL) j;
if (old > i) {
/* must have wrapped the constant ... too big */
overflow = TRUE;
}
old = i;
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
r = F_ten * r + (RVAL) j;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
nextch ();
}
ival = i;
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
rval = r;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
}
/*
* getoctal() - get an octal number
*/
static void getoctal P0 (void)
{
register UVAL i = (UVAL) 0;
register unsigned j;
UVAL old = (UVAL) 0;
while (is_octal (*bufcur)) {
j = radix36 (*bufcur);
i = ((UVAL) 8 * i) + (UVAL) j;
if (old > i) {
/* must have wrapped the constant ... too big */
overflow = TRUE;
}
old = i;
nextch ();
}
ival = i;
}
/*
* gethex() - get a hexadecimal number.
*/
static void gethex P0 (void)
{
register UVAL i = (UVAL) 0;
register unsigned j;
UVAL old = (UVAL) 0;
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
register RVAL r = F_zero;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
#ifndef SYNTAX_CORRECT
if (!is_hex (*bufcur)) {
static CHAR temp[] = { " " };
temp[0] = *bufcur;
message (ERR_PUNCT, temp);
}
#endif /* SYNTAX_CORRECT */
while (is_hex (*bufcur)) {
j = radix36 (*bufcur);
i = ((UVAL) 16 * i) + (UVAL) j;
if (old > i) {
/* must have wrapped the constant ... too big */
overflow = TRUE;
}
old = i;
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
r = F_sixteen * r + (RVAL) j;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
nextch ();
}
ival = i;
}
/*
* getfrac() - get fraction part of a floating number.
*
* Since 0.1 has no exact representation in a binary base,
* we divide by 10.0 instead of multiplying by 0.1
* (Thanks to Michael Mueller for this comment)
* Improved algorithym by doing a single division at the end
* - supplied by Tom Watson.
*/
static void getfrac P0 (void)
{
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
RVAL frmul;
RVAL fraction;
frmul = F_one;
fraction = F_zero;
while (is_digit (*bufcur)) {
frmul *= F_ten;
fraction *= F_ten;
fraction += (RVAL) radix36 (*bufcur);
nextch ();
}
rval += fraction / frmul;
lastst = tk_rconst;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
}
static void gethexfrac P0 (void)
{
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
RVAL frmul;
RVAL fraction;
frmul = F_one;
fraction = F_zero;
while (is_hex (*bufcur)) {
frmul *= F_sixteen;
fraction *= F_sixteen;
fraction += (RVAL) radix36 (*bufcur);
nextch ();
}
rval += fraction / frmul;
lastst = tk_rconst;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
}
/*
* getexp() - get exponent part of floating number.
*
* This algorithm is primitive but useful.
* We have to limit the exponent range somehow since 'endless'
* loops can occur if 1E123456789 is to be converted.
* The biggest exponent range I am aware of (CRAY Y-MP) is
* 2^4096, say 10^1200, so I limit the exponent range to 1500.
* Is it better to flag an error or to generate +/- inf or
* zero here?
*
* The reason we divide by exmul, and not multiply by 1/exmul is that
* 0.1 can NOT be represented as an exact quantity in a binary base.
* Thus, when you increase sizeof(double), you get into trouble.
*/
static void getexp P0 (void)
{
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
RVAL expo;
RVAL multiplier;
int flag = FALSE;
expo = rval;
multiplier = F_ten;
switch (*bufcur) {
case '-':
flag = TRUE;
/*lint -fallthrough */
case '+':
nextch ();
break;
default:
break;
}
#ifndef SYNTAX_CORRECT
if (!is_digit (*bufcur)) {
static CHAR temp[] = " ";
temp[0] = *bufcur;
message (ERR_PUNCT, temp);
}
#endif /* SYNTAX_CORRECT */
getdecimal ();
if (ival < (IVAL) TARGET_LDBL_MAX_EXP) {
while (ival-- != (UVAL) 0) {
if (flag) {
expo /= multiplier;
} else {
expo *= multiplier;
}
}
#ifndef SYNTAX_CORRECT
} else {
message (ERR_CONSTFLOAT);
#endif /* SYNTAX_CORRECT */
}
rval = expo;
lastst = tk_rconst;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
}
static void gethexexp P0 (void)
{
#ifdef FLOAT_SUPPORT
#ifndef FLOAT_BOOTSTRAP
RVAL expo;
RVAL multiplier;
int flag = FALSE;
expo = rval;
multiplier = F_two;
switch (*bufcur) {
case '-':
flag = TRUE;
/*lint -fallthrough */
case '+':
nextch ();
break;
default:
break;
}
#ifndef SYNTAX_CORRECT
if (!is_hex (*bufcur)) {
static CHAR temp[] = " ";
temp[0] = *bufcur;
message (ERR_PUNCT, temp);
}
#endif /* SYNTAX_CORRECT */
gethex ();
if (ival < (UVAL) 1500) {
while (ival-- != (UVAL) 0) {
if (flag) {
expo /= multiplier;
} else {
expo *= multiplier;
}
}
#ifndef SYNTAX_CORRECT
} else {
message (ERR_CONSTFLOAT);
#endif /* SYNTAX_CORRECT */
}
rval = expo;
lastst = tk_rconst;
#endif /* FLOAT_BOOTSTRAP */
#endif /* FLOAT_SUPPORT */
}
/*
* getnum() - get a number from input.
*
* getnum handles all of the numeric input. it accepts decimal, octal,
* hexidecimal, and floating point numbers.
*/
static void getnum P0 (void)
{
overflow = FALSE;
lastst = tk_iconst;
switch (*bufcur) {
case '0':
nextch ();
switch (*bufcur) {
case 'x':
case 'X':
nextch ();
switch (*bufcur) {
case '.':
if (lang_option >= LANG_C99) {
break;
}
/*lint -fallthrough */
default:
gethex ();
break;
}
if (lang_option >= LANG_C99) {
switch (*bufcur) {
case '.':
/* rval already set */
nextch ();
gethexfrac (); /* add the fractional part */
/*lint -fallthrough*/ case 'p':
case 'P':
switch (*bufcur) {
case 'p':
case 'P':
nextch ();
gethexexp (); /* get the exponent */
test_real ();
break;
default:
#ifndef SYNTAX_CORRECT
message (ERR_BINARYEXP);
#endif /* SYNTAX_CORRECT */
break;
}
break;
default:
test_int (H);
break;
}
} else {
test_int (H);
}
return;
default:
getoctal ();
test_int (H);
return;
case '.':
case 'e':
case 'E':
break;
}
/*lint -fallthrough */
default:
getdecimal ();
switch (*bufcur) {
case '.':
/* rval already set */
nextch ();
getfrac (); /* add the fractional part */
/*lint -fallthrough */
default:
switch (*bufcur) {
case 'e':
case 'E':
nextch ();
getexp (); /* get the exponent */
break;
default:
break;
}
if (lastst == tk_rconst) {
test_real ();
} else {
/*
* look for l and u qualifiers
*/
test_int (0U);
}
break;
}
}
}
/*
* getsym() - get next symbol from input stream.
*
* getsym is the basic lexical analyser.
* It builds basic tokens out of the characters on the input stream
* and sets the following global variables:
*
* lastst: type of last symbol read.
* lastsym: last identifier/string read.
* ival: last integer constant read.
* rval: last real constant read.
*
* getsym should be called for all your input needs...
*/
void getsym P0 (void)
{
register SIZE i;
for (;;) {
restart:
symstart = bufcur;
switch (*bufcur) {
case '\n':
new_line ();
continue;
case '\f':
case '\r':
case '\t':
case '\v':
case ' ':
bufcur++;
continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
getnum ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -