⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getsym.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *	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 + -