lcc源代码解析之lex.c
来源:互联网 发布:2016年双十一销售数据 编辑:程序博客网 时间:2024/06/05 13:31
有了前面的铺垫,终于可以上正餐了,本节解析编译器的一个重要组件:词法分析器,即lcc的lex.c文件。
lcc出于对效率的考虑,并没有使用类似nfa思想的自动词法解析生成工具来生成,而是采用了手写的lex。
具体代码如下:
#include "c.h"#include <float.h>#include <errno.h>static char rcsid[] = "$Id: lex.c,v 1.1 2002/08/28 23:12:44 drh Exp $";#define MAXTOKEN 32/*字符的6大类别,空格/换行/字母/数字/16进制/其他*/enum { BLANK=01, NEWLINE=02, LETTER=04, DIGIT=010, HEX=020, OTHER=040 };/*字符掩码,将字符归为六类中的一类或多类,如abcdef可以作为字母存在,也是作为16进制字符存在*/static unsigned char map[256] = { /* 000 nul */0, /* 001 soh */0, /* 002 stx */0, /* 003 etx */0, /* 004 eot */0, /* 005 enq */0, /* 006 ack */0, /* 007 bel */0, /* 010 bs */0, /* 011 ht */BLANK, /* 012 nl */NEWLINE, /* 013 vt */BLANK, /* 014 ff */BLANK, /* 015 cr */0, /* 016 so */0, /* 017 si */0, /* 020 dle */0, /* 021 dc1 */0, /* 022 dc2 */0, /* 023 dc3 */0, /* 024 dc4 */0, /* 025 nak */0, /* 026 syn */0, /* 027 etb */0, /* 030 can */0, /* 031 em */0, /* 032 sub */0, /* 033 esc */0, /* 034 fs */0, /* 035 gs */0, /* 036 rs */0, /* 037 us */0, /* 040 sp */BLANK, /* 041 ! */OTHER, /* 042 " */OTHER, /* 043 # */OTHER, /* 044 $ */0, /* 045 % */OTHER, /* 046 & */OTHER, /* 047 ' */OTHER, /* 050 ( */OTHER, /* 051 ) */OTHER, /* 052 * */OTHER, /* 053 + */OTHER, /* 054 , */OTHER, /* 055 - */OTHER, /* 056 . */OTHER, /* 057 / */OTHER, /* 060 0 */DIGIT, /* 061 1 */DIGIT, /* 062 2 */DIGIT, /* 063 3 */DIGIT, /* 064 4 */DIGIT, /* 065 5 */DIGIT, /* 066 6 */DIGIT, /* 067 7 */DIGIT, /* 070 8 */DIGIT, /* 071 9 */DIGIT, /* 072 : */OTHER, /* 073 ; */OTHER, /* 074 < */OTHER, /* 075 = */OTHER, /* 076 > */OTHER, /* 077 ? */OTHER, /* 100 @ */0, /* 101 A */LETTER|HEX, /* 102 B */LETTER|HEX, /* 103 C */LETTER|HEX, /* 104 D */LETTER|HEX, /* 105 E */LETTER|HEX, /* 106 F */LETTER|HEX, /* 107 G */LETTER, /* 110 H */LETTER, /* 111 I */LETTER, /* 112 J */LETTER, /* 113 K */LETTER, /* 114 L */LETTER, /* 115 M */LETTER, /* 116 N */LETTER, /* 117 O */LETTER, /* 120 P */LETTER, /* 121 Q */LETTER, /* 122 R */LETTER, /* 123 S */LETTER, /* 124 T */LETTER, /* 125 U */LETTER, /* 126 V */LETTER, /* 127 W */LETTER, /* 130 X */LETTER, /* 131 Y */LETTER, /* 132 Z */LETTER, /* 133 [ */OTHER, /* 134 \ */OTHER, /* 135 ] */OTHER, /* 136 ^ */OTHER, /* 137 _ */LETTER, /* 140 ` */0, /* 141 a */LETTER|HEX, /* 142 b */LETTER|HEX, /* 143 c */LETTER|HEX, /* 144 d */LETTER|HEX, /* 145 e */LETTER|HEX, /* 146 f */LETTER|HEX, /* 147 g */LETTER, /* 150 h */LETTER, /* 151 i */LETTER, /* 152 j */LETTER, /* 153 k */LETTER, /* 154 l */LETTER, /* 155 m */LETTER, /* 156 n */LETTER, /* 157 o */LETTER, /* 160 p */LETTER, /* 161 q */LETTER, /* 162 r */LETTER, /* 163 s */LETTER, /* 164 t */LETTER, /* 165 u */LETTER, /* 166 v */LETTER, /* 167 w */LETTER, /* 170 x */LETTER, /* 171 y */LETTER, /* 172 z */LETTER, /* 173 { */OTHER, /* 174 | */OTHER, /* 175 } */OTHER, /* 176 ~ */OTHER, };static struct symbol tval;static char cbuf[BUFSIZE+1];static unsigned int wcbuf[BUFSIZE+1];Coordinate src;/* current source coordinate */int t;char *token;/* current token */Symbol tsym;/* symbol table entry for current token */static void *cput(int c, void *cl);static void *wcput(int c, void *cl);static void *scon(int q, void *put(int c, void *cl), void *cl);static int backslash(int q);static Symbol fcon(void);static Symbol icon(unsigned long, int, int);static void ppnumber(char *);//这个文件主要作为一个词法分析器的功能存在。/**@brief:获取词素,返回给语法分析器,*通过词素的第一个字符将词素归类,并通过后面的字符形成完整的词素*/int gettok(void) {//没有条件for循环,就是想识别出一个记号才返回for (;;) {//获取当前输入缓冲区的指针register unsigned char *rcp = cp;//去掉空白字符while (map[*rcp]&BLANK)rcp++;//判断输入缓冲区剩余的字符小于最大的记号时,就重新从文件里获取源程序,填充到缓冲区里。if (limit - rcp < MAXTOKEN) {cp = rcp;fillbuf();//重新读取rcp = cp;}//记录前记号的开始位置,以便出错时可以定位出错的源程序位置src.file = file;src.x = (char *)rcp - line;//列数src.y = lineno;//处理识别一个字符的移动指针,让它指向下一个字符cp = rcp + 1;//根据第一个字符来进行识别处理,它是使用一个switch来实的switch (*rcp++) {//识别C程序的注释,并把这些注释删除case '/': if (*rcp == '*') { int c = 0; for (rcp++; *rcp != '/' || c != '*'; ) if (map[*rcp]&NEWLINE) { if (rcp < limit) c = *rcp; cp = rcp + 1; nextline(); rcp = cp; if (rcp == limit) break; } else c = *rcp++; if (rcp < limit) rcp++; else error("unclosed comment\n"); cp = rcp; continue; } return '/'; case '<':if (*rcp == '=') return cp++, LEQ;if (*rcp == '<') return cp++, LSHIFT;return '<';case '>':if (*rcp == '=') return cp++, GEQ;if (*rcp == '>') return cp++, RSHIFT;return '>';case '-':if (*rcp == '>') return cp++, DEREF;if (*rcp == '-') return cp++, DECR;return '-';case '=': return *rcp == '=' ? cp++, EQL : '=';case '!': return *rcp == '=' ? cp++, NEQ : '!';case '|': return *rcp == '|' ? cp++, OROR : '|';case '&': return *rcp == '&' ? cp++, ANDAND : '&';case '+': return *rcp == '+' ? cp++, INCR : '+';case ';': case ',': case ':':case '*': case '~': case '%': case '^': case '?':case '[': case ']': case '{': case '}': case '(': case ')': return rcp[-1];case '\n': case '\v': case '\r': case '\f':nextline();if (cp == limit) {tsym = NULL;return EOI;}continue;case 'i':if (rcp[0] == 'f'&& !(map[rcp[1]]&(DIGIT|LETTER))) {cp = rcp + 1;return IF;}if (rcp[0] == 'n'&& rcp[1] == 't'&& !(map[rcp[2]]&(DIGIT|LETTER))) {cp = rcp + 2;tsym = inttype->u.sym;return INT;}goto id;//去掉关键之if,int以外的其他以i开头的词素作为id处理case 'h': case 'j': case 'k': case 'm': case 'n': case 'o':case 'p': case 'q': case 'x': case 'y': case 'z':case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':case 'G': case 'H': case 'I': case 'J': case 'K':case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':case 'Y': case 'Z'://以上这些字母开头的不会产生关键字,所以直接作为id处理,其他如abede都有可能产生关键字,在下面的case里处理id://保证缓冲区有足够的字符if (limit - rcp < MAXLINE) {cp = rcp - 1;fillbuf();rcp = ++cp;}assert(cp == rcp);token = (char *)rcp - 1;while (map[*rcp]&(DIGIT|LETTER))rcp++;token = stringn(token, (char *)rcp - token);tsym = lookup(token, identifiers);//查找这个ID是否已经声明,如果没有声明返回是空指令给tsymcp = rcp;return ID;/*数字的识别*/case '0': case '1': case '2': case '3': case '4':case '5': case '6': case '7': case '8': case '9': {unsigned long n = 0;if (limit - rcp < MAXLINE) {cp = rcp - 1;fillbuf();rcp = ++cp;}assert(cp == rcp);token = (char *)rcp - 1;//16进制数的识别if (*token == '0' && (*rcp == 'x' || *rcp == 'X')) {int d, overflow = 0;while (*++rcp) {if (map[*rcp]&DIGIT)d = *rcp - '0';else if (*rcp >= 'a' && *rcp <= 'f')d = *rcp - 'a' + 10;else if (*rcp >= 'A' && *rcp <= 'F')d = *rcp - 'A' + 10;elsebreak;if (n&~(~0UL >> 4))overflow = 1;elsen = (n<<4) + d;}if ((char *)rcp - token <= 2)error("invalid hexadecimal constant `%S'\n", token, (char *)rcp-token);cp = rcp;tsym = icon(n, overflow, 16);}//8进制数的识别else if (*token == '0') {int err = 0, overflow = 0;for ( ; map[*rcp]&DIGIT; rcp++) {if (*rcp == '8' || *rcp == '9')err = 1;if (n&~(~0UL >> 3))overflow = 1;elsen = (n<<3) + (*rcp - '0');}if (*rcp == '.' || *rcp == 'e' || *rcp == 'E') {cp = rcp;tsym = fcon();return FCON;}cp = rcp;tsym = icon(n, overflow, 8);if (err)error("invalid octal constant `%S'\n", token, (char*)cp-token);}//10进制else {int overflow = 0;for (n = *token - '0'; map[*rcp]&DIGIT; ) {int d = *rcp++ - '0';if (n > (ULONG_MAX - d)/10)overflow = 1;elsen = 10*n + d;}if (*rcp == '.' || *rcp == 'e' || *rcp == 'E') {cp = rcp;tsym = fcon();return FCON;}cp = rcp;tsym = icon(n, overflow, 10);}return ICON;}case '.':if (rcp[0] == '.' && rcp[1] == '.') {cp += 2;return ELLIPSIS;}if ((map[*rcp]&DIGIT) == 0)return '.';if (limit - rcp < MAXLINE) {cp = rcp - 1;fillbuf();rcp = ++cp;}assert(cp == rcp);cp = rcp - 1;token = (char *)cp;tsym = fcon();return FCON;case 'L':if (*rcp == '\'') {unsigned int *s = scon(*cp, wcput, wcbuf);if (s - wcbuf > 2)warning("excess characters in wide-character literal ignored\n");tval.type = widechar;tval.u.c.v.u = wcbuf[0];tsym = &tval;return ICON;} else if (*rcp == '"') {unsigned int *s = scon(*cp, wcput, wcbuf);tval.type = array(widechar, s - wcbuf, 0);tval.u.c.v.p = wcbuf;tsym = &tval;return SCON;} elsegoto id;case '\'': {char *s = scon(*--cp, cput, cbuf);if (s - cbuf > 2)warning("excess characters in multibyte character literal ignored\n");tval.type = inttype;if (chartype->op == INT)tval.u.c.v.i = extend(cbuf[0], chartype);elsetval.u.c.v.i = cbuf[0]&0xFF;tsym = &tval;return ICON;}case '"': {char *s = scon(*--cp, cput, cbuf);tval.type = array(chartype, s - cbuf, 0);tval.u.c.v.p = cbuf;tsym = &tval;return SCON;}//以下为关键字的处理case 'a':if (rcp[0] == 'u'&& rcp[1] == 't'&& rcp[2] == 'o'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;return AUTO;}goto id;case 'b':if (rcp[0] == 'r'&& rcp[1] == 'e'&& rcp[2] == 'a'&& rcp[3] == 'k'&& !(map[rcp[4]]&(DIGIT|LETTER))) {cp = rcp + 4;return BREAK;}goto id;case 'c':if (rcp[0] == 'a'&& rcp[1] == 's'&& rcp[2] == 'e'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;return CASE;}if (rcp[0] == 'h'&& rcp[1] == 'a'&& rcp[2] == 'r'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;tsym = chartype->u.sym;return CHAR;}if (rcp[0] == 'o'&& rcp[1] == 'n'&& rcp[2] == 's'&& rcp[3] == 't'&& !(map[rcp[4]]&(DIGIT|LETTER))) {cp = rcp + 4;return CONST;}if (rcp[0] == 'o'&& rcp[1] == 'n'&& rcp[2] == 't'&& rcp[3] == 'i'&& rcp[4] == 'n'&& rcp[5] == 'u'&& rcp[6] == 'e'&& !(map[rcp[7]]&(DIGIT|LETTER))) {cp = rcp + 7;return CONTINUE;}goto id;case 'd':if (rcp[0] == 'e'&& rcp[1] == 'f'&& rcp[2] == 'a'&& rcp[3] == 'u'&& rcp[4] == 'l'&& rcp[5] == 't'&& !(map[rcp[6]]&(DIGIT|LETTER))) {cp = rcp + 6;return DEFAULT;}if (rcp[0] == 'o'&& rcp[1] == 'u'&& rcp[2] == 'b'&& rcp[3] == 'l'&& rcp[4] == 'e'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;tsym = doubletype->u.sym;return DOUBLE;}if (rcp[0] == 'o'&& !(map[rcp[1]]&(DIGIT|LETTER))) {cp = rcp + 1;return DO;}goto id;case 'e':if (rcp[0] == 'l'&& rcp[1] == 's'&& rcp[2] == 'e'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;return ELSE;}if (rcp[0] == 'n'&& rcp[1] == 'u'&& rcp[2] == 'm'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;return ENUM;}if (rcp[0] == 'x'&& rcp[1] == 't'&& rcp[2] == 'e'&& rcp[3] == 'r'&& rcp[4] == 'n'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return EXTERN;}goto id;case 'f':if (rcp[0] == 'l'&& rcp[1] == 'o'&& rcp[2] == 'a'&& rcp[3] == 't'&& !(map[rcp[4]]&(DIGIT|LETTER))) {cp = rcp + 4;tsym = floattype->u.sym;return FLOAT;}if (rcp[0] == 'o'&& rcp[1] == 'r'&& !(map[rcp[2]]&(DIGIT|LETTER))) {cp = rcp + 2;return FOR;}goto id;case 'g':if (rcp[0] == 'o'&& rcp[1] == 't'&& rcp[2] == 'o'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;return GOTO;}goto id;case 'l':if (rcp[0] == 'o'&& rcp[1] == 'n'&& rcp[2] == 'g'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;return LONG;}goto id;case 'r':if (rcp[0] == 'e'&& rcp[1] == 'g'&& rcp[2] == 'i'&& rcp[3] == 's'&& rcp[4] == 't'&& rcp[5] == 'e'&& rcp[6] == 'r'&& !(map[rcp[7]]&(DIGIT|LETTER))) {cp = rcp + 7;return REGISTER;}if (rcp[0] == 'e'&& rcp[1] == 't'&& rcp[2] == 'u'&& rcp[3] == 'r'&& rcp[4] == 'n'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return RETURN;}goto id;case 's':if (rcp[0] == 'h'&& rcp[1] == 'o'&& rcp[2] == 'r'&& rcp[3] == 't'&& !(map[rcp[4]]&(DIGIT|LETTER))) {cp = rcp + 4;return SHORT;}if (rcp[0] == 'i'&& rcp[1] == 'g'&& rcp[2] == 'n'&& rcp[3] == 'e'&& rcp[4] == 'd'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return SIGNED;}if (rcp[0] == 'i'&& rcp[1] == 'z'&& rcp[2] == 'e'&& rcp[3] == 'o'&& rcp[4] == 'f'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return SIZEOF;}if (rcp[0] == 't'&& rcp[1] == 'a'&& rcp[2] == 't'&& rcp[3] == 'i'&& rcp[4] == 'c'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return STATIC;}if (rcp[0] == 't'&& rcp[1] == 'r'&& rcp[2] == 'u'&& rcp[3] == 'c'&& rcp[4] == 't'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return STRUCT;}if (rcp[0] == 'w'&& rcp[1] == 'i'&& rcp[2] == 't'&& rcp[3] == 'c'&& rcp[4] == 'h'&& !(map[rcp[5]]&(DIGIT|LETTER))) {cp = rcp + 5;return SWITCH;}goto id;case 't':if (rcp[0] == 'y'&& rcp[1] == 'p'&& rcp[2] == 'e'&& rcp[3] == 'd'&& rcp[4] == 'e'&& rcp[5] == 'f'&& !(map[rcp[6]]&(DIGIT|LETTER))) {cp = rcp + 6;return TYPEDEF;}goto id;case 'u':if (rcp[0] == 'n'&& rcp[1] == 'i'&& rcp[2] == 'o'&& rcp[3] == 'n'&& !(map[rcp[4]]&(DIGIT|LETTER))) {cp = rcp + 4;return UNION;}if (rcp[0] == 'n'&& rcp[1] == 's'&& rcp[2] == 'i'&& rcp[3] == 'g'&& rcp[4] == 'n'&& rcp[5] == 'e'&& rcp[6] == 'd'&& !(map[rcp[7]]&(DIGIT|LETTER))) {cp = rcp + 7;return UNSIGNED;}goto id;case 'v':if (rcp[0] == 'o'&& rcp[1] == 'i'&& rcp[2] == 'd'&& !(map[rcp[3]]&(DIGIT|LETTER))) {cp = rcp + 3;tsym = voidtype->u.sym;return VOID;}if (rcp[0] == 'o'&& rcp[1] == 'l'&& rcp[2] == 'a'&& rcp[3] == 't'&& rcp[4] == 'i'&& rcp[5] == 'l'&& rcp[6] == 'e'&& !(map[rcp[7]]&(DIGIT|LETTER))) {cp = rcp + 7;return VOLATILE;}goto id;case 'w':if (rcp[0] == 'h'&& rcp[1] == 'i'&& rcp[2] == 'l'&& rcp[3] == 'e'&& !(map[rcp[4]]&(DIGIT|LETTER))) {cp = rcp + 4;return WHILE;}goto id;case '_':if (rcp[0] == '_'&& rcp[1] == 't'&& rcp[2] == 'y'&& rcp[3] == 'p'&& rcp[4] == 'e'&& rcp[5] == 'c'&& rcp[6] == 'o'&& rcp[7] == 'd'&& rcp[8] == 'e'&& !(map[rcp[9]]&(DIGIT|LETTER))) {cp = rcp + 9;return TYPECODE;}if (rcp[0] == '_'&& rcp[1] == 'f'&& rcp[2] == 'i'&& rcp[3] == 'r'&& rcp[4] == 's'&& rcp[5] == 't'&& rcp[6] == 'a'&& rcp[7] == 'r'&& rcp[8] == 'g'&& !(map[rcp[9]]&(DIGIT|LETTER))) {cp = rcp + 9;return FIRSTARG;}goto id;default:if ((map[cp[-1]]&BLANK) == 0)if (cp[-1] < ' ' || cp[-1] >= 0177)error("illegal character `\\0%o'\n", cp[-1]);elseerror("illegal character `%c'\n", cp[-1]);}}}//处理整形数据的后缀,如UuLl等static Symbol icon(unsigned long n, int overflow, int base) {if ((*cp=='u'||*cp=='U') && (cp[1]=='l'||cp[1]=='L')|| (*cp=='l'||*cp=='L') && (cp[1]=='u'||cp[1]=='U')) {tval.type = unsignedlong;cp += 2;} else if (*cp == 'u' || *cp == 'U') {if (overflow || n > unsignedtype->u.sym->u.limits.max.i)tval.type = unsignedlong;elsetval.type = unsignedtype;cp += 1;} else if (*cp == 'l' || *cp == 'L') {if (overflow || n > longtype->u.sym->u.limits.max.i)tval.type = unsignedlong;elsetval.type = longtype;cp += 1;} else if (overflow || n > longtype->u.sym->u.limits.max.i)tval.type = unsignedlong;else if (n > inttype->u.sym->u.limits.max.i)tval.type = longtype;else if (base != 10 && n > inttype->u.sym->u.limits.max.i)tval.type = unsignedtype;elsetval.type = inttype;switch (tval.type->op) {case INT:if (overflow || n > tval.type->u.sym->u.limits.max.i) {warning("overflow in constant `%S'\n", token,(char*)cp - token);tval.u.c.v.i = tval.type->u.sym->u.limits.max.i;} elsetval.u.c.v.i = n;break;case UNSIGNED:if (overflow || n > tval.type->u.sym->u.limits.max.u) {warning("overflow in constant `%S'\n", token,(char*)cp - token);tval.u.c.v.u = tval.type->u.sym->u.limits.max.u;} elsetval.u.c.v.u = n;break;default: assert(0);}ppnumber("integer");return &tval;}static void ppnumber(char *which) {unsigned char *rcp = cp--;for ( ; (map[*cp]&(DIGIT|LETTER)) || *cp == '.'; cp++)if ((cp[0] == 'E' || cp[0] == 'e')&& (cp[1] == '-' || cp[1] == '+'))cp++;if (cp > rcp)error("`%S' is a preprocessing number but an invalid %s constant\n", token,(char*)cp-token, which);}//处理浮点型数据的后缀static Symbol fcon(void) {if (*cp == '.')docp++;while (map[*cp]&DIGIT);if (*cp == 'e' || *cp == 'E') {if (*++cp == '-' || *cp == '+')cp++;if (map[*cp]&DIGIT)docp++;while (map[*cp]&DIGIT);elseerror("invalid floating constant `%S'\n", token,(char*)cp - token);}errno = 0;tval.u.c.v.d = strtod(token, NULL);if (errno == ERANGE)warning("overflow in floating constant `%S'\n", token,(char*)cp - token);if (*cp == 'f' || *cp == 'F') {++cp;if (tval.u.c.v.d > floattype->u.sym->u.limits.max.d)warning("overflow in floating constant `%S'\n", token,(char*)cp - token);tval.type = floattype;} else if (*cp == 'l' || *cp == 'L') {cp++;tval.type = longdouble;} else {if (tval.u.c.v.d > doubletype->u.sym->u.limits.max.d)warning("overflow in floating constant `%S'\n", token,(char*)cp - token);tval.type = doubletype;}ppnumber("floating");return &tval;}static void *cput(int c, void *cl) {char *s = cl;if (c < 0 || c > 255)warning("overflow in escape sequence with resulting value `%d'\n", c);*s++ = c;return s;}static void *wcput(int c, void *cl) {unsigned int *s = cl;*s++ = c;return s;}/*字符常量的处理*/static void *scon(int q, void *put(int c, void *cl), void *cl) {int n = 0, nbad = 0;do {cp++;while (*cp != q) {//非双反斜杠或者""int c;if (map[*cp]&NEWLINE) {if (cp < limit)break;cp++;nextline();if (cp == limit)break;continue;}c = *cp++;if (c == '\\') {if (map[*cp]&NEWLINE) {if (cp++ < limit)continue;nextline();}if (limit - cp < MAXTOKEN)fillbuf();c = backslash(q);} else if (c < 0 || c > 255 || map[c] == 0)nbad++;if (n++ < BUFSIZE)cl = put(c, cl);}if (*cp == q)cp++;elseerror("missing %c\n", q);if (q == '"' && put == wcput && getchr() == 'L') {if (limit - cp < 2)fillbuf();if (cp[1] == '"')cp++;}} while (q == '"' && getchr() == '"');cl = put(0, cl);if (n >= BUFSIZE)error("%s literal too long\n", q == '"' ? "string" : "character");if (Aflag >= 2 && q == '"' && n > 509)warning("more than 509 characters in a string literal\n");if (Aflag >= 2 && nbad > 0)warning("%s literal contains non-portable characters\n",q == '"' ? "string" : "character");return cl;}int getchr(void) {for (;;) {while (map[*cp]&BLANK)cp++;if (!(map[*cp]&NEWLINE))return *cp;cp++;nextline();if (cp == limit)return EOI;}}static int backslash(int q) {unsigned int c;switch (*cp++) {case 'a': return 7;case 'b': return '\b';case 'f': return '\f';case 'n': return '\n';case 'r': return '\r';case 't': return '\t';case 'v': return '\v';case '\'': case '"': case '\\': case '\?': break;case 'x': {int overflow = 0;if ((map[*cp]&(DIGIT|HEX)) == 0) {if (*cp < ' ' || *cp == 0177)error("ill-formed hexadecimal escape sequence\n");elseerror("ill-formed hexadecimal escape sequence `\\x%c'\n", *cp);if (*cp != q)cp++;return 0;}for (c = 0; map[*cp]&(DIGIT|HEX); cp++) {if (c >> (8*widechar->size - 4))overflow = 1;if (map[*cp]&DIGIT)c = (c<<4) + *cp - '0';elsec = (c<<4) + (*cp&~040) - 'A' + 10;}if (overflow)warning("overflow in hexadecimal escape sequence\n");return c&ones(8*widechar->size);}case '0': case '1': case '2': case '3':case '4': case '5': case '6': case '7':c = *(cp-1) - '0';if (*cp >= '0' && *cp <= '7') {c = (c<<3) + *cp++ - '0';if (*cp >= '0' && *cp <= '7')c = (c<<3) + *cp++ - '0';}return c;default:if (cp[-1] < ' ' || cp[-1] >= 0177)warning("unrecognized character escape sequence\n");elsewarning("unrecognized character escape sequence `\\%c'\n", cp[-1]);}return cp[-1];}
0 0
- lcc源代码解析之lex.c
- lcc源代码解析之sym.c
- lcc源代码解析之string.c
- lcc源代码解析之types.c
- lcc源代码解析之alloc.c
- lcc源代码解析之input.c
- lcc源代码解析之expr.c
- lcc源代码解析之stat.c
- lcc源代码解析之tree.c
- lcc源代码解析之dag.c
- lcc源代码解析之gen.c
- lcc源代码解析之interface
- lcc源代码解析只decl.c
- lcc 源代码解析之token.h
- lcc源代码解析之x86后端
- lcc源代码详解之概述
- lcc源代码详解之介绍
- lcc源代码详解之介绍
- zjut_1208 排列对称串
- 写出一个二叉树类,也就是C++中的模板类,后面加一个二叉树接口口,即c++中的类模板,最后再来一个二叉树结点类
- 德国地方个地方个地方个地方过放电
- 十分士大夫似的发生的地方
- a20 uart0 test demo
- lcc源代码解析之lex.c
- 子集生成 -- 二进制法
- 硬盘的读写原理
- 折半查找(待改进)
- 构建交叉编译环境
- IOS-给UIScrollView(包括继承它的UITableView、UICollectionView)添加下拉刷新-上拉加载更多
- 通过URL访问网络页面的一张图片
- 黑马程序员——C语言
- 解决Win7系统下以管理员身份运行的程序接收不到拖放文件消息[WM_DROPFILES]问题的方法