aboutsummaryrefslogtreecommitdiff
path: root/llex.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-05-18 14:28:04 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-05-18 14:28:04 -0300
commit889284ebd01dbc923403b0aa38b82dc80ed86af8 (patch)
tree739b2ee0b7b76da05843a0b646137b142e3e8470 /llex.c
parent6956331093e3a8d21c795b3bb125594b8ed6617b (diff)
downloadlua-889284ebd01dbc923403b0aa38b82dc80ed86af8.tar.gz
lua-889284ebd01dbc923403b0aa38b82dc80ed86af8.tar.bz2
lua-889284ebd01dbc923403b0aa38b82dc80ed86af8.zip
hexadecimal escape sequences in strings + better error messages for
bad decimal escape sequences
Diffstat (limited to 'llex.c')
-rw-r--r--llex.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/llex.c b/llex.c
index 9273260c..4d1146ce 100644
--- a/llex.c
+++ b/llex.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llex.c,v 2.31 2009/02/19 17:18:25 roberto Exp roberto $ 2** $Id: llex.c,v 2.32 2009/03/11 13:27:32 roberto Exp roberto $
3** Lexical Analyzer 3** Lexical Analyzer
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -29,7 +29,6 @@
29 29
30 30
31 31
32
33#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') 32#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
34 33
35 34
@@ -52,14 +51,14 @@ static void lexerror (LexState *ls, const char *msg, int token);
52 51
53static void save (LexState *ls, int c) { 52static void save (LexState *ls, int c) {
54 Mbuffer *b = ls->buff; 53 Mbuffer *b = ls->buff;
55 if (b->n + 1 > b->buffsize) { 54 if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
56 size_t newsize; 55 size_t newsize;
57 if (b->buffsize >= MAX_SIZET/2) 56 if (luaZ_sizebuffer(b) >= MAX_SIZET/2)
58 lexerror(ls, "lexical element too long", 0); 57 lexerror(ls, "lexical element too long", 0);
59 newsize = b->buffsize * 2; 58 newsize = luaZ_sizebuffer(b) * 2;
60 luaZ_resizebuffer(ls->L, b, newsize); 59 luaZ_resizebuffer(ls->L, b, newsize);
61 } 60 }
62 b->buffer[b->n++] = cast(char, c); 61 b->buffer[luaZ_bufflen(b)++] = cast(char, c);
63} 62}
64 63
65 64
@@ -264,6 +263,48 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
264} 263}
265 264
266 265
266static int hexavalue (int c) {
267 if (lisdigit(c)) return c - '0';
268 else if (lisupper(c)) return c - 'A' + 10;
269 else return c - 'a' + 10;
270}
271
272
273static int readhexaesc (LexState *ls) {
274 int c1, c2 = EOZ;
275 if (!lisxdigit(c1 = next(ls)) || !lisxdigit(c2 = next(ls))) {
276 luaZ_resetbuffer(ls->buff); /* prepare error message */
277 save(ls, '\\'); save(ls, 'x');
278 if (c1 != EOZ) save(ls, c1);
279 if (c2 != EOZ) save(ls, c2);
280 lexerror(ls, "hexadecimal digit expected", TK_STRING);
281 }
282 return (hexavalue(c1) << 4) + hexavalue(c2);
283}
284
285
286static int readdecesc (LexState *ls) {
287 int c1 = ls->current, c2, c3;
288 int c = c1 - '0';
289 if (lisdigit(c2 = next(ls))) {
290 c = 10*c + c2 - '0';
291 if (lisdigit(c3 = next(ls))) {
292 c = 10*c + c3 - '0';
293 if (c > UCHAR_MAX) {
294 luaZ_resetbuffer(ls->buff); /* prepare error message */
295 save(ls, '\\');
296 save(ls, c1); save(ls, c2); save(ls, c3);
297 lexerror(ls, "decimal escape too large", TK_STRING);
298 }
299 return c;
300 }
301 }
302 /* else, has read one character that was not a digit */
303 zungetc(ls->z); /* return it to input stream */
304 return c;
305}
306
307
267static void read_string (LexState *ls, int del, SemInfo *seminfo) { 308static void read_string (LexState *ls, int del, SemInfo *seminfo) {
268 save_and_next(ls); 309 save_and_next(ls);
269 while (ls->current != del) { 310 while (ls->current != del) {
@@ -275,8 +316,8 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
275 case '\r': 316 case '\r':
276 lexerror(ls, "unfinished string", TK_STRING); 317 lexerror(ls, "unfinished string", TK_STRING);
277 continue; /* to avoid warnings */ 318 continue; /* to avoid warnings */
278 case '\\': { 319 case '\\': { /* escape sequences */
279 int c; 320 int c; /* final character to be saved */
280 next(ls); /* do not save the `\' */ 321 next(ls); /* do not save the `\' */
281 switch (ls->current) { 322 switch (ls->current) {
282 case 'a': c = '\a'; break; 323 case 'a': c = '\a'; break;
@@ -286,28 +327,20 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
286 case 'r': c = '\r'; break; 327 case 'r': c = '\r'; break;
287 case 't': c = '\t'; break; 328 case 't': c = '\t'; break;
288 case 'v': c = '\v'; break; 329 case 'v': c = '\v'; break;
330 case 'x': c = readhexaesc(ls); break;
289 case '\n': 331 case '\n':
290 case '\r': save(ls, '\n'); inclinenumber(ls); continue; 332 case '\r': save(ls, '\n'); inclinenumber(ls); continue;
291 case EOZ: continue; /* will raise an error next loop */ 333 case EOZ: continue; /* will raise an error next loop */
292 default: { 334 default: {
293 if (!lisdigit(ls->current)) 335 if (!lisdigit(ls->current))
294 save_and_next(ls); /* handles \\, \", \', and \? */ 336 c = ls->current; /* handles \\, \", \', and \? */
295 else { /* \xxx */ 337 else /* digital escape \ddd */
296 int i = 0; 338 c = readdecesc(ls);
297 c = 0; 339 break;
298 do {
299 c = 10*c + (ls->current-'0');
300 next(ls);
301 } while (++i<3 && lisdigit(ls->current));
302 if (c > UCHAR_MAX)
303 lexerror(ls, "escape sequence too large", TK_STRING);
304 save(ls, c);
305 }
306 continue;
307 } 340 }
308 } 341 }
309 save(ls, c);
310 next(ls); 342 next(ls);
343 save(ls, c);
311 continue; 344 continue;
312 } 345 }
313 default: 346 default: