Branch data Line data Source code
1 : : // lex.cc -- Go frontend lexer.
2 : :
3 : : // Copyright 2009 The Go Authors. All rights reserved.
4 : : // Use of this source code is governed by a BSD-style
5 : : // license that can be found in the LICENSE file.
6 : :
7 : : #include "go-system.h"
8 : : #include "go-diagnostics.h"
9 : :
10 : : #include "lex.h"
11 : :
12 : : // Manage mapping from keywords to the Keyword codes.
13 : :
14 : : class Keywords
15 : : {
16 : : public:
17 : : // The structure which maps keywords to codes.
18 : : struct Mapping
19 : : {
20 : : // Keyword string.
21 : : const char* keystring;
22 : : // Keyword code.
23 : : Keyword keycode;
24 : : };
25 : :
26 : : // Return the parsecode corresponding to KEYSTRING, or
27 : : // KEYWORD_INVALID if it is not a keyword.
28 : : Keyword
29 : : keyword_to_code(const char* keyword, size_t len) const;
30 : :
31 : : // Return the string for a keyword.
32 : : const char*
33 : : keyword_to_string(Keyword) const;
34 : :
35 : : private:
36 : : static const Mapping mapping_[];
37 : : static const int count_;
38 : : };
39 : :
40 : : // Mapping from keyword string to keyword code. This array must be
41 : : // kept in sorted order, and the order must match the Keyword enum.
42 : : // Strings are looked up using bsearch.
43 : :
44 : : const Keywords::Mapping
45 : : Keywords::mapping_[] =
46 : : {
47 : : { NULL, KEYWORD_INVALID },
48 : : { "__asm__", KEYWORD_ASM },
49 : : { "break", KEYWORD_BREAK },
50 : : { "case", KEYWORD_CASE },
51 : : { "chan", KEYWORD_CHAN },
52 : : { "const", KEYWORD_CONST },
53 : : { "continue", KEYWORD_CONTINUE },
54 : : { "default", KEYWORD_DEFAULT },
55 : : { "defer", KEYWORD_DEFER },
56 : : { "else", KEYWORD_ELSE },
57 : : { "fallthrough", KEYWORD_FALLTHROUGH },
58 : : { "for", KEYWORD_FOR },
59 : : { "func", KEYWORD_FUNC },
60 : : { "go", KEYWORD_GO },
61 : : { "goto", KEYWORD_GOTO },
62 : : { "if", KEYWORD_IF },
63 : : { "import", KEYWORD_IMPORT },
64 : : { "interface", KEYWORD_INTERFACE },
65 : : { "map", KEYWORD_MAP },
66 : : { "package", KEYWORD_PACKAGE },
67 : : { "range", KEYWORD_RANGE },
68 : : { "return", KEYWORD_RETURN },
69 : : { "select", KEYWORD_SELECT },
70 : : { "struct", KEYWORD_STRUCT },
71 : : { "switch", KEYWORD_SWITCH },
72 : : { "type", KEYWORD_TYPE },
73 : : { "var", KEYWORD_VAR }
74 : : };
75 : :
76 : : // Number of entries in the map.
77 : :
78 : : const int Keywords::count_ =
79 : : sizeof(Keywords::mapping_) / sizeof(Keywords::mapping_[0]);
80 : :
81 : : // Comparison function passed to bsearch.
82 : :
83 : : extern "C"
84 : : {
85 : :
86 : : struct Keywords_search_key
87 : : {
88 : : const char* str;
89 : : size_t len;
90 : : };
91 : :
92 : : static int
93 : 33414298 : keyword_compare(const void* keyv, const void* mapv)
94 : : {
95 : 33414298 : const Keywords_search_key* key =
96 : : static_cast<const Keywords_search_key*>(keyv);
97 : 33414298 : const Keywords::Mapping* map =
98 : : static_cast<const Keywords::Mapping*>(mapv);
99 : 33414298 : if (map->keystring == NULL)
100 : : return 1;
101 : 32193491 : int i = strncmp(key->str, map->keystring, key->len);
102 : 32193491 : if (i != 0)
103 : : return i;
104 : 2318563 : if (map->keystring[key->len] != '\0')
105 : 1212888 : return -1;
106 : : return 0;
107 : : }
108 : :
109 : : } // End extern "C".
110 : :
111 : : // Convert a string to a keyword code. Return KEYWORD_INVALID if the
112 : : // string is not a keyword.
113 : :
114 : : Keyword
115 : 6985008 : Keywords::keyword_to_code(const char* keyword, size_t len) const
116 : : {
117 : 6985008 : Keywords_search_key key;
118 : 6985008 : key.str = keyword;
119 : 6985008 : key.len = len;
120 : 6985008 : void* mapv = bsearch(&key,
121 : : this->mapping_,
122 : : this->count_,
123 : : sizeof(this->mapping_[0]),
124 : : keyword_compare);
125 : 6985008 : if (mapv == NULL)
126 : : return KEYWORD_INVALID;
127 : 1105675 : Mapping* map = static_cast<Mapping*>(mapv);
128 : 1105675 : return map->keycode;
129 : : }
130 : :
131 : : // Convert a keyword code to a string.
132 : :
133 : : const char*
134 : 0 : Keywords::keyword_to_string(Keyword code) const
135 : : {
136 : 0 : go_assert(code > KEYWORD_INVALID && code < this->count_);
137 : 0 : const Mapping* map = &this->mapping_[code];
138 : 0 : go_assert(map->keycode == code);
139 : 0 : return map->keystring;
140 : : }
141 : :
142 : : // There is one instance of the Keywords class.
143 : :
144 : : static Keywords keywords;
145 : :
146 : : // Class Token.
147 : :
148 : : // Make a general token.
149 : :
150 : 21742768 : Token::Token(Classification classification, Location location)
151 : 21742768 : : classification_(classification), location_(location)
152 : : {
153 : 21742768 : }
154 : :
155 : : // Destroy a token.
156 : :
157 : 23070164 : Token::~Token()
158 : : {
159 : 23070164 : this->clear();
160 : 23070164 : }
161 : :
162 : : // Clear a token--release memory.
163 : :
164 : : void
165 : 44787526 : Token::clear()
166 : : {
167 : 44787526 : if (this->classification_ == TOKEN_INTEGER
168 : 44787526 : || this->classification_ == TOKEN_CHARACTER)
169 : 3923067 : mpz_clear(this->u_.integer_value);
170 : 40864459 : else if (this->classification_ == TOKEN_FLOAT
171 : 40864459 : || this->classification_ == TOKEN_IMAGINARY)
172 : 59121 : mpfr_clear(this->u_.float_value);
173 : 44787526 : }
174 : :
175 : : // Construct a token.
176 : :
177 : 1327396 : Token::Token(const Token& tok)
178 : 1327396 : : classification_(tok.classification_), location_(tok.location_)
179 : : {
180 : 1327396 : switch (this->classification_)
181 : : {
182 : : case TOKEN_INVALID:
183 : : case TOKEN_EOF:
184 : : break;
185 : 0 : case TOKEN_KEYWORD:
186 : 0 : this->u_.keyword = tok.u_.keyword;
187 : 0 : break;
188 : 0 : case TOKEN_IDENTIFIER:
189 : 0 : case TOKEN_STRING:
190 : 0 : this->u_.string_value = tok.u_.string_value;
191 : 0 : break;
192 : 0 : case TOKEN_OPERATOR:
193 : 0 : this->u_.op = tok.u_.op;
194 : 0 : break;
195 : 1307689 : case TOKEN_CHARACTER:
196 : 1307689 : case TOKEN_INTEGER:
197 : 1307689 : mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
198 : 1307689 : break;
199 : 19707 : case TOKEN_FLOAT:
200 : 19707 : case TOKEN_IMAGINARY:
201 : 19707 : mpfr_init_set(this->u_.float_value, tok.u_.float_value, MPFR_RNDN);
202 : 19707 : break;
203 : 0 : default:
204 : 0 : go_unreachable();
205 : : }
206 : 1327396 : }
207 : :
208 : : // Assign to a token.
209 : :
210 : : Token&
211 : 21717362 : Token::operator=(const Token& tok)
212 : : {
213 : 21717362 : this->clear();
214 : 21717362 : this->classification_ = tok.classification_;
215 : 21717362 : this->location_ = tok.location_;
216 : 21717362 : switch (tok.classification_)
217 : : {
218 : : case TOKEN_INVALID:
219 : : case TOKEN_EOF:
220 : : break;
221 : 1105675 : case TOKEN_KEYWORD:
222 : 1105675 : this->u_.keyword = tok.u_.keyword;
223 : 1105675 : break;
224 : 7636308 : case TOKEN_IDENTIFIER:
225 : 7636308 : this->u_.identifier_value.name = tok.u_.identifier_value.name;
226 : 7636308 : this->u_.identifier_value.is_exported =
227 : 7636308 : tok.u_.identifier_value.is_exported;
228 : 7636308 : break;
229 : 460494 : case TOKEN_STRING:
230 : 460494 : this->u_.string_value = tok.u_.string_value;
231 : 460494 : break;
232 : 11174784 : case TOKEN_OPERATOR:
233 : 11174784 : this->u_.op = tok.u_.op;
234 : 11174784 : break;
235 : 1307689 : case TOKEN_CHARACTER:
236 : 1307689 : case TOKEN_INTEGER:
237 : 1307689 : mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
238 : 1307689 : break;
239 : 19707 : case TOKEN_FLOAT:
240 : 19707 : case TOKEN_IMAGINARY:
241 : 19707 : mpfr_init_set(this->u_.float_value, tok.u_.float_value, MPFR_RNDN);
242 : 19707 : break;
243 : 0 : default:
244 : 0 : go_unreachable();
245 : : }
246 : 21717362 : return *this;
247 : : }
248 : :
249 : : // Print the token for debugging.
250 : :
251 : : void
252 : 0 : Token::print(FILE* file) const
253 : : {
254 : 0 : switch (this->classification_)
255 : : {
256 : 0 : case TOKEN_INVALID:
257 : 0 : fprintf(file, "invalid");
258 : 0 : break;
259 : 0 : case TOKEN_EOF:
260 : 0 : fprintf(file, "EOF");
261 : 0 : break;
262 : 0 : case TOKEN_KEYWORD:
263 : 0 : fprintf(file, "keyword %s", keywords.keyword_to_string(this->u_.keyword));
264 : 0 : break;
265 : 0 : case TOKEN_IDENTIFIER:
266 : 0 : fprintf(file, "identifier \"%s\"", this->u_.string_value->c_str());
267 : 0 : break;
268 : 0 : case TOKEN_STRING:
269 : 0 : fprintf(file, "quoted string \"%s\"", this->u_.string_value->c_str());
270 : 0 : break;
271 : 0 : case TOKEN_CHARACTER:
272 : 0 : fprintf(file, "character ");
273 : 0 : mpz_out_str(file, 10, this->u_.integer_value);
274 : 0 : break;
275 : 0 : case TOKEN_INTEGER:
276 : 0 : fprintf(file, "integer ");
277 : 0 : mpz_out_str(file, 10, this->u_.integer_value);
278 : 0 : break;
279 : 0 : case TOKEN_FLOAT:
280 : 0 : fprintf(file, "float ");
281 : 0 : mpfr_out_str(file, 10, 0, this->u_.float_value, MPFR_RNDN);
282 : 0 : break;
283 : 0 : case TOKEN_IMAGINARY:
284 : 0 : fprintf(file, "imaginary ");
285 : 0 : mpfr_out_str(file, 10, 0, this->u_.float_value, MPFR_RNDN);
286 : 0 : break;
287 : 0 : case TOKEN_OPERATOR:
288 : 0 : fprintf(file, "operator ");
289 : 0 : switch (this->u_.op)
290 : : {
291 : 0 : case OPERATOR_INVALID:
292 : 0 : fprintf(file, "invalid");
293 : 0 : break;
294 : 0 : case OPERATOR_OROR:
295 : 0 : fprintf(file, "||");
296 : 0 : break;
297 : 0 : case OPERATOR_ANDAND:
298 : 0 : fprintf(file, "&&");
299 : 0 : break;
300 : 0 : case OPERATOR_EQEQ:
301 : 0 : fprintf(file, "==");
302 : 0 : break;
303 : 0 : case OPERATOR_NOTEQ:
304 : 0 : fprintf(file, "!=");
305 : 0 : break;
306 : 0 : case OPERATOR_LT:
307 : 0 : fprintf(file, "<");
308 : 0 : break;
309 : 0 : case OPERATOR_LE:
310 : 0 : fprintf(file, "<=");
311 : 0 : break;
312 : 0 : case OPERATOR_GT:
313 : 0 : fprintf(file, ">");
314 : 0 : break;
315 : 0 : case OPERATOR_GE:
316 : 0 : fprintf(file, ">=");
317 : 0 : break;
318 : 0 : case OPERATOR_PLUS:
319 : 0 : fprintf(file, "+");
320 : 0 : break;
321 : 0 : case OPERATOR_MINUS:
322 : 0 : fprintf(file, "-");
323 : 0 : break;
324 : 0 : case OPERATOR_OR:
325 : 0 : fprintf(file, "|");
326 : 0 : break;
327 : 0 : case OPERATOR_XOR:
328 : 0 : fprintf(file, "^");
329 : 0 : break;
330 : 0 : case OPERATOR_MULT:
331 : 0 : fprintf(file, "*");
332 : 0 : break;
333 : 0 : case OPERATOR_DIV:
334 : 0 : fprintf(file, "/");
335 : 0 : break;
336 : 0 : case OPERATOR_MOD:
337 : 0 : fprintf(file, "%%");
338 : 0 : break;
339 : 0 : case OPERATOR_LSHIFT:
340 : 0 : fprintf(file, "<<");
341 : 0 : break;
342 : 0 : case OPERATOR_RSHIFT:
343 : 0 : fprintf(file, ">>");
344 : 0 : break;
345 : 0 : case OPERATOR_AND:
346 : 0 : fprintf(file, "&");
347 : 0 : break;
348 : 0 : case OPERATOR_BITCLEAR:
349 : 0 : fprintf(file, "&^");
350 : 0 : break;
351 : 0 : case OPERATOR_NOT:
352 : 0 : fprintf(file, "!");
353 : 0 : break;
354 : 0 : case OPERATOR_CHANOP:
355 : 0 : fprintf(file, "<-");
356 : 0 : break;
357 : 0 : case OPERATOR_EQ:
358 : 0 : fprintf(file, "=");
359 : 0 : break;
360 : 0 : case OPERATOR_PLUSEQ:
361 : 0 : fprintf(file, "+=");
362 : 0 : break;
363 : 0 : case OPERATOR_MINUSEQ:
364 : 0 : fprintf(file, "-=");
365 : 0 : break;
366 : 0 : case OPERATOR_OREQ:
367 : 0 : fprintf(file, "|=");
368 : 0 : break;
369 : 0 : case OPERATOR_XOREQ:
370 : 0 : fprintf(file, "^=");
371 : 0 : break;
372 : 0 : case OPERATOR_MULTEQ:
373 : 0 : fprintf(file, "*=");
374 : 0 : break;
375 : 0 : case OPERATOR_DIVEQ:
376 : 0 : fprintf(file, "/=");
377 : 0 : break;
378 : 0 : case OPERATOR_MODEQ:
379 : 0 : fprintf(file, "%%=");
380 : 0 : break;
381 : 0 : case OPERATOR_LSHIFTEQ:
382 : 0 : fprintf(file, "<<=");
383 : 0 : break;
384 : 0 : case OPERATOR_RSHIFTEQ:
385 : 0 : fprintf(file, ">>=");
386 : 0 : break;
387 : 0 : case OPERATOR_ANDEQ:
388 : 0 : fprintf(file, "&=");
389 : 0 : break;
390 : 0 : case OPERATOR_BITCLEAREQ:
391 : 0 : fprintf(file, "&^=");
392 : 0 : break;
393 : 0 : case OPERATOR_PLUSPLUS:
394 : 0 : fprintf(file, "++");
395 : 0 : break;
396 : 0 : case OPERATOR_MINUSMINUS:
397 : 0 : fprintf(file, "--");
398 : 0 : break;
399 : 0 : case OPERATOR_COLON:
400 : 0 : fprintf(file, ":");
401 : 0 : break;
402 : 0 : case OPERATOR_COLONEQ:
403 : 0 : fprintf(file, ":=");
404 : 0 : break;
405 : 0 : case OPERATOR_SEMICOLON:
406 : 0 : fprintf(file, ";");
407 : 0 : break;
408 : 0 : case OPERATOR_DOT:
409 : 0 : fprintf(file, ".");
410 : 0 : break;
411 : 0 : case OPERATOR_COMMA:
412 : 0 : fprintf(file, ",");
413 : 0 : break;
414 : 0 : case OPERATOR_LPAREN:
415 : 0 : fprintf(file, "(");
416 : 0 : break;
417 : 0 : case OPERATOR_RPAREN:
418 : 0 : fprintf(file, ")");
419 : 0 : break;
420 : 0 : case OPERATOR_LCURLY:
421 : 0 : fprintf(file, "{");
422 : 0 : break;
423 : 0 : case OPERATOR_RCURLY:
424 : 0 : fprintf(file, "}");
425 : 0 : break;
426 : 0 : case OPERATOR_LSQUARE:
427 : 0 : fprintf(file, "[");
428 : 0 : break;
429 : 0 : case OPERATOR_RSQUARE:
430 : 0 : fprintf(file, "]");
431 : 0 : break;
432 : 0 : default:
433 : 0 : go_unreachable();
434 : : }
435 : : break;
436 : 0 : default:
437 : 0 : go_unreachable();
438 : : }
439 : 0 : }
440 : :
441 : : // Class Lex.
442 : :
443 : 12703 : Lex::Lex(const char* input_file_name, FILE* input_file, Linemap* linemap)
444 : 12703 : : input_file_name_(input_file_name), input_file_(input_file),
445 : 12703 : linemap_(linemap), linebuf_(NULL), linebufsize_(120), linesize_(0),
446 : 12703 : lineoff_(0), lineno_(0), add_semi_at_eol_(false), pragmas_(0),
447 : 12703 : extern_(), linknames_(NULL)
448 : : {
449 : 12703 : this->linebuf_ = new char[this->linebufsize_];
450 : 12703 : this->linemap_->start_file(input_file_name, 0);
451 : 12703 : }
452 : :
453 : 12703 : Lex::~Lex()
454 : : {
455 : 12703 : delete[] this->linebuf_;
456 : 12703 : }
457 : :
458 : : // Read a new line from the file.
459 : :
460 : : ssize_t
461 : 3767584 : Lex::get_line()
462 : : {
463 : 3767584 : char* buf = this->linebuf_;
464 : 3767584 : size_t size = this->linebufsize_;
465 : :
466 : 3767584 : FILE* file = this->input_file_;
467 : 3767584 : size_t cur = 0;
468 : 118806109 : while (true)
469 : : {
470 : 118806109 : int c = getc(file);
471 : 118806109 : if (c == EOF)
472 : : {
473 : 12718 : if (cur == 0)
474 : : return -1;
475 : : break;
476 : : }
477 : 118793391 : if (cur + 1 >= size)
478 : : {
479 : 2790 : size_t ns = 2 * size + 1;
480 : 2790 : if (ns < size || static_cast<ssize_t>(ns) < 0)
481 : 0 : go_error_at(this->location(), "out of memory");
482 : 2790 : char* nb = new char[ns];
483 : 2790 : memcpy(nb, buf, cur);
484 : 2790 : delete[] buf;
485 : 2790 : buf = nb;
486 : 2790 : size = ns;
487 : : }
488 : 118793391 : buf[cur] = c;
489 : 118793391 : ++cur;
490 : :
491 : 118793391 : if (c == '\n')
492 : : break;
493 : : }
494 : :
495 : 3754873 : buf[cur] = '\0';
496 : :
497 : 3754873 : this->linebuf_ = buf;
498 : 3754873 : this->linebufsize_ = size;
499 : :
500 : 3754873 : return cur;
501 : : }
502 : :
503 : : // See if we need to read a new line. Return true if there is a new
504 : : // line, false if we are at EOF.
505 : :
506 : : bool
507 : 21767370 : Lex::require_line()
508 : : {
509 : 21767370 : if (this->lineoff_ < this->linesize_)
510 : : return true;
511 : :
512 : 3767584 : ssize_t got = this->get_line();
513 : 3767584 : if (got < 0)
514 : : return false;
515 : 3754873 : ++this->lineno_;
516 : 3754873 : this->linesize_= got;
517 : 3754873 : this->lineoff_ = 0;
518 : :
519 : 3754873 : this->linemap_->start_line(this->lineno_, this->linesize_);
520 : :
521 : 3754873 : return true;
522 : : }
523 : :
524 : : // Get the current location.
525 : :
526 : : Location
527 : 19831359 : Lex::location() const
528 : : {
529 : 19831359 : return this->linemap_->get_location(this->lineoff_ + 1);
530 : : }
531 : :
532 : : // Get a location slightly before the current one. This is used for
533 : : // slightly more efficient handling of operator tokens.
534 : :
535 : : Location
536 : 10931719 : Lex::earlier_location(int chars) const
537 : : {
538 : 10931719 : return this->linemap_->get_location(this->lineoff_ + 1 - chars);
539 : : }
540 : :
541 : : // Get the next token.
542 : :
543 : : Token
544 : 19717593 : Lex::next_token()
545 : : {
546 : 19717593 : bool saw_cpp_comment = false;
547 : 23638117 : while (true)
548 : : {
549 : 21677855 : if (!this->require_line())
550 : : {
551 : 12711 : bool add_semi_at_eol = this->add_semi_at_eol_;
552 : 12711 : this->add_semi_at_eol_ = false;
553 : 12711 : if (add_semi_at_eol)
554 : 6 : return this->make_operator(OPERATOR_SEMICOLON, 1);
555 : 12705 : return this->make_eof_token();
556 : : }
557 : :
558 : 21665144 : if (!saw_cpp_comment)
559 : 20989622 : this->extern_.clear();
560 : 21665144 : saw_cpp_comment = false;
561 : :
562 : 21665144 : const char* p = this->linebuf_ + this->lineoff_;
563 : 21665144 : const char* pend = this->linebuf_ + this->linesize_;
564 : :
565 : 32459501 : while (p < pend)
566 : : {
567 : 30499239 : unsigned char cc = *p;
568 : 30499239 : switch (cc)
569 : : {
570 : 8769469 : case ' ': case '\t': case '\r':
571 : 8769469 : ++p;
572 : : // Skip whitespace quickly.
573 : 11671695 : while (*p == ' ' || *p == '\t' || *p == '\r')
574 : 2902226 : ++p;
575 : : break;
576 : :
577 : 2998980 : case '\n':
578 : 2998980 : {
579 : 2998980 : ++p;
580 : 2998980 : bool add_semi_at_eol = this->add_semi_at_eol_;
581 : 2998980 : this->add_semi_at_eol_ = false;
582 : 2998980 : if (add_semi_at_eol)
583 : : {
584 : 1714381 : this->lineoff_ = p - this->linebuf_;
585 : 1714381 : return this->make_operator(OPERATOR_SEMICOLON, 1);
586 : : }
587 : : }
588 : : break;
589 : :
590 : 751472 : case '/':
591 : 751472 : if (p[1] == '/')
592 : : {
593 : 731017 : this->lineoff_ = p + 2 - this->linebuf_;
594 : 731017 : this->skip_cpp_comment();
595 : 731017 : p = pend;
596 : 731017 : if (p[-1] == '\n' && this->add_semi_at_eol_)
597 : 55358 : --p;
598 : : saw_cpp_comment = true;
599 : : }
600 : 20455 : else if (p[1] == '*')
601 : : {
602 : 9291 : this->lineoff_ = p + 2 - this->linebuf_;
603 : 9291 : Location location = this->location();
604 : 9291 : bool found_newline = false;
605 : 9291 : if (!this->skip_c_comment(&found_newline))
606 : 25 : return Token::make_invalid_token(location);
607 : 9291 : if (found_newline && this->add_semi_at_eol_)
608 : : {
609 : 25 : this->add_semi_at_eol_ = false;
610 : 25 : return this->make_operator(OPERATOR_SEMICOLON, 1);
611 : : }
612 : 9266 : p = this->linebuf_ + this->lineoff_;
613 : 9266 : pend = this->linebuf_ + this->linesize_;
614 : : }
615 : 11164 : else if (p[1] == '=')
616 : : {
617 : 407 : this->add_semi_at_eol_ = false;
618 : 407 : this->lineoff_ = p + 2 - this->linebuf_;
619 : 407 : return this->make_operator(OPERATOR_DIVEQ, 2);
620 : : }
621 : : else
622 : : {
623 : 10757 : this->add_semi_at_eol_ = false;
624 : 10757 : this->lineoff_ = p + 1 - this->linebuf_;
625 : 10757 : return this->make_operator(OPERATOR_DIV, 1);
626 : : }
627 : : break;
628 : :
629 : 6985178 : case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
630 : 6985178 : case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
631 : 6985178 : case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
632 : 6985178 : case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
633 : 6985178 : case 'Y': case 'Z':
634 : 6985178 : case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
635 : 6985178 : case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
636 : 6985178 : case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
637 : 6985178 : case 's': case 't': case 'u': case 'v': case 'w': case 'x':
638 : 6985178 : case 'y': case 'z':
639 : 6985178 : case '_':
640 : 6985178 : this->lineoff_ = p - this->linebuf_;
641 : 6985178 : return this->gather_identifier();
642 : :
643 : 1278203 : case '0': case '1': case '2': case '3': case '4':
644 : 1278203 : case '5': case '6': case '7': case '8': case '9':
645 : 1278203 : this->add_semi_at_eol_ = true;
646 : 1278203 : this->lineoff_ = p - this->linebuf_;
647 : 1278203 : return this->gather_number();
648 : :
649 : 49036 : case '\'':
650 : 49036 : this->add_semi_at_eol_ = true;
651 : 49036 : this->lineoff_ = p - this->linebuf_;
652 : 49036 : return this->gather_character();
653 : :
654 : 432554 : case '"':
655 : 432554 : this->add_semi_at_eol_ = true;
656 : 432554 : this->lineoff_ = p - this->linebuf_;
657 : 432554 : return this->gather_string();
658 : :
659 : 27940 : case '`':
660 : 27940 : this->add_semi_at_eol_ = true;
661 : 27940 : this->lineoff_ = p - this->linebuf_;
662 : 27940 : return this->gather_raw_string();
663 : :
664 : 237751 : case '<':
665 : 237751 : case '>':
666 : 237751 : case '&':
667 : 237751 : if (p + 2 < pend)
668 : : {
669 : 237751 : this->add_semi_at_eol_ = false;
670 : 237751 : Operator op = this->three_character_operator(cc, p[1], p[2]);
671 : 237751 : if (op != OPERATOR_INVALID)
672 : : {
673 : 2273 : this->lineoff_ = p + 3 - this->linebuf_;
674 : 2273 : return this->make_operator(op, 3);
675 : : }
676 : : }
677 : : // Fall through.
678 : 8185016 : case '|':
679 : 8185016 : case '=':
680 : 8185016 : case '!':
681 : 8185016 : case '+':
682 : 8185016 : case '-':
683 : 8185016 : case '^':
684 : 8185016 : case '*':
685 : : // '/' handled above.
686 : 8185016 : case '%':
687 : 8185016 : case ':':
688 : 8185016 : case ';':
689 : 8185016 : case ',':
690 : 8185016 : case '(': case ')':
691 : 8185016 : case '{': case '}':
692 : 8185016 : case '[': case ']':
693 : 8185016 : {
694 : 8185016 : this->add_semi_at_eol_ = false;
695 : 8185016 : Operator op = this->two_character_operator(cc, p[1]);
696 : 8185016 : int chars;
697 : 8185016 : if (op != OPERATOR_INVALID)
698 : : {
699 : 645459 : ++p;
700 : 645459 : chars = 2;
701 : : }
702 : : else
703 : : {
704 : 7539557 : op = this->one_character_operator(cc);
705 : 7539557 : chars = 1;
706 : : }
707 : 8185016 : this->lineoff_ = p + 1 - this->linebuf_;
708 : 8185016 : return this->make_operator(op, chars);
709 : : }
710 : :
711 : 1019011 : case '.':
712 : 1019011 : if (p[1] >= '0' && p[1] <= '9')
713 : : {
714 : 157 : this->add_semi_at_eol_ = true;
715 : 157 : this->lineoff_ = p - this->linebuf_;
716 : 157 : return this->gather_number();
717 : : }
718 : 1018854 : if (p[1] == '.' && p[2] == '.')
719 : : {
720 : 8216 : this->add_semi_at_eol_ = false;
721 : 8216 : this->lineoff_ = p + 3 - this->linebuf_;
722 : 8216 : return this->make_operator(OPERATOR_ELLIPSIS, 3);
723 : : }
724 : 1010638 : this->add_semi_at_eol_ = false;
725 : 1010638 : this->lineoff_ = p + 1 - this->linebuf_;
726 : 1010638 : return this->make_operator(OPERATOR_DOT, 1);
727 : :
728 : 107 : default:
729 : 107 : {
730 : 107 : unsigned int ci;
731 : 107 : bool issued_error;
732 : 107 : this->lineoff_ = p - this->linebuf_;
733 : 107 : const char *pnext = this->advance_one_utf8_char(p, &ci,
734 : : &issued_error);
735 : :
736 : : // Ignore byte order mark at start of file.
737 : 107 : if (ci == 0xfeff)
738 : : {
739 : : p = pnext;
740 : 6 : break;
741 : : }
742 : :
743 : 105 : if (Lex::is_unicode_letter(ci))
744 : 101 : return this->gather_identifier();
745 : :
746 : 4 : if (!issued_error && Lex::is_unicode_digit(ci))
747 : : {
748 : 1 : go_error_at(this->location(),
749 : : "identifier cannot begin with digit");
750 : 1 : issued_error = true;
751 : : }
752 : :
753 : 4 : if (!issued_error)
754 : 1 : go_error_at(this->location(),
755 : : "invalid character 0x%x in input file",
756 : : ci);
757 : :
758 : : p = pend;
759 : :
760 : : break;
761 : : }
762 : : }
763 : : }
764 : :
765 : 1960262 : this->lineoff_ = p - this->linebuf_;
766 : 1960262 : }
767 : : }
768 : :
769 : : // Fetch one UTF-8 character from a string. Set *VALUE to the value.
770 : : // Return the number of bytes read from the string. Returns 0 if the
771 : : // string does not point to a valid UTF-8 character.
772 : :
773 : : int
774 : 44244939 : Lex::fetch_char(const char* p, unsigned int* value)
775 : : {
776 : 44244939 : unsigned char c = *p;
777 : 44244939 : if (c <= 0x7f)
778 : : {
779 : 43199377 : *value = c;
780 : 43199377 : return 1;
781 : : }
782 : 1045562 : else if ((c & 0xe0) == 0xc0
783 : 25808 : && (p[1] & 0xc0) == 0x80)
784 : : {
785 : 25806 : *value = (((c & 0x1f) << 6)
786 : 25806 : + (p[1] & 0x3f));
787 : 25806 : if (*value <= 0x7f)
788 : : {
789 : 1 : *value = 0xfffd;
790 : 1 : return 0;
791 : : }
792 : : return 2;
793 : : }
794 : 1019756 : else if ((c & 0xf0) == 0xe0
795 : 1018925 : && (p[1] & 0xc0) == 0x80
796 : 1018924 : && (p[2] & 0xc0) == 0x80)
797 : : {
798 : 1018923 : *value = (((c & 0xf) << 12)
799 : 1018923 : + ((p[1] & 0x3f) << 6)
800 : 1018923 : + (p[2] & 0x3f));
801 : 1018923 : if (*value <= 0x7ff)
802 : : {
803 : 0 : *value = 0xfffd;
804 : 0 : return 0;
805 : : }
806 : : return 3;
807 : : }
808 : 833 : else if ((c & 0xf8) == 0xf0
809 : 821 : && (p[1] & 0xc0) == 0x80
810 : 821 : && (p[2] & 0xc0) == 0x80
811 : 821 : && (p[3] & 0xc0) == 0x80)
812 : : {
813 : 821 : *value = (((c & 0x7) << 18)
814 : 821 : + ((p[1] & 0x3f) << 12)
815 : 821 : + ((p[2] & 0x3f) << 6)
816 : 821 : + (p[3] & 0x3f));
817 : 821 : if (*value <= 0xffff)
818 : : {
819 : 0 : *value = 0xfffd;
820 : 0 : return 0;
821 : : }
822 : : return 4;
823 : : }
824 : : else
825 : : {
826 : : /* Invalid encoding. Return the Unicode replacement
827 : : character. */
828 : 12 : *value = 0xfffd;
829 : 12 : return 0;
830 : : }
831 : : }
832 : :
833 : : // Advance one UTF-8 character. Return the pointer beyond the
834 : : // character. Set *VALUE to the value. Set *ISSUED_ERROR if an error
835 : : // was issued.
836 : :
837 : : const char*
838 : 43840346 : Lex::advance_one_utf8_char(const char* p, unsigned int* value,
839 : : bool* issued_error)
840 : : {
841 : 43840346 : *issued_error = false;
842 : :
843 : 43840346 : if (*p == '\0')
844 : : {
845 : 7 : go_error_at(this->location(), "invalid NUL byte");
846 : 7 : *issued_error = true;
847 : 7 : *value = 0;
848 : 7 : return p + 1;
849 : : }
850 : :
851 : 43840339 : int adv = Lex::fetch_char(p, value);
852 : 43840339 : if (adv == 0)
853 : : {
854 : 9 : go_error_at(this->location(), "invalid UTF-8 encoding");
855 : 9 : *issued_error = true;
856 : 9 : return p + 1;
857 : : }
858 : :
859 : : // Warn about byte order mark, except at start of file.
860 : 43840330 : if (*value == 0xfeff && (this->lineno_ != 1 || this->lineoff_ != 0))
861 : : {
862 : 4 : go_error_at(this->location(), "Unicode (UTF-8) BOM in middle of file");
863 : 4 : *issued_error = true;
864 : : }
865 : :
866 : 43840330 : return p + adv;
867 : : }
868 : :
869 : : // Pick up an identifier.
870 : :
871 : : Token
872 : 6985279 : Lex::gather_identifier()
873 : : {
874 : 6985279 : const char* pstart = this->linebuf_ + this->lineoff_;
875 : 6985279 : const char* p = pstart;
876 : 6985279 : const char* pend = this->linebuf_ + this->linesize_;
877 : 6985279 : bool is_first = true;
878 : 6985279 : bool is_exported = false;
879 : 6985279 : bool has_non_ascii_char = false;
880 : 6985279 : std::string buf;
881 : 41811662 : while (p < pend)
882 : : {
883 : 41811661 : unsigned char cc = *p;
884 : 41811661 : if (cc <= 0x7f)
885 : : {
886 : 41811393 : if ((cc < 'A' || cc > 'Z')
887 : 41811393 : && (cc < 'a' || cc > 'z')
888 : 8776212 : && cc != '_'
889 : 8129362 : && (cc < '0' || cc > '9'))
890 : : {
891 : : // Check for an invalid character here, as we get better
892 : : // error behaviour if we swallow them as part of the
893 : : // identifier we are building.
894 : 6985282 : if ((cc >= ' ' && cc < 0x7f)
895 : 6985282 : || cc == '\t'
896 : 404185 : || cc == '\r'
897 : 404185 : || cc == '\n')
898 : : break;
899 : :
900 : 4 : this->lineoff_ = p - this->linebuf_;
901 : 4 : go_error_at(this->location(),
902 : : "invalid character 0x%x in identifier",
903 : : cc);
904 : 4 : if (!has_non_ascii_char)
905 : : {
906 : 4 : buf.assign(pstart, p - pstart);
907 : 4 : has_non_ascii_char = true;
908 : : }
909 : 4 : if (!Lex::is_invalid_identifier(buf))
910 : 4 : buf.append("$INVALID$");
911 : : }
912 : 34826115 : ++p;
913 : 34826115 : if (is_first)
914 : : {
915 : 6985178 : is_exported = cc >= 'A' && cc <= 'Z';
916 : 6985178 : is_first = false;
917 : : }
918 : 34826115 : if (has_non_ascii_char)
919 : 772 : buf.push_back(cc);
920 : : }
921 : : else
922 : : {
923 : 268 : unsigned int ci;
924 : 268 : bool issued_error;
925 : 268 : this->lineoff_ = p - this->linebuf_;
926 : 268 : const char* pnext = this->advance_one_utf8_char(p, &ci,
927 : : &issued_error);
928 : 268 : bool is_invalid = false;
929 : 268 : if (!Lex::is_unicode_letter(ci) && !Lex::is_unicode_digit(ci))
930 : : {
931 : : // There is no valid place for a non-ASCII character
932 : : // other than an identifier, so we get better error
933 : : // handling behaviour if we swallow this character after
934 : : // giving an error.
935 : 3 : if (!issued_error)
936 : 1 : go_error_at(this->location(),
937 : : "invalid character 0x%x in identifier",
938 : : ci);
939 : : is_invalid = true;
940 : : }
941 : 268 : if (is_first)
942 : : {
943 : 101 : is_exported = Lex::is_unicode_uppercase(ci);
944 : 101 : is_first = false;
945 : : }
946 : 268 : if (!has_non_ascii_char)
947 : : {
948 : 267 : buf.assign(pstart, p - pstart);
949 : 267 : has_non_ascii_char = true;
950 : : }
951 : 268 : if (is_invalid && !Lex::is_invalid_identifier(buf))
952 : 2 : buf.append("$INVALID$");
953 : 268 : buf.append(p, pnext - p);
954 : 268 : p = pnext;
955 : : }
956 : : }
957 : 6985279 : Location location = this->location();
958 : 6985279 : this->add_semi_at_eol_ = true;
959 : 6985279 : this->lineoff_ = p - this->linebuf_;
960 : 6985279 : if (has_non_ascii_char)
961 : 271 : return Token::make_identifier_token(buf, is_exported, location);
962 : : else
963 : : {
964 : 6985008 : Keyword code = keywords.keyword_to_code(pstart, p - pstart);
965 : 6985008 : if (code == KEYWORD_INVALID)
966 : 5879333 : return Token::make_identifier_token(std::string(pstart, p - pstart),
967 : 5879333 : is_exported, location);
968 : : else
969 : : {
970 : 1105675 : switch (code)
971 : : {
972 : : case KEYWORD_BREAK:
973 : : case KEYWORD_CONTINUE:
974 : : case KEYWORD_FALLTHROUGH:
975 : : case KEYWORD_RETURN:
976 : : break;
977 : 893401 : default:
978 : 893401 : this->add_semi_at_eol_ = false;
979 : 893401 : break;
980 : : }
981 : 1105675 : return Token::make_keyword_token(code, location);
982 : : }
983 : : }
984 : 6985279 : }
985 : :
986 : : // Return whether C is a hex digit.
987 : :
988 : : bool
989 : 6122437 : Lex::is_hex_digit(char c)
990 : : {
991 : 6122437 : return ((c >= '0' && c <= '9')
992 : 6122437 : || (c >= 'A' && c <= 'F')
993 : 6122437 : || (c >= 'a' && c <= 'f'));
994 : : }
995 : :
996 : : // Return whether C is a valid digit in BASE.
997 : :
998 : : bool
999 : 3818314 : Lex::is_base_digit(int base, char c)
1000 : : {
1001 : 3818314 : switch (base)
1002 : : {
1003 : 774 : case 2:
1004 : 774 : return c == '0' || c == '1';
1005 : 0 : case 8:
1006 : 0 : return c >= '0' && c <= '7';
1007 : 548010 : case 10:
1008 : 548010 : return c >= '0' && c <= '9';
1009 : 3269530 : case 16:
1010 : 3269530 : return Lex::is_hex_digit(c);
1011 : 0 : default:
1012 : 0 : go_unreachable();
1013 : : }
1014 : : }
1015 : :
1016 : : // not a hex value
1017 : : #define NHV 100
1018 : :
1019 : : // for use by Lex::hex_val
1020 : : static const unsigned char hex_value_lookup_table[256] =
1021 : : {
1022 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // NUL SOH STX ETX EOT ENQ ACK BEL
1023 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // BS HT LF VT FF CR SO SI
1024 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // DLE DC1 DC2 DC3 DC4 NAK SYN ETB
1025 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // CAN EM SUB ESC FS GS RS US
1026 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // SP ! " # $ % & '
1027 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // ( ) * + , - . /
1028 : : 0, 1, 2, 3, 4, 5, 6, 7, // 0 1 2 3 4 5 6 7
1029 : : 8, 9, NHV, NHV, NHV, NHV, NHV, NHV, // 8 9 : ; < = > ?
1030 : : NHV, 10, 11, 12, 13, 14, 15, NHV, // @ A B C D E F G
1031 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // H I J K L M N O
1032 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // P Q R S T U V W
1033 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // X Y Z [ \ ] ^ _
1034 : : NHV, 10, 11, 12, 13, 14, 15, NHV, // ` a b c d e f g
1035 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // h i j k l m n o
1036 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // p q r s t u v w
1037 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, // x y z { | } ~
1038 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1039 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1040 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1041 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1042 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1043 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1044 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1045 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1046 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1047 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1048 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1049 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1050 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1051 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1052 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV, //
1053 : : NHV, NHV, NHV, NHV, NHV, NHV, NHV, NHV //
1054 : : };
1055 : :
1056 : : unsigned
1057 : 2852902 : Lex::hex_val(char c)
1058 : : {
1059 : 2852902 : return hex_value_lookup_table[static_cast<unsigned char>(c)];
1060 : : }
1061 : :
1062 : : // Return whether an exponent could start at P, in base BASE.
1063 : :
1064 : : bool
1065 : 1277967 : Lex::could_be_exponent(int base, const char* p, const char* pend)
1066 : : {
1067 : 1277967 : switch (base)
1068 : : {
1069 : 666373 : case 10:
1070 : 666373 : if (*p != 'e' && *p != 'E')
1071 : : return false;
1072 : : break;
1073 : 611594 : case 16:
1074 : 611594 : if (*p != 'p' && *p != 'P')
1075 : : return false;
1076 : : break;
1077 : 0 : default:
1078 : 0 : go_unreachable();
1079 : : }
1080 : 10993 : ++p;
1081 : 10993 : if (p >= pend)
1082 : : return false;
1083 : 10993 : if (*p == '+' || *p == '-')
1084 : : {
1085 : 8114 : ++p;
1086 : 8114 : if (p >= pend)
1087 : : return false;
1088 : : }
1089 : 10993 : return *p >= '0' && *p <= '9';
1090 : : }
1091 : :
1092 : : // Pick up a number.
1093 : :
1094 : : Token
1095 : 1278360 : Lex::gather_number()
1096 : : {
1097 : 1278360 : const char* pstart = this->linebuf_ + this->lineoff_;
1098 : 1278360 : const char* p = pstart;
1099 : 1278360 : const char* pend = this->linebuf_ + this->linesize_;
1100 : :
1101 : 1278360 : Location location = this->location();
1102 : :
1103 : 1278360 : int base = 10;
1104 : 1278360 : std::string num;
1105 : 1278360 : if (*p == '0')
1106 : : {
1107 : 774460 : int basecheck;
1108 : 774460 : int off;
1109 : 774460 : if (p[1] == 'x' || p[1] == 'X')
1110 : : {
1111 : : base = 16;
1112 : : basecheck = 16;
1113 : : off = 2;
1114 : : }
1115 : : else if (p[1] == 'o' || p[1] == 'O')
1116 : : {
1117 : : base = 8;
1118 : : basecheck = 8;
1119 : : off = 2;
1120 : : }
1121 : : else if (p[1] == 'b' || p[1] == 'B')
1122 : : {
1123 : : base = 2;
1124 : : basecheck = 2;
1125 : : off = 2;
1126 : : }
1127 : : else
1128 : : {
1129 : : // Old style octal literal. May also be the start of a
1130 : : // floating-point number (e.g., 09.2, 09e2) or an imaginary
1131 : : // literal (e.g., 09i), so we have to accept decimal digits.
1132 : 774460 : base = 8;
1133 : 774460 : basecheck = 10;
1134 : 774460 : off = 0;
1135 : : }
1136 : :
1137 : 774460 : p += off;
1138 : 774460 : if (*p == '_' && Lex::is_base_digit(basecheck, p[1]))
1139 : 0 : ++p;
1140 : :
1141 : 3611643 : while (Lex::is_base_digit(basecheck, *p))
1142 : : {
1143 : 2837183 : num.push_back(*p);
1144 : 2837183 : ++p;
1145 : 2837183 : if (*p == '_' && Lex::is_base_digit(basecheck, p[1]))
1146 : 0 : ++p;
1147 : : }
1148 : :
1149 : : // We must see at least one valid digit, except for a case like
1150 : : // 0x.0p1.
1151 : 774460 : if (num.length() == 0 && (base != 16 || *p != '.'))
1152 : : {
1153 : 0 : go_error_at(this->location(), "invalid numeric literal");
1154 : 0 : this->lineoff_ = p - this->linebuf_;
1155 : 0 : mpz_t val;
1156 : 0 : mpz_init_set_ui(val, 0);
1157 : 0 : Token ret = Token::make_integer_token(val, location);
1158 : 0 : mpz_clear(val);
1159 : 0 : return ret;
1160 : 0 : }
1161 : :
1162 : 774460 : bool is_float = false;
1163 : : // A number that looks like an old-style octal literal might
1164 : : // actually be the beginning of a floating-point or imaginary
1165 : : // literal, in which case the value is decimal digits. Handle
1166 : : // that case below by treating the leading '0' as decimal.
1167 : 774460 : if (off == 0
1168 : 774460 : && (*p == '.' || *p == 'i' || Lex::could_be_exponent(10, p, pend)))
1169 : : {
1170 : : is_float = true;
1171 : : base = 10;
1172 : : }
1173 : 769198 : else if (base == 16
1174 : 769198 : && (*p == '.' || Lex::could_be_exponent(16, p, pend)))
1175 : : is_float = true;
1176 : :
1177 : 774460 : if (!is_float)
1178 : : {
1179 : 769123 : mpz_t val;
1180 : 769123 : int r = mpz_init_set_str(val, num.c_str(), base);
1181 : 769123 : if (r != 0)
1182 : : {
1183 : 0 : const char *errword;
1184 : 0 : switch (base)
1185 : : {
1186 : : case 2:
1187 : : errword = "binary";
1188 : : break;
1189 : 0 : case 8:
1190 : 0 : errword = "octal";
1191 : 0 : break;
1192 : 0 : case 16:
1193 : 0 : errword = "hex";
1194 : 0 : break;
1195 : 0 : default:
1196 : 0 : go_unreachable();
1197 : : }
1198 : 0 : go_error_at(this->location(), "invalid %s literal", errword);
1199 : : }
1200 : :
1201 : 769123 : bool is_imaginary = *p == 'i';
1202 : 769123 : if (is_imaginary)
1203 : 0 : ++p;
1204 : :
1205 : 769123 : this->lineoff_ = p - this->linebuf_;
1206 : :
1207 : 769123 : if (*p == 'e' || *p == 'E' || *p == 'p' || *p == 'P')
1208 : : {
1209 : 1 : go_error_at(location,
1210 : : "invalid prefix for floating constant");
1211 : 1 : this->skip_exponent();
1212 : : }
1213 : :
1214 : 769123 : if (!is_imaginary)
1215 : : {
1216 : 769123 : Token ret = Token::make_integer_token(val, location);
1217 : 769123 : mpz_clear(val);
1218 : 769123 : return ret;
1219 : 769123 : }
1220 : : else
1221 : : {
1222 : 0 : mpfr_t ival;
1223 : 0 : mpfr_init_set_z(ival, val, MPFR_RNDN);
1224 : 0 : mpz_clear(val);
1225 : 0 : Token ret = Token::make_imaginary_token(ival, location);
1226 : 0 : mpfr_clear(ival);
1227 : 0 : return ret;
1228 : 0 : }
1229 : : }
1230 : : }
1231 : :
1232 : 1472188 : while (p < pend)
1233 : : {
1234 : 1472188 : if (*p == '_' && p[1] >= '0' && p[1] <= '9')
1235 : 58 : ++p;
1236 : 1472130 : else if (*p < '0' || *p > '9')
1237 : : break;
1238 : 962951 : num.push_back(*p);
1239 : 962951 : ++p;
1240 : : }
1241 : :
1242 : 509237 : if (*p != '.' && *p != 'i' && !Lex::could_be_exponent(base, p, pend))
1243 : : {
1244 : 489530 : mpz_t val;
1245 : 489530 : int r = mpz_init_set_str(val, num.c_str(), 10);
1246 : 489530 : go_assert(r == 0);
1247 : :
1248 : 489530 : this->lineoff_ = p - this->linebuf_;
1249 : :
1250 : 489530 : if (*p == 'e' || *p == 'E' || *p == 'p' || *p == 'P')
1251 : : {
1252 : 1 : go_error_at(location,
1253 : : "invalid prefix for floating constant");
1254 : 1 : this->skip_exponent();
1255 : : }
1256 : :
1257 : 489530 : Token ret = Token::make_integer_token(val, location);
1258 : 489530 : mpz_clear(val);
1259 : 489530 : return ret;
1260 : 489530 : }
1261 : :
1262 : 19707 : if (*p != 'i')
1263 : : {
1264 : 19276 : bool dot = *p == '.';
1265 : :
1266 : 19276 : num.push_back(*p);
1267 : 19276 : ++p;
1268 : :
1269 : 19276 : if (!dot)
1270 : : {
1271 : 2756 : if (*p == '+' || *p == '-')
1272 : : {
1273 : 461 : num.push_back(*p);
1274 : 461 : ++p;
1275 : : }
1276 : : }
1277 : :
1278 : : bool first = true;
1279 : 206671 : while (p < pend)
1280 : : {
1281 : 206671 : if (!first && *p == '_' && Lex::is_base_digit(base, p[1]))
1282 : 0 : ++p;
1283 : 206671 : else if (!Lex::is_base_digit(base, *p))
1284 : : break;
1285 : 187395 : num.push_back(*p);
1286 : 187395 : ++p;
1287 : 187395 : first = false;
1288 : : }
1289 : :
1290 : 19276 : if (dot && Lex::could_be_exponent(base, p, pend))
1291 : : {
1292 : 8101 : num.push_back(*p);
1293 : 8101 : ++p;
1294 : 8101 : if (*p == '+' || *p == '-')
1295 : : {
1296 : 7612 : num.push_back(*p);
1297 : 7612 : ++p;
1298 : : }
1299 : : first = true;
1300 : 24426 : while (p < pend)
1301 : : {
1302 : 24426 : if (!first && *p == '_' && p[1] >= '0' && p[1] <= '9')
1303 : 0 : ++p;
1304 : 24426 : else if (*p < '0' || *p > '9')
1305 : : break;
1306 : 16325 : num.push_back(*p);
1307 : 16325 : ++p;
1308 : 16325 : first = false;
1309 : : }
1310 : : }
1311 : 11175 : else if (dot && base == 16)
1312 : : {
1313 : 0 : go_error_at(this->location(),
1314 : : "invalid hex floating-point literal with no exponent");
1315 : 0 : num.append("p0");
1316 : : }
1317 : : }
1318 : :
1319 : 19707 : mpfr_clear_overflow();
1320 : 19707 : mpfr_t val;
1321 : 19707 : int r = mpfr_init_set_str(val, num.c_str(), base, MPFR_RNDN);
1322 : 19707 : go_assert(r == 0);
1323 : 19707 : if (mpfr_overflow_p())
1324 : 11 : go_error_at(this->location(),
1325 : : "floating-point exponent too large to represent");
1326 : :
1327 : 19707 : bool is_imaginary = *p == 'i';
1328 : 19707 : if (is_imaginary)
1329 : 993 : ++p;
1330 : :
1331 : 19707 : this->lineoff_ = p - this->linebuf_;
1332 : :
1333 : 19707 : if (*p == 'e' || *p == 'E' || *p == 'p' || *p == 'P')
1334 : : {
1335 : 0 : go_error_at(location,
1336 : : "invalid prefix for floating constant");
1337 : 0 : this->skip_exponent();
1338 : : }
1339 : :
1340 : 19707 : if (is_imaginary)
1341 : : {
1342 : 993 : Token ret = Token::make_imaginary_token(val, location);
1343 : 993 : mpfr_clear(val);
1344 : 993 : return ret;
1345 : 993 : }
1346 : : else
1347 : : {
1348 : 18714 : Token ret = Token::make_float_token(val, location);
1349 : 18714 : mpfr_clear(val);
1350 : 18714 : return ret;
1351 : 18714 : }
1352 : 1278360 : }
1353 : :
1354 : : // Skip an exponent after reporting an error.
1355 : :
1356 : : void
1357 : 2 : Lex::skip_exponent()
1358 : : {
1359 : 2 : const char* p = this->linebuf_ + this->lineoff_;
1360 : 2 : const char* pend = this->linebuf_ + this->linesize_;
1361 : 2 : if (*p != 'e' && *p != 'E' && *p != 'p' && *p != 'P')
1362 : : return;
1363 : 2 : ++p;
1364 : 2 : if (*p == '+' || *p == '-')
1365 : 0 : ++p;
1366 : 5 : while (p < pend)
1367 : : {
1368 : 5 : if ((*p < '0' || *p > '9') && *p != '_')
1369 : : break;
1370 : 3 : ++p;
1371 : : }
1372 : 2 : this->lineoff_ = p - this->linebuf_;
1373 : : }
1374 : :
1375 : : // Advance one character, possibly escaped. Return the pointer beyond
1376 : : // the character. Set *VALUE to the character. Set *IS_CHARACTER if
1377 : : // this is a character (e.g., 'a' or '\u1234') rather than a byte
1378 : : // value (e.g., '\001').
1379 : :
1380 : : const char*
1381 : 7765788 : Lex::advance_one_char(const char* p, bool is_single_quote, unsigned int* value,
1382 : : bool* is_character)
1383 : : {
1384 : 7765788 : *value = 0;
1385 : 7765788 : *is_character = true;
1386 : 7765788 : if (*p != '\\')
1387 : : {
1388 : 6300446 : bool issued_error;
1389 : 6300446 : const char* ret = this->advance_one_utf8_char(p, value, &issued_error);
1390 : 6300446 : if (is_single_quote
1391 : 29759 : && (*value == '\'' || *value == '\n')
1392 : 1 : && !issued_error)
1393 : 1 : go_error_at(this->location(), "invalid character literal");
1394 : 6300446 : return ret;
1395 : : }
1396 : : else
1397 : : {
1398 : 1465342 : ++p;
1399 : 1465342 : switch (*p)
1400 : : {
1401 : 124 : case '0': case '1': case '2': case '3':
1402 : 124 : case '4': case '5': case '6': case '7':
1403 : 124 : *is_character = false;
1404 : 124 : if (p[1] >= '0' && p[1] <= '7'
1405 : 123 : && p[2] >= '0' && p[2] <= '7')
1406 : : {
1407 : 122 : *value = ((Lex::octal_value(p[0]) << 6)
1408 : 122 : + (Lex::octal_value(p[1]) << 3)
1409 : 122 : + Lex::octal_value(p[2]));
1410 : 122 : if (*value > 255)
1411 : : {
1412 : 0 : go_error_at(this->location(), "invalid octal constant");
1413 : 0 : *value = 255;
1414 : : }
1415 : 122 : return p + 3;
1416 : : }
1417 : 2 : go_error_at(this->location(), "invalid octal character");
1418 : 2 : return (p[1] >= '0' && p[1] <= '7'
1419 : 2 : ? p + 2
1420 : 2 : : p + 1);
1421 : :
1422 : 1360367 : case 'x':
1423 : 1360367 : *is_character = false;
1424 : 1360367 : if (Lex::is_hex_digit(p[1]) && Lex::is_hex_digit(p[2]))
1425 : : {
1426 : 1360365 : *value = (Lex::hex_val(p[1]) << 4) + Lex::hex_val(p[2]);
1427 : 1360365 : return p + 3;
1428 : : }
1429 : 2 : go_error_at(this->location(), "invalid hex character");
1430 : 2 : return (Lex::is_hex_digit(p[1])
1431 : 2 : ? p + 2
1432 : : : p + 1);
1433 : :
1434 : 4887 : case 'a':
1435 : 4887 : *value = '\a';
1436 : 4887 : return p + 1;
1437 : 5989 : case 'b':
1438 : 5989 : *value = '\b';
1439 : 5989 : return p + 1;
1440 : 4643 : case 'f':
1441 : 4643 : *value = '\f';
1442 : 4643 : return p + 1;
1443 : 36225 : case 'n':
1444 : 36225 : *value = '\n';
1445 : 36225 : return p + 1;
1446 : 6905 : case 'r':
1447 : 6905 : *value = '\r';
1448 : 6905 : return p + 1;
1449 : 11147 : case 't':
1450 : 11147 : *value = '\t';
1451 : 11147 : return p + 1;
1452 : 7497 : case 'v':
1453 : 7497 : *value = '\v';
1454 : 7497 : return p + 1;
1455 : 2459 : case '\\':
1456 : 2459 : *value = '\\';
1457 : 2459 : return p + 1;
1458 : 469 : case '\'':
1459 : 469 : if (!is_single_quote)
1460 : 1 : go_error_at(this->location(), "invalid quoted character");
1461 : 469 : *value = '\'';
1462 : 469 : return p + 1;
1463 : 4558 : case '"':
1464 : 4558 : if (is_single_quote)
1465 : 0 : go_error_at(this->location(), "invalid quoted character");
1466 : 4558 : *value = '"';
1467 : 4558 : return p + 1;
1468 : :
1469 : 7101 : case 'u':
1470 : 14202 : if (Lex::is_hex_digit(p[1]) && Lex::is_hex_digit(p[2])
1471 : 14202 : && Lex::is_hex_digit(p[3]) && Lex::is_hex_digit(p[4]))
1472 : : {
1473 : 7101 : *value = ((Lex::hex_val(p[1]) << 12)
1474 : 7101 : + (Lex::hex_val(p[2]) << 8)
1475 : 7101 : + (Lex::hex_val(p[3]) << 4)
1476 : 7101 : + Lex::hex_val(p[4]));
1477 : 7101 : if (*value >= 0xd800 && *value < 0xe000)
1478 : : {
1479 : 3 : go_error_at(this->location(),
1480 : : "invalid unicode code point 0x%x",
1481 : : *value);
1482 : : // Use the replacement character.
1483 : 3 : *value = 0xfffd;
1484 : : }
1485 : 7101 : return p + 5;
1486 : : }
1487 : 0 : go_error_at(this->location(), "invalid little unicode code point");
1488 : 0 : return p + 1;
1489 : :
1490 : 12971 : case 'U':
1491 : 25942 : if (Lex::is_hex_digit(p[1]) && Lex::is_hex_digit(p[2])
1492 : 12971 : && Lex::is_hex_digit(p[3]) && Lex::is_hex_digit(p[4])
1493 : 12971 : && Lex::is_hex_digit(p[5]) && Lex::is_hex_digit(p[6])
1494 : 25942 : && Lex::is_hex_digit(p[7]) && Lex::is_hex_digit(p[8]))
1495 : : {
1496 : 12971 : *value = ((Lex::hex_val(p[1]) << 28)
1497 : 12971 : + (Lex::hex_val(p[2]) << 24)
1498 : 12971 : + (Lex::hex_val(p[3]) << 20)
1499 : 12971 : + (Lex::hex_val(p[4]) << 16)
1500 : 12971 : + (Lex::hex_val(p[5]) << 12)
1501 : 12971 : + (Lex::hex_val(p[6]) << 8)
1502 : 12971 : + (Lex::hex_val(p[7]) << 4)
1503 : 12971 : + Lex::hex_val(p[8]));
1504 : 12971 : if (*value > 0x10ffff
1505 : 12971 : || (*value >= 0xd800 && *value < 0xe000))
1506 : : {
1507 : 5 : go_error_at(this->location(),
1508 : : "invalid unicode code point 0x%x",
1509 : : *value);
1510 : : // Use the replacement character.
1511 : 5 : *value = 0xfffd;
1512 : : }
1513 : 12971 : return p + 9;
1514 : : }
1515 : 0 : go_error_at(this->location(), "invalid big unicode code point");
1516 : 0 : return p + 1;
1517 : :
1518 : 0 : default:
1519 : 0 : go_error_at(this->location(), "invalid character after %<\\%>");
1520 : 0 : *value = *p;
1521 : 0 : return p + 1;
1522 : : }
1523 : : }
1524 : : }
1525 : :
1526 : : // Append V to STR. IS_CHARACTER is true for a character which should
1527 : : // be stored in UTF-8, false for a general byte value which should be
1528 : : // stored directly.
1529 : :
1530 : : void
1531 : 10305704 : Lex::append_char(unsigned int v, bool is_character, std::string* str,
1532 : : Location location)
1533 : : {
1534 : 10305704 : char buf[4];
1535 : 10305704 : size_t len;
1536 : 10305704 : if (v <= 0x7f || !is_character)
1537 : : {
1538 : 9273487 : buf[0] = v;
1539 : 9273487 : len = 1;
1540 : : }
1541 : 1032217 : else if (v <= 0x7ff)
1542 : : {
1543 : 20247 : buf[0] = 0xc0 + (v >> 6);
1544 : 20247 : buf[1] = 0x80 + (v & 0x3f);
1545 : 20247 : len = 2;
1546 : : }
1547 : : else
1548 : : {
1549 : 1011970 : if (v > 0x10ffff)
1550 : : {
1551 : 9 : go_warning_at(location, 0,
1552 : : "unicode code point 0x%x out of range in string", v);
1553 : : // Turn it into the "replacement character".
1554 : 9 : v = 0xfffd;
1555 : : }
1556 : 1011970 : if (v >= 0xd800 && v < 0xe000)
1557 : : {
1558 : 2 : go_warning_at(location, 0,
1559 : : "unicode code point 0x%x is invalid surrogate pair", v);
1560 : 2 : v = 0xfffd;
1561 : : }
1562 : 1011970 : if (v <= 0xffff)
1563 : : {
1564 : 1011384 : buf[0] = 0xe0 + (v >> 12);
1565 : 1011384 : buf[1] = 0x80 + ((v >> 6) & 0x3f);
1566 : 1011384 : buf[2] = 0x80 + (v & 0x3f);
1567 : 1011384 : len = 3;
1568 : : }
1569 : : else
1570 : : {
1571 : 586 : buf[0] = 0xf0 + (v >> 18);
1572 : 586 : buf[1] = 0x80 + ((v >> 12) & 0x3f);
1573 : 586 : buf[2] = 0x80 + ((v >> 6) & 0x3f);
1574 : 586 : buf[3] = 0x80 + (v & 0x3f);
1575 : 586 : len = 4;
1576 : : }
1577 : : }
1578 : 10305704 : str->append(buf, len);
1579 : 10305704 : }
1580 : :
1581 : : // Pick up a character literal.
1582 : :
1583 : : Token
1584 : 49036 : Lex::gather_character()
1585 : : {
1586 : 49036 : ++this->lineoff_;
1587 : 49036 : const char* pstart = this->linebuf_ + this->lineoff_;
1588 : 49036 : const char* p = pstart;
1589 : :
1590 : 49036 : unsigned int value;
1591 : 49036 : bool is_character;
1592 : 49036 : p = this->advance_one_char(p, true, &value, &is_character);
1593 : :
1594 : 49036 : if (*p != '\'')
1595 : : {
1596 : 0 : go_error_at(this->location(), "unterminated character constant");
1597 : 0 : this->lineoff_ = p - this->linebuf_;
1598 : 0 : return this->make_invalid_token();
1599 : : }
1600 : :
1601 : 49036 : mpz_t val;
1602 : 49036 : mpz_init_set_ui(val, value);
1603 : :
1604 : 49036 : Location location = this->location();
1605 : 49036 : this->lineoff_ = p + 1 - this->linebuf_;
1606 : 49036 : Token ret = Token::make_character_token(val, location);
1607 : 49036 : mpz_clear(val);
1608 : 49036 : return ret;
1609 : 49036 : }
1610 : :
1611 : : // Pick up a quoted string.
1612 : :
1613 : : Token
1614 : 432554 : Lex::gather_string()
1615 : : {
1616 : 432554 : const char* pstart = this->linebuf_ + this->lineoff_ + 1;
1617 : 432554 : const char* p = pstart;
1618 : 432554 : const char* pend = this->linebuf_ + this->linesize_;
1619 : :
1620 : 432554 : std::string value;
1621 : 8149216 : while (*p != '"')
1622 : : {
1623 : 7716662 : Location loc = this->location();
1624 : 7716662 : unsigned int c;
1625 : 7716662 : bool is_character;
1626 : 7716662 : this->lineoff_ = p - this->linebuf_;
1627 : 7716662 : p = this->advance_one_char(p, false, &c, &is_character);
1628 : 7716662 : if (p >= pend)
1629 : : {
1630 : 0 : go_error_at(this->location(), "unterminated string");
1631 : 0 : --p;
1632 : 0 : break;
1633 : : }
1634 : 7716662 : Lex::append_char(c, is_character, &value, loc);
1635 : : }
1636 : :
1637 : 432554 : Location location = this->location();
1638 : 432554 : this->lineoff_ = p + 1 - this->linebuf_;
1639 : 432554 : return Token::make_string_token(value, location);
1640 : 432554 : }
1641 : :
1642 : : // Pick up a raw string.
1643 : :
1644 : : Token
1645 : 27940 : Lex::gather_raw_string()
1646 : : {
1647 : 27940 : const char* p = this->linebuf_ + this->lineoff_ + 1;
1648 : 27940 : const char* pend = this->linebuf_ + this->linesize_;
1649 : 27940 : Location location = this->location();
1650 : :
1651 : 27940 : std::string value;
1652 : 50958 : while (true)
1653 : : {
1654 : 2667356 : while (p < pend)
1655 : : {
1656 : 2616398 : if (*p == '`')
1657 : : {
1658 : 27940 : this->lineoff_ = p + 1 - this->linebuf_;
1659 : 27940 : return Token::make_string_token(value, location);
1660 : : }
1661 : 2588458 : Location loc = this->location();
1662 : 2588458 : unsigned int c;
1663 : 2588458 : bool issued_error;
1664 : 2588458 : this->lineoff_ = p - this->linebuf_;
1665 : 2588458 : p = this->advance_one_utf8_char(p, &c, &issued_error);
1666 : : // "Carriage return characters ('\r') inside raw string literals
1667 : : // are discarded from the raw string value."
1668 : 2588458 : if (c != '\r')
1669 : 2588450 : Lex::append_char(c, true, &value, loc);
1670 : : }
1671 : 50958 : this->lineoff_ = p - this->linebuf_;
1672 : 50958 : if (!this->require_line())
1673 : : {
1674 : 0 : go_error_at(location, "unterminated raw string");
1675 : 0 : return Token::make_string_token(value, location);
1676 : : }
1677 : 50958 : p = this->linebuf_ + this->lineoff_;
1678 : 50958 : pend = this->linebuf_ + this->linesize_;
1679 : 50958 : }
1680 : 27940 : }
1681 : :
1682 : : // If C1 C2 C3 are a three character operator, return the code.
1683 : :
1684 : : Operator
1685 : 237751 : Lex::three_character_operator(char c1, char c2, char c3)
1686 : : {
1687 : 237751 : if (c3 == '=')
1688 : : {
1689 : 2273 : if (c1 == '<' && c2 == '<')
1690 : : return OPERATOR_LSHIFTEQ;
1691 : 1680 : else if (c1 == '>' && c2 == '>')
1692 : : return OPERATOR_RSHIFTEQ;
1693 : 545 : else if (c1 == '&' && c2 == '^')
1694 : 545 : return OPERATOR_BITCLEAREQ;
1695 : : }
1696 : : return OPERATOR_INVALID;
1697 : : }
1698 : :
1699 : : // If C1 C2 are a two character operator, return the code.
1700 : :
1701 : : Operator
1702 : 8185016 : Lex::two_character_operator(char c1, char c2)
1703 : : {
1704 : 8185016 : switch (c1)
1705 : : {
1706 : 40432 : case '|':
1707 : 40432 : if (c2 == '|')
1708 : : return OPERATOR_OROR;
1709 : 13814 : else if (c2 == '=')
1710 : 2764 : return OPERATOR_OREQ;
1711 : : break;
1712 : 113868 : case '&':
1713 : 113868 : if (c2 == '&')
1714 : : return OPERATOR_ANDAND;
1715 : 76410 : else if (c2 == '^')
1716 : : return OPERATOR_BITCLEAR;
1717 : 74971 : else if (c2 == '=')
1718 : 584 : return OPERATOR_ANDEQ;
1719 : : break;
1720 : 6387 : case '^':
1721 : 6387 : if (c2 == '=')
1722 : 824 : return OPERATOR_XOREQ;
1723 : : break;
1724 : 470597 : case '=':
1725 : 470597 : if (c2 == '=')
1726 : 88337 : return OPERATOR_EQEQ;
1727 : : break;
1728 : 151122 : case '!':
1729 : 151122 : if (c2 == '=')
1730 : 118937 : return OPERATOR_NOTEQ;
1731 : : break;
1732 : 78095 : case '<':
1733 : 78095 : if (c2 == '=')
1734 : : return OPERATOR_LE;
1735 : 67989 : else if (c2 == '<')
1736 : : return OPERATOR_LSHIFT;
1737 : 46813 : else if (c2 == '-')
1738 : 11971 : return OPERATOR_CHANOP;
1739 : : break;
1740 : 43515 : case '>':
1741 : 43515 : if (c2 == '=')
1742 : : return OPERATOR_GE;
1743 : 33620 : else if (c2 == '>')
1744 : 12004 : return OPERATOR_RSHIFT;
1745 : : break;
1746 : 193866 : case '*':
1747 : 193866 : if (c2 == '=')
1748 : 924 : return OPERATOR_MULTEQ;
1749 : : break;
1750 : 0 : case '/':
1751 : 0 : if (c2 == '=')
1752 : 0 : return OPERATOR_DIVEQ;
1753 : : break;
1754 : 4319 : case '%':
1755 : 4319 : if (c2 == '=')
1756 : 54 : return OPERATOR_MODEQ;
1757 : : break;
1758 : 140952 : case '+':
1759 : 140952 : if (c2 == '+')
1760 : : {
1761 : 23183 : this->add_semi_at_eol_ = true;
1762 : 23183 : return OPERATOR_PLUSPLUS;
1763 : : }
1764 : 117769 : else if (c2 == '=')
1765 : 13607 : return OPERATOR_PLUSEQ;
1766 : : break;
1767 : 101265 : case '-':
1768 : 101265 : if (c2 == '-')
1769 : : {
1770 : 4271 : this->add_semi_at_eol_ = true;
1771 : 4271 : return OPERATOR_MINUSMINUS;
1772 : : }
1773 : 96994 : else if (c2 == '=')
1774 : 3872 : return OPERATOR_MINUSEQ;
1775 : : break;
1776 : 635810 : case ':':
1777 : 635810 : if (c2 == '=')
1778 : 257435 : return OPERATOR_COLONEQ;
1779 : : break;
1780 : : default:
1781 : : break;
1782 : : }
1783 : : return OPERATOR_INVALID;
1784 : : }
1785 : :
1786 : : // If character C is an operator, return the code.
1787 : :
1788 : : Operator
1789 : 7539557 : Lex::one_character_operator(char c)
1790 : : {
1791 : 7539557 : switch (c)
1792 : : {
1793 : : case '<':
1794 : : return OPERATOR_LT;
1795 : 21616 : case '>':
1796 : 21616 : return OPERATOR_GT;
1797 : 104162 : case '+':
1798 : 104162 : return OPERATOR_PLUS;
1799 : 93122 : case '-':
1800 : 93122 : return OPERATOR_MINUS;
1801 : 11050 : case '|':
1802 : 11050 : return OPERATOR_OR;
1803 : 5563 : case '^':
1804 : 5563 : return OPERATOR_XOR;
1805 : 192942 : case '*':
1806 : 192942 : return OPERATOR_MULT;
1807 : 0 : case '/':
1808 : 0 : return OPERATOR_DIV;
1809 : 4265 : case '%':
1810 : 4265 : return OPERATOR_MOD;
1811 : 74387 : case '&':
1812 : 74387 : return OPERATOR_AND;
1813 : 32185 : case '!':
1814 : 32185 : return OPERATOR_NOT;
1815 : 382260 : case '=':
1816 : 382260 : return OPERATOR_EQ;
1817 : 378375 : case ':':
1818 : 378375 : return OPERATOR_COLON;
1819 : 108489 : case ';':
1820 : 108489 : return OPERATOR_SEMICOLON;
1821 : 0 : case '.':
1822 : 0 : return OPERATOR_DOT;
1823 : 1709916 : case ',':
1824 : 1709916 : return OPERATOR_COMMA;
1825 : 1175315 : case '(':
1826 : 1175315 : return OPERATOR_LPAREN;
1827 : 1175313 : case ')':
1828 : 1175313 : this->add_semi_at_eol_ = true;
1829 : 1175313 : return OPERATOR_RPAREN;
1830 : 744474 : case '{':
1831 : 744474 : return OPERATOR_LCURLY;
1832 : 744461 : case '}':
1833 : 744461 : this->add_semi_at_eol_ = true;
1834 : 744461 : return OPERATOR_RCURLY;
1835 : 273410 : case '[':
1836 : 273410 : return OPERATOR_LSQUARE;
1837 : 273410 : case ']':
1838 : 273410 : this->add_semi_at_eol_ = true;
1839 : 273410 : return OPERATOR_RSQUARE;
1840 : 0 : default:
1841 : 0 : return OPERATOR_INVALID;
1842 : : }
1843 : : }
1844 : :
1845 : : // Skip a C-style comment.
1846 : :
1847 : : bool
1848 : 9291 : Lex::skip_c_comment(bool* found_newline)
1849 : : {
1850 : 67823 : while (true)
1851 : : {
1852 : 38557 : if (!this->require_line())
1853 : : {
1854 : 0 : go_error_at(this->location(), "unterminated comment");
1855 : 0 : return false;
1856 : : }
1857 : :
1858 : 38557 : const char* p = this->linebuf_ + this->lineoff_;
1859 : 38557 : const char* pend = this->linebuf_ + this->linesize_;
1860 : :
1861 : 1337234 : while (p < pend)
1862 : : {
1863 : 1307968 : if (p[0] == '*' && p + 1 < pend && p[1] == '/')
1864 : : {
1865 : 9291 : this->lineoff_ = p + 2 - this->linebuf_;
1866 : 9291 : return true;
1867 : : }
1868 : :
1869 : 1298677 : if (p[0] == '\n')
1870 : 29266 : *found_newline = true;
1871 : :
1872 : 1298677 : this->lineoff_ = p - this->linebuf_;
1873 : 1298677 : unsigned int c;
1874 : 1298677 : bool issued_error;
1875 : 1298677 : p = this->advance_one_utf8_char(p, &c, &issued_error);
1876 : : }
1877 : :
1878 : 29266 : this->lineoff_ = p - this->linebuf_;
1879 : 29266 : }
1880 : : }
1881 : :
1882 : : // Skip a C++-style comment.
1883 : :
1884 : : void
1885 : 731017 : Lex::skip_cpp_comment()
1886 : : {
1887 : : // Ensure that if EXTERN_ is set, it means that we just saw a
1888 : : // //extern comment.
1889 : 731017 : this->extern_.clear();
1890 : :
1891 : 731017 : Location loc = this->location();
1892 : 731017 : size_t lineoff = this->lineoff_;
1893 : :
1894 : 731017 : const char* p = this->linebuf_ + lineoff;
1895 : 731017 : const char* pend = this->linebuf_ + this->linesize_;
1896 : :
1897 : 731017 : const char* pcheck = p;
1898 : 731017 : bool saw_error = false;
1899 : 34379463 : while (pcheck < pend)
1900 : : {
1901 : 33648446 : this->lineoff_ = pcheck - this->linebuf_;
1902 : 33648446 : unsigned int c;
1903 : 33648446 : bool issued_error;
1904 : 33648446 : pcheck = this->advance_one_utf8_char(pcheck, &c, &issued_error);
1905 : 33648446 : if (issued_error)
1906 : 4 : saw_error = true;
1907 : : }
1908 : :
1909 : 731017 : if (saw_error)
1910 : 720732 : return;
1911 : :
1912 : : // Recognize various magic comments at the start of a line, preceded
1913 : : // only by spaces or tabs.
1914 : :
1915 : : // "- 2" for the "//" at the start of the comment.
1916 : 1309730 : for (const char* psp = this->linebuf_; psp < p - 2; psp++)
1917 : 654436 : if (*psp != ' ' && *psp != '\t')
1918 : : return;
1919 : :
1920 : : while (pend > p
1921 : 1310594 : && (pend[-1] == ' ' || pend[-1] == '\t'
1922 : : || pend[-1] == '\r' || pend[-1] == '\n'))
1923 : 655300 : --pend;
1924 : :
1925 : : // A C++ comment at the start of the line of the form
1926 : : // //line FILE:LINENO
1927 : : // is interpreted as setting the file name and line number of the
1928 : : // next source line.
1929 : 655294 : if (pend - p > 5 && memcmp(p, "line ", 5) == 0)
1930 : : {
1931 : 154 : p += 5;
1932 : 154 : while (p < pend && *p == ' ')
1933 : 0 : ++p;
1934 : 154 : const char* pcolon = static_cast<const char*>(memchr(p, ':', pend - p));
1935 : 154 : if (pcolon != NULL
1936 : 154 : && pcolon[1] >= '0'
1937 : 154 : && pcolon[1] <= '9')
1938 : : {
1939 : 142 : char* plend;
1940 : 142 : long lineno = strtol(pcolon + 1, &plend, 10);
1941 : 142 : if (plend > pcolon + 1
1942 : 142 : && (plend == pend
1943 : 67 : || *plend < '0'
1944 : 67 : || *plend > '9')
1945 : : && lineno > 0
1946 : 142 : && lineno < 0x7fffffff)
1947 : : {
1948 : 142 : unsigned int filelen = pcolon - p;
1949 : 142 : char* file = new char[filelen + 1];
1950 : 142 : memcpy(file, p, filelen);
1951 : 142 : file[filelen] = '\0';
1952 : :
1953 : 142 : this->linemap_->start_file(file, lineno);
1954 : 142 : this->lineno_ = lineno - 1;
1955 : :
1956 : 142 : p = plend;
1957 : : }
1958 : : }
1959 : 154 : return;
1960 : : }
1961 : :
1962 : : // As a special gccgo extension, a C++ comment at the start of the
1963 : : // line of the form
1964 : : // //extern NAME
1965 : : // which immediately precedes a function declaration means that the
1966 : : // external name of the function declaration is NAME. This is
1967 : : // normally used to permit Go code to call a C function.
1968 : 655140 : if (pend - p > 7 && memcmp(p, "extern ", 7) == 0)
1969 : : {
1970 : 613 : p += 7;
1971 : 613 : while (p < pend && (*p == ' ' || *p == '\t'))
1972 : 0 : ++p;
1973 : 613 : if (pend > p)
1974 : 613 : this->extern_ = std::string(p, pend - p);
1975 : 613 : return;
1976 : : }
1977 : :
1978 : : // All other special comments start with "go:".
1979 : :
1980 : 654527 : if (pend - p < 4 || memcmp(p, "go:", 3) != 0)
1981 : : return;
1982 : :
1983 : 10285 : const char *ps = p + 3;
1984 : 93997 : while (ps < pend && *ps != ' ' && *ps != '\t')
1985 : 83712 : ++ps;
1986 : 10285 : std::string verb = std::string(p, ps - p);
1987 : :
1988 : 10285 : if (verb == "go:linkname")
1989 : : {
1990 : : // As in the gc compiler, set the external link name for a Go symbol.
1991 : 3920 : std::string go_name;
1992 : 3920 : std::string ext_name;
1993 : 3920 : bool is_exported = false;
1994 : 3920 : if (ps < pend)
1995 : : {
1996 : 7840 : while (ps < pend && (*ps == ' ' || *ps == '\t'))
1997 : 3920 : ++ps;
1998 : 3920 : if (ps < pend)
1999 : : {
2000 : 3920 : const char* pg = ps;
2001 : :
2002 : 3920 : unsigned int c;
2003 : 3920 : bool issued_error;
2004 : 3920 : ps = this->advance_one_utf8_char(ps, &c, &issued_error);
2005 : 3920 : is_exported = Lex::is_unicode_uppercase(c);
2006 : :
2007 : 54613 : while (ps < pend && *ps != ' ' && *ps != '\t')
2008 : 46773 : ++ps;
2009 : 3920 : if (ps <= pend)
2010 : 3920 : go_name = std::string(pg, ps - pg);
2011 : 6160 : while (ps < pend && (*ps == ' ' || *ps == '\t'))
2012 : 2240 : ++ps;
2013 : : }
2014 : 3920 : if (ps < pend)
2015 : : {
2016 : : const char* pc = ps;
2017 : 37607 : while (ps < pend && *ps != ' ' && *ps != '\t')
2018 : 35367 : ++ps;
2019 : 2240 : if (ps <= pend)
2020 : 2240 : ext_name = std::string(pc, ps - pc);
2021 : : }
2022 : 3920 : if (ps != pend)
2023 : : {
2024 : 0 : go_name.clear();
2025 : 0 : ext_name.clear();
2026 : : }
2027 : : }
2028 : 3920 : if (go_name.empty())
2029 : 0 : go_error_at(loc, "usage: %<//go:linkname%> localname [linkname]");
2030 : : else
2031 : : {
2032 : 3920 : if (this->linknames_ == NULL)
2033 : 538 : this->linknames_ = new Linknames();
2034 : 3920 : (*this->linknames_)[go_name] = Linkname(ext_name, is_exported, loc);
2035 : : }
2036 : 3920 : }
2037 : 6365 : else if (verb == "go:embed")
2038 : 23 : this->gather_embed(ps, pend);
2039 : 6342 : else if (verb == "go:nointerface")
2040 : : {
2041 : : // For field tracking analysis: a //go:nointerface comment means
2042 : : // that the next interface method should not be stored in the
2043 : : // type descriptor. This permits it to be discarded if it is
2044 : : // not needed.
2045 : 1 : this->pragmas_ |= GOPRAGMA_NOINTERFACE;
2046 : : }
2047 : 6341 : else if (verb == "go:noescape")
2048 : : {
2049 : : // Applies to the next function declaration. Any arguments do
2050 : : // not escape.
2051 : : // FIXME: Not implemented.
2052 : 1608 : this->pragmas_ |= GOPRAGMA_NOESCAPE;
2053 : : }
2054 : 4733 : else if (verb == "go:nosplit")
2055 : : {
2056 : : // Applies to the next function. Do not split the stack when
2057 : : // entering the function.
2058 : 1434 : this->pragmas_ |= GOPRAGMA_NOSPLIT;
2059 : : }
2060 : 3299 : else if (verb == "go:noinline")
2061 : : {
2062 : : // Applies to the next function. Do not inline the function.
2063 : 360 : this->pragmas_ |= GOPRAGMA_NOINLINE;
2064 : : }
2065 : 2939 : else if (verb == "go:notinheap")
2066 : : {
2067 : : // Applies to the next type. The type does not live in the heap.
2068 : 203 : this->pragmas_ |= GOPRAGMA_NOTINHEAP;
2069 : : }
2070 : 2736 : else if (verb == "go:systemstack")
2071 : : {
2072 : : // Applies to the next function. It must run on the system stack.
2073 : : // FIXME: Should only work when compiling the runtime package.
2074 : : // FIXME: Not implemented.
2075 : 203 : this->pragmas_ |= GOPRAGMA_SYSTEMSTACK;
2076 : : }
2077 : 2533 : else if (verb == "go:nowritebarrier")
2078 : : {
2079 : : // Applies to the next function. If the function needs to use
2080 : : // any write barriers, it should emit an error instead.
2081 : : // FIXME: Should only work when compiling the runtime package.
2082 : 301 : this->pragmas_ |= GOPRAGMA_NOWRITEBARRIER;
2083 : : }
2084 : 2232 : else if (verb == "go:nowritebarrierrec")
2085 : : {
2086 : : // Applies to the next function. If the function, or any
2087 : : // function that it calls, needs to use any write barriers, it
2088 : : // should emit an error instead.
2089 : : // FIXME: Should only work when compiling the runtime package.
2090 : 451 : this->pragmas_ |= GOPRAGMA_NOWRITEBARRIERREC;
2091 : : }
2092 : 1781 : else if (verb == "go:yeswritebarrierrec")
2093 : : {
2094 : : // Applies to the next function. Disables go:nowritebarrierrec
2095 : : // when looking at callees; write barriers are permitted here.
2096 : : // FIXME: Should only work when compiling the runtime package.
2097 : 42 : this->pragmas_ |= GOPRAGMA_YESWRITEBARRIERREC;
2098 : : }
2099 : 1739 : else if (verb == "go:cgo_unsafe_args")
2100 : : {
2101 : : // Applies to the next function. Taking the address of any
2102 : : // argument implies taking the address of all arguments.
2103 : : // FIXME: Not implemented.
2104 : 0 : this->pragmas_ |= GOPRAGMA_CGOUNSAFEARGS;
2105 : : }
2106 : 1739 : else if (verb == "go:uintptrescapes")
2107 : : {
2108 : : // Applies to the next function. If an argument is a pointer
2109 : : // converted to uintptr, then the pointer escapes.
2110 : : // FIXME: Not implemented.
2111 : 12 : this->pragmas_ |= GOPRAGMA_UINTPTRESCAPES;
2112 : : }
2113 : 10285 : }
2114 : :
2115 : : // Read a go:embed directive. This is a series of space-separated
2116 : : // patterns. Each pattern may be a quoted or backquoted string.
2117 : :
2118 : : void
2119 : 23 : Lex::gather_embed(const char *p, const char *pend)
2120 : : {
2121 : 47 : while (true)
2122 : : {
2123 : : // Skip spaces to find the start of the next pattern. We do a
2124 : : // fast skip of space and tab, but we also permit and skip
2125 : : // Unicode space characters.
2126 : 71 : while (p < pend && (*p == ' ' || *p == '\t'))
2127 : 24 : ++p;
2128 : 47 : if (p >= pend)
2129 : : break;
2130 : 24 : unsigned int c;
2131 : 24 : bool issued_error;
2132 : 24 : const char *pnext = this->advance_one_utf8_char(p, &c, &issued_error);
2133 : 24 : if (issued_error)
2134 : 0 : return;
2135 : 24 : if (Lex::is_unicode_space(c))
2136 : : {
2137 : 0 : p = pnext;
2138 : 0 : continue;
2139 : : }
2140 : :
2141 : : // Here P points to the start of the next pattern, PNEXT points
2142 : : // to the second character in the pattern, and C is the first
2143 : : // character in that pattern (the character to which P points).
2144 : :
2145 : 24 : if (c == '"' || c == '`')
2146 : : {
2147 : 5 : Location loc = this->location();
2148 : 5 : const unsigned char quote = c;
2149 : 5 : std::string value;
2150 : 5 : p = pnext;
2151 : 95 : while (p < pend && *p != quote)
2152 : : {
2153 : 90 : bool is_character;
2154 : 90 : if (quote == '"')
2155 : 90 : p = this->advance_one_char(p, false, &c, &is_character);
2156 : : else
2157 : : {
2158 : 0 : p = this->advance_one_utf8_char(p, &c, &issued_error);
2159 : 0 : if (issued_error)
2160 : 0 : return;
2161 : : // "Carriage return characters ('\r') inside raw string
2162 : : // literals are discarded from the raw string value."
2163 : 0 : if (c == '\r')
2164 : 0 : continue;
2165 : 0 : is_character = true;
2166 : : }
2167 : 90 : Lex::append_char(c, is_character, &value, loc);
2168 : : }
2169 : 5 : if (p >= pend)
2170 : : {
2171 : : // Note that within a go:embed directive we do not
2172 : : // permit raw strings to cross multiple lines.
2173 : 0 : go_error_at(loc, "unterminated string");
2174 : 0 : return;
2175 : : }
2176 : 5 : this->embeds_.push_back(value);
2177 : 5 : ++p;
2178 : 5 : }
2179 : : else
2180 : : {
2181 : : const char *start = p;
2182 : : p = pnext;
2183 : 176 : while (p < pend)
2184 : : {
2185 : 158 : c = *p;
2186 : 158 : if (c == ' ' || c == '\t')
2187 : : break;
2188 : 157 : if (c > ' ' && c <= 0x7f)
2189 : : {
2190 : : // ASCII non-space character.
2191 : 157 : ++p;
2192 : 157 : continue;
2193 : : }
2194 : 0 : pnext = this->advance_one_utf8_char(p, &c, &issued_error);
2195 : 0 : if (issued_error)
2196 : : return;
2197 : 0 : if (Lex::is_unicode_space(c))
2198 : : break;
2199 : : p = pnext;
2200 : : }
2201 : :
2202 : 19 : this->embeds_.push_back(std::string(start, p - start));
2203 : : }
2204 : : }
2205 : : }
2206 : :
2207 : : // The Unicode tables use this struct.
2208 : :
2209 : : struct Unicode_range
2210 : : {
2211 : : // The low end of the range.
2212 : : unsigned int low;
2213 : : // The high end of the range.
2214 : : unsigned int high;
2215 : : // The stride. This entries represents low, low + stride, low + 2 *
2216 : : // stride, etc., up to high.
2217 : : unsigned int stride;
2218 : : };
2219 : :
2220 : : // A table of whitespace characters--Unicode code points classified as
2221 : : // "Space", "C" locale whitespace characters, the "next line" control
2222 : : // character (0085), the line separator (2028), the paragraph
2223 : : // separator (2029), and the "zero-width non-break space" (feff).
2224 : :
2225 : : static const Unicode_range unicode_space[] =
2226 : : {
2227 : : { 0x0009, 0x000d, 1 },
2228 : : { 0x0020, 0x0020, 1 },
2229 : : { 0x0085, 0x0085, 1 },
2230 : : { 0x00a0, 0x00a0, 1 },
2231 : : { 0x1680, 0x1680, 1 },
2232 : : { 0x180e, 0x180e, 1 },
2233 : : { 0x2000, 0x200a, 1 },
2234 : : { 0x2028, 0x2029, 1 },
2235 : : { 0x202f, 0x202f, 1 },
2236 : : { 0x205f, 0x205f, 1 },
2237 : : { 0x3000, 0x3000, 1 },
2238 : : { 0xfeff, 0xfeff, 1 },
2239 : : };
2240 : :
2241 : : // A table of Unicode digits--Unicode code points classified as
2242 : : // "Digit".
2243 : :
2244 : : static const Unicode_range unicode_digits[] =
2245 : : {
2246 : : { 0x0030, 0x0039, 1},
2247 : : { 0x0660, 0x0669, 1},
2248 : : { 0x06f0, 0x06f9, 1},
2249 : : { 0x07c0, 0x07c9, 1},
2250 : : { 0x0966, 0x096f, 1},
2251 : : { 0x09e6, 0x09ef, 1},
2252 : : { 0x0a66, 0x0a6f, 1},
2253 : : { 0x0ae6, 0x0aef, 1},
2254 : : { 0x0b66, 0x0b6f, 1},
2255 : : { 0x0be6, 0x0bef, 1},
2256 : : { 0x0c66, 0x0c6f, 1},
2257 : : { 0x0ce6, 0x0cef, 1},
2258 : : { 0x0d66, 0x0d6f, 1},
2259 : : { 0x0e50, 0x0e59, 1},
2260 : : { 0x0ed0, 0x0ed9, 1},
2261 : : { 0x0f20, 0x0f29, 1},
2262 : : { 0x1040, 0x1049, 1},
2263 : : { 0x17e0, 0x17e9, 1},
2264 : : { 0x1810, 0x1819, 1},
2265 : : { 0x1946, 0x194f, 1},
2266 : : { 0x19d0, 0x19d9, 1},
2267 : : { 0x1b50, 0x1b59, 1},
2268 : : { 0xff10, 0xff19, 1},
2269 : : { 0x104a0, 0x104a9, 1},
2270 : : { 0x1d7ce, 0x1d7ff, 1},
2271 : : };
2272 : :
2273 : : // A table of Unicode letters--Unicode code points classified as
2274 : : // "Letter".
2275 : :
2276 : : static const Unicode_range unicode_letters[] =
2277 : : {
2278 : : { 0x0041, 0x005a, 1},
2279 : : { 0x0061, 0x007a, 1},
2280 : : { 0x00aa, 0x00b5, 11},
2281 : : { 0x00ba, 0x00c0, 6},
2282 : : { 0x00c1, 0x00d6, 1},
2283 : : { 0x00d8, 0x00f6, 1},
2284 : : { 0x00f8, 0x02c1, 1},
2285 : : { 0x02c6, 0x02d1, 1},
2286 : : { 0x02e0, 0x02e4, 1},
2287 : : { 0x02ec, 0x02ee, 2},
2288 : : { 0x0370, 0x0374, 1},
2289 : : { 0x0376, 0x0377, 1},
2290 : : { 0x037a, 0x037d, 1},
2291 : : { 0x037f, 0x0386, 7},
2292 : : { 0x0388, 0x038a, 1},
2293 : : { 0x038c, 0x038e, 2},
2294 : : { 0x038f, 0x03a1, 1},
2295 : : { 0x03a3, 0x03f5, 1},
2296 : : { 0x03f7, 0x0481, 1},
2297 : : { 0x048a, 0x052f, 1},
2298 : : { 0x0531, 0x0556, 1},
2299 : : { 0x0559, 0x0561, 8},
2300 : : { 0x0562, 0x0587, 1},
2301 : : { 0x05d0, 0x05ea, 1},
2302 : : { 0x05f0, 0x05f2, 1},
2303 : : { 0x0620, 0x064a, 1},
2304 : : { 0x066e, 0x066f, 1},
2305 : : { 0x0671, 0x06d3, 1},
2306 : : { 0x06d5, 0x06e5, 16},
2307 : : { 0x06e6, 0x06ee, 8},
2308 : : { 0x06ef, 0x06fa, 11},
2309 : : { 0x06fb, 0x06fc, 1},
2310 : : { 0x06ff, 0x0710, 17},
2311 : : { 0x0712, 0x072f, 1},
2312 : : { 0x074d, 0x07a5, 1},
2313 : : { 0x07b1, 0x07ca, 25},
2314 : : { 0x07cb, 0x07ea, 1},
2315 : : { 0x07f4, 0x07f5, 1},
2316 : : { 0x07fa, 0x0800, 6},
2317 : : { 0x0801, 0x0815, 1},
2318 : : { 0x081a, 0x0824, 10},
2319 : : { 0x0828, 0x0840, 24},
2320 : : { 0x0841, 0x0858, 1},
2321 : : { 0x08a0, 0x08b4, 1},
2322 : : { 0x0904, 0x0939, 1},
2323 : : { 0x093d, 0x0950, 19},
2324 : : { 0x0958, 0x0961, 1},
2325 : : { 0x0971, 0x0980, 1},
2326 : : { 0x0985, 0x098c, 1},
2327 : : { 0x098f, 0x0990, 1},
2328 : : { 0x0993, 0x09a8, 1},
2329 : : { 0x09aa, 0x09b0, 1},
2330 : : { 0x09b2, 0x09b6, 4},
2331 : : { 0x09b7, 0x09b9, 1},
2332 : : { 0x09bd, 0x09ce, 17},
2333 : : { 0x09dc, 0x09dd, 1},
2334 : : { 0x09df, 0x09e1, 1},
2335 : : { 0x09f0, 0x09f1, 1},
2336 : : { 0x0a05, 0x0a0a, 1},
2337 : : { 0x0a0f, 0x0a10, 1},
2338 : : { 0x0a13, 0x0a28, 1},
2339 : : { 0x0a2a, 0x0a30, 1},
2340 : : { 0x0a32, 0x0a33, 1},
2341 : : { 0x0a35, 0x0a36, 1},
2342 : : { 0x0a38, 0x0a39, 1},
2343 : : { 0x0a59, 0x0a5c, 1},
2344 : : { 0x0a5e, 0x0a72, 20},
2345 : : { 0x0a73, 0x0a74, 1},
2346 : : { 0x0a85, 0x0a8d, 1},
2347 : : { 0x0a8f, 0x0a91, 1},
2348 : : { 0x0a93, 0x0aa8, 1},
2349 : : { 0x0aaa, 0x0ab0, 1},
2350 : : { 0x0ab2, 0x0ab3, 1},
2351 : : { 0x0ab5, 0x0ab9, 1},
2352 : : { 0x0abd, 0x0ad0, 19},
2353 : : { 0x0ae0, 0x0ae1, 1},
2354 : : { 0x0af9, 0x0b05, 12},
2355 : : { 0x0b06, 0x0b0c, 1},
2356 : : { 0x0b0f, 0x0b10, 1},
2357 : : { 0x0b13, 0x0b28, 1},
2358 : : { 0x0b2a, 0x0b30, 1},
2359 : : { 0x0b32, 0x0b33, 1},
2360 : : { 0x0b35, 0x0b39, 1},
2361 : : { 0x0b3d, 0x0b5c, 31},
2362 : : { 0x0b5d, 0x0b5f, 2},
2363 : : { 0x0b60, 0x0b61, 1},
2364 : : { 0x0b71, 0x0b83, 18},
2365 : : { 0x0b85, 0x0b8a, 1},
2366 : : { 0x0b8e, 0x0b90, 1},
2367 : : { 0x0b92, 0x0b95, 1},
2368 : : { 0x0b99, 0x0b9a, 1},
2369 : : { 0x0b9c, 0x0b9e, 2},
2370 : : { 0x0b9f, 0x0ba3, 4},
2371 : : { 0x0ba4, 0x0ba8, 4},
2372 : : { 0x0ba9, 0x0baa, 1},
2373 : : { 0x0bae, 0x0bb9, 1},
2374 : : { 0x0bd0, 0x0c05, 53},
2375 : : { 0x0c06, 0x0c0c, 1},
2376 : : { 0x0c0e, 0x0c10, 1},
2377 : : { 0x0c12, 0x0c28, 1},
2378 : : { 0x0c2a, 0x0c39, 1},
2379 : : { 0x0c3d, 0x0c58, 27},
2380 : : { 0x0c59, 0x0c5a, 1},
2381 : : { 0x0c60, 0x0c61, 1},
2382 : : { 0x0c85, 0x0c8c, 1},
2383 : : { 0x0c8e, 0x0c90, 1},
2384 : : { 0x0c92, 0x0ca8, 1},
2385 : : { 0x0caa, 0x0cb3, 1},
2386 : : { 0x0cb5, 0x0cb9, 1},
2387 : : { 0x0cbd, 0x0cde, 33},
2388 : : { 0x0ce0, 0x0ce1, 1},
2389 : : { 0x0cf1, 0x0cf2, 1},
2390 : : { 0x0d05, 0x0d0c, 1},
2391 : : { 0x0d0e, 0x0d10, 1},
2392 : : { 0x0d12, 0x0d3a, 1},
2393 : : { 0x0d3d, 0x0d5f, 17},
2394 : : { 0x0d60, 0x0d61, 1},
2395 : : { 0x0d7a, 0x0d7f, 1},
2396 : : { 0x0d85, 0x0d96, 1},
2397 : : { 0x0d9a, 0x0db1, 1},
2398 : : { 0x0db3, 0x0dbb, 1},
2399 : : { 0x0dbd, 0x0dc0, 3},
2400 : : { 0x0dc1, 0x0dc6, 1},
2401 : : { 0x0e01, 0x0e30, 1},
2402 : : { 0x0e32, 0x0e33, 1},
2403 : : { 0x0e40, 0x0e46, 1},
2404 : : { 0x0e81, 0x0e82, 1},
2405 : : { 0x0e84, 0x0e87, 3},
2406 : : { 0x0e88, 0x0e8a, 2},
2407 : : { 0x0e8d, 0x0e94, 7},
2408 : : { 0x0e95, 0x0e97, 1},
2409 : : { 0x0e99, 0x0e9f, 1},
2410 : : { 0x0ea1, 0x0ea3, 1},
2411 : : { 0x0ea5, 0x0ea7, 2},
2412 : : { 0x0eaa, 0x0eab, 1},
2413 : : { 0x0ead, 0x0eb0, 1},
2414 : : { 0x0eb2, 0x0eb3, 1},
2415 : : { 0x0ebd, 0x0ec0, 3},
2416 : : { 0x0ec1, 0x0ec4, 1},
2417 : : { 0x0ec6, 0x0edc, 22},
2418 : : { 0x0edd, 0x0edf, 1},
2419 : : { 0x0f00, 0x0f40, 64},
2420 : : { 0x0f41, 0x0f47, 1},
2421 : : { 0x0f49, 0x0f6c, 1},
2422 : : { 0x0f88, 0x0f8c, 1},
2423 : : { 0x1000, 0x102a, 1},
2424 : : { 0x103f, 0x1050, 17},
2425 : : { 0x1051, 0x1055, 1},
2426 : : { 0x105a, 0x105d, 1},
2427 : : { 0x1061, 0x1065, 4},
2428 : : { 0x1066, 0x106e, 8},
2429 : : { 0x106f, 0x1070, 1},
2430 : : { 0x1075, 0x1081, 1},
2431 : : { 0x108e, 0x10a0, 18},
2432 : : { 0x10a1, 0x10c5, 1},
2433 : : { 0x10c7, 0x10cd, 6},
2434 : : { 0x10d0, 0x10fa, 1},
2435 : : { 0x10fc, 0x1248, 1},
2436 : : { 0x124a, 0x124d, 1},
2437 : : { 0x1250, 0x1256, 1},
2438 : : { 0x1258, 0x125a, 2},
2439 : : { 0x125b, 0x125d, 1},
2440 : : { 0x1260, 0x1288, 1},
2441 : : { 0x128a, 0x128d, 1},
2442 : : { 0x1290, 0x12b0, 1},
2443 : : { 0x12b2, 0x12b5, 1},
2444 : : { 0x12b8, 0x12be, 1},
2445 : : { 0x12c0, 0x12c2, 2},
2446 : : { 0x12c3, 0x12c5, 1},
2447 : : { 0x12c8, 0x12d6, 1},
2448 : : { 0x12d8, 0x1310, 1},
2449 : : { 0x1312, 0x1315, 1},
2450 : : { 0x1318, 0x135a, 1},
2451 : : { 0x1380, 0x138f, 1},
2452 : : { 0x13a0, 0x13f5, 1},
2453 : : { 0x13f8, 0x13fd, 1},
2454 : : { 0x1401, 0x166c, 1},
2455 : : { 0x166f, 0x167f, 1},
2456 : : { 0x1681, 0x169a, 1},
2457 : : { 0x16a0, 0x16ea, 1},
2458 : : { 0x16f1, 0x16f8, 1},
2459 : : { 0x1700, 0x170c, 1},
2460 : : { 0x170e, 0x1711, 1},
2461 : : { 0x1720, 0x1731, 1},
2462 : : { 0x1740, 0x1751, 1},
2463 : : { 0x1760, 0x176c, 1},
2464 : : { 0x176e, 0x1770, 1},
2465 : : { 0x1780, 0x17b3, 1},
2466 : : { 0x17d7, 0x17dc, 5},
2467 : : { 0x1820, 0x1877, 1},
2468 : : { 0x1880, 0x18a8, 1},
2469 : : { 0x18aa, 0x18b0, 6},
2470 : : { 0x18b1, 0x18f5, 1},
2471 : : { 0x1900, 0x191e, 1},
2472 : : { 0x1950, 0x196d, 1},
2473 : : { 0x1970, 0x1974, 1},
2474 : : { 0x1980, 0x19ab, 1},
2475 : : { 0x19b0, 0x19c9, 1},
2476 : : { 0x1a00, 0x1a16, 1},
2477 : : { 0x1a20, 0x1a54, 1},
2478 : : { 0x1aa7, 0x1b05, 94},
2479 : : { 0x1b06, 0x1b33, 1},
2480 : : { 0x1b45, 0x1b4b, 1},
2481 : : { 0x1b83, 0x1ba0, 1},
2482 : : { 0x1bae, 0x1baf, 1},
2483 : : { 0x1bba, 0x1be5, 1},
2484 : : { 0x1c00, 0x1c23, 1},
2485 : : { 0x1c4d, 0x1c4f, 1},
2486 : : { 0x1c5a, 0x1c7d, 1},
2487 : : { 0x1ce9, 0x1cec, 1},
2488 : : { 0x1cee, 0x1cf1, 1},
2489 : : { 0x1cf5, 0x1cf6, 1},
2490 : : { 0x1d00, 0x1dbf, 1},
2491 : : { 0x1e00, 0x1f15, 1},
2492 : : { 0x1f18, 0x1f1d, 1},
2493 : : { 0x1f20, 0x1f45, 1},
2494 : : { 0x1f48, 0x1f4d, 1},
2495 : : { 0x1f50, 0x1f57, 1},
2496 : : { 0x1f59, 0x1f5f, 2},
2497 : : { 0x1f60, 0x1f7d, 1},
2498 : : { 0x1f80, 0x1fb4, 1},
2499 : : { 0x1fb6, 0x1fbc, 1},
2500 : : { 0x1fbe, 0x1fc2, 4},
2501 : : { 0x1fc3, 0x1fc4, 1},
2502 : : { 0x1fc6, 0x1fcc, 1},
2503 : : { 0x1fd0, 0x1fd3, 1},
2504 : : { 0x1fd6, 0x1fdb, 1},
2505 : : { 0x1fe0, 0x1fec, 1},
2506 : : { 0x1ff2, 0x1ff4, 1},
2507 : : { 0x1ff6, 0x1ffc, 1},
2508 : : { 0x2071, 0x207f, 14},
2509 : : { 0x2090, 0x209c, 1},
2510 : : { 0x2102, 0x2107, 5},
2511 : : { 0x210a, 0x2113, 1},
2512 : : { 0x2115, 0x2119, 4},
2513 : : { 0x211a, 0x211d, 1},
2514 : : { 0x2124, 0x212a, 2},
2515 : : { 0x212b, 0x212d, 1},
2516 : : { 0x212f, 0x2139, 1},
2517 : : { 0x213c, 0x213f, 1},
2518 : : { 0x2145, 0x2149, 1},
2519 : : { 0x214e, 0x2183, 53},
2520 : : { 0x2184, 0x2c00, 2684},
2521 : : { 0x2c01, 0x2c2e, 1},
2522 : : { 0x2c30, 0x2c5e, 1},
2523 : : { 0x2c60, 0x2ce4, 1},
2524 : : { 0x2ceb, 0x2cee, 1},
2525 : : { 0x2cf2, 0x2cf3, 1},
2526 : : { 0x2d00, 0x2d25, 1},
2527 : : { 0x2d27, 0x2d2d, 6},
2528 : : { 0x2d30, 0x2d67, 1},
2529 : : { 0x2d6f, 0x2d80, 17},
2530 : : { 0x2d81, 0x2d96, 1},
2531 : : { 0x2da0, 0x2da6, 1},
2532 : : { 0x2da8, 0x2dae, 1},
2533 : : { 0x2db0, 0x2db6, 1},
2534 : : { 0x2db8, 0x2dbe, 1},
2535 : : { 0x2dc0, 0x2dc6, 1},
2536 : : { 0x2dc8, 0x2dce, 1},
2537 : : { 0x2dd0, 0x2dd6, 1},
2538 : : { 0x2dd8, 0x2dde, 1},
2539 : : { 0x2e2f, 0x3005, 470},
2540 : : { 0x3006, 0x3031, 43},
2541 : : { 0x3032, 0x3035, 1},
2542 : : { 0x303b, 0x303c, 1},
2543 : : { 0x3041, 0x3096, 1},
2544 : : { 0x309d, 0x309f, 1},
2545 : : { 0x30a1, 0x30fa, 1},
2546 : : { 0x30fc, 0x30ff, 1},
2547 : : { 0x3105, 0x312d, 1},
2548 : : { 0x3131, 0x318e, 1},
2549 : : { 0x31a0, 0x31ba, 1},
2550 : : { 0x31f0, 0x31ff, 1},
2551 : : { 0x3400, 0x4db5, 1},
2552 : : { 0x4e00, 0x9fd5, 1},
2553 : : { 0xa000, 0xa48c, 1},
2554 : : { 0xa4d0, 0xa4fd, 1},
2555 : : { 0xa500, 0xa60c, 1},
2556 : : { 0xa610, 0xa61f, 1},
2557 : : { 0xa62a, 0xa62b, 1},
2558 : : { 0xa640, 0xa66e, 1},
2559 : : { 0xa67f, 0xa69d, 1},
2560 : : { 0xa6a0, 0xa6e5, 1},
2561 : : { 0xa717, 0xa71f, 1},
2562 : : { 0xa722, 0xa788, 1},
2563 : : { 0xa78b, 0xa7ad, 1},
2564 : : { 0xa7b0, 0xa7b7, 1},
2565 : : { 0xa7f7, 0xa801, 1},
2566 : : { 0xa803, 0xa805, 1},
2567 : : { 0xa807, 0xa80a, 1},
2568 : : { 0xa80c, 0xa822, 1},
2569 : : { 0xa840, 0xa873, 1},
2570 : : { 0xa882, 0xa8b3, 1},
2571 : : { 0xa8f2, 0xa8f7, 1},
2572 : : { 0xa8fb, 0xa8fd, 2},
2573 : : { 0xa90a, 0xa925, 1},
2574 : : { 0xa930, 0xa946, 1},
2575 : : { 0xa960, 0xa97c, 1},
2576 : : { 0xa984, 0xa9b2, 1},
2577 : : { 0xa9cf, 0xa9e0, 17},
2578 : : { 0xa9e1, 0xa9e4, 1},
2579 : : { 0xa9e6, 0xa9ef, 1},
2580 : : { 0xa9fa, 0xa9fe, 1},
2581 : : { 0xaa00, 0xaa28, 1},
2582 : : { 0xaa40, 0xaa42, 1},
2583 : : { 0xaa44, 0xaa4b, 1},
2584 : : { 0xaa60, 0xaa76, 1},
2585 : : { 0xaa7a, 0xaa7e, 4},
2586 : : { 0xaa7f, 0xaaaf, 1},
2587 : : { 0xaab1, 0xaab5, 4},
2588 : : { 0xaab6, 0xaab9, 3},
2589 : : { 0xaaba, 0xaabd, 1},
2590 : : { 0xaac0, 0xaac2, 2},
2591 : : { 0xaadb, 0xaadd, 1},
2592 : : { 0xaae0, 0xaaea, 1},
2593 : : { 0xaaf2, 0xaaf4, 1},
2594 : : { 0xab01, 0xab06, 1},
2595 : : { 0xab09, 0xab0e, 1},
2596 : : { 0xab11, 0xab16, 1},
2597 : : { 0xab20, 0xab26, 1},
2598 : : { 0xab28, 0xab2e, 1},
2599 : : { 0xab30, 0xab5a, 1},
2600 : : { 0xab5c, 0xab65, 1},
2601 : : { 0xab70, 0xabe2, 1},
2602 : : { 0xac00, 0xd7a3, 1},
2603 : : { 0xd7b0, 0xd7c6, 1},
2604 : : { 0xd7cb, 0xd7fb, 1},
2605 : : { 0xf900, 0xfa6d, 1},
2606 : : { 0xfa70, 0xfad9, 1},
2607 : : { 0xfb00, 0xfb06, 1},
2608 : : { 0xfb13, 0xfb17, 1},
2609 : : { 0xfb1d, 0xfb1f, 2},
2610 : : { 0xfb20, 0xfb28, 1},
2611 : : { 0xfb2a, 0xfb36, 1},
2612 : : { 0xfb38, 0xfb3c, 1},
2613 : : { 0xfb3e, 0xfb40, 2},
2614 : : { 0xfb41, 0xfb43, 2},
2615 : : { 0xfb44, 0xfb46, 2},
2616 : : { 0xfb47, 0xfbb1, 1},
2617 : : { 0xfbd3, 0xfd3d, 1},
2618 : : { 0xfd50, 0xfd8f, 1},
2619 : : { 0xfd92, 0xfdc7, 1},
2620 : : { 0xfdf0, 0xfdfb, 1},
2621 : : { 0xfe70, 0xfe74, 1},
2622 : : { 0xfe76, 0xfefc, 1},
2623 : : { 0xff21, 0xff3a, 1},
2624 : : { 0xff41, 0xff5a, 1},
2625 : : { 0xff66, 0xffbe, 1},
2626 : : { 0xffc2, 0xffc7, 1},
2627 : : { 0xffca, 0xffcf, 1},
2628 : : { 0xffd2, 0xffd7, 1},
2629 : : { 0xffda, 0xffdc, 1},
2630 : : { 0x10000, 0x1000b, 1},
2631 : : { 0x1000d, 0x10026, 1},
2632 : : { 0x10028, 0x1003a, 1},
2633 : : { 0x1003c, 0x1003d, 1},
2634 : : { 0x1003f, 0x1004d, 1},
2635 : : { 0x10050, 0x1005d, 1},
2636 : : { 0x10080, 0x100fa, 1},
2637 : : { 0x10280, 0x1029c, 1},
2638 : : { 0x102a0, 0x102d0, 1},
2639 : : { 0x10300, 0x1031f, 1},
2640 : : { 0x10330, 0x10340, 1},
2641 : : { 0x10342, 0x10349, 1},
2642 : : { 0x10350, 0x10375, 1},
2643 : : { 0x10380, 0x1039d, 1},
2644 : : { 0x103a0, 0x103c3, 1},
2645 : : { 0x103c8, 0x103cf, 1},
2646 : : { 0x10400, 0x1049d, 1},
2647 : : { 0x10500, 0x10527, 1},
2648 : : { 0x10530, 0x10563, 1},
2649 : : { 0x10600, 0x10736, 1},
2650 : : { 0x10740, 0x10755, 1},
2651 : : { 0x10760, 0x10767, 1},
2652 : : { 0x10800, 0x10805, 1},
2653 : : { 0x10808, 0x1080a, 2},
2654 : : { 0x1080b, 0x10835, 1},
2655 : : { 0x10837, 0x10838, 1},
2656 : : { 0x1083c, 0x1083f, 3},
2657 : : { 0x10840, 0x10855, 1},
2658 : : { 0x10860, 0x10876, 1},
2659 : : { 0x10880, 0x1089e, 1},
2660 : : { 0x108e0, 0x108f2, 1},
2661 : : { 0x108f4, 0x108f5, 1},
2662 : : { 0x10900, 0x10915, 1},
2663 : : { 0x10920, 0x10939, 1},
2664 : : { 0x10980, 0x109b7, 1},
2665 : : { 0x109be, 0x109bf, 1},
2666 : : { 0x10a00, 0x10a10, 16},
2667 : : { 0x10a11, 0x10a13, 1},
2668 : : { 0x10a15, 0x10a17, 1},
2669 : : { 0x10a19, 0x10a33, 1},
2670 : : { 0x10a60, 0x10a7c, 1},
2671 : : { 0x10a80, 0x10a9c, 1},
2672 : : { 0x10ac0, 0x10ac7, 1},
2673 : : { 0x10ac9, 0x10ae4, 1},
2674 : : { 0x10b00, 0x10b35, 1},
2675 : : { 0x10b40, 0x10b55, 1},
2676 : : { 0x10b60, 0x10b72, 1},
2677 : : { 0x10b80, 0x10b91, 1},
2678 : : { 0x10c00, 0x10c48, 1},
2679 : : { 0x10c80, 0x10cb2, 1},
2680 : : { 0x10cc0, 0x10cf2, 1},
2681 : : { 0x11003, 0x11037, 1},
2682 : : { 0x11083, 0x110af, 1},
2683 : : { 0x110d0, 0x110e8, 1},
2684 : : { 0x11103, 0x11126, 1},
2685 : : { 0x11150, 0x11172, 1},
2686 : : { 0x11176, 0x11183, 13},
2687 : : { 0x11184, 0x111b2, 1},
2688 : : { 0x111c1, 0x111c4, 1},
2689 : : { 0x111da, 0x111dc, 2},
2690 : : { 0x11200, 0x11211, 1},
2691 : : { 0x11213, 0x1122b, 1},
2692 : : { 0x11280, 0x11286, 1},
2693 : : { 0x11288, 0x1128a, 2},
2694 : : { 0x1128b, 0x1128d, 1},
2695 : : { 0x1128f, 0x1129d, 1},
2696 : : { 0x1129f, 0x112a8, 1},
2697 : : { 0x112b0, 0x112de, 1},
2698 : : { 0x11305, 0x1130c, 1},
2699 : : { 0x1130f, 0x11310, 1},
2700 : : { 0x11313, 0x11328, 1},
2701 : : { 0x1132a, 0x11330, 1},
2702 : : { 0x11332, 0x11333, 1},
2703 : : { 0x11335, 0x11339, 1},
2704 : : { 0x1133d, 0x11350, 19},
2705 : : { 0x1135d, 0x11361, 1},
2706 : : { 0x11480, 0x114af, 1},
2707 : : { 0x114c4, 0x114c5, 1},
2708 : : { 0x114c7, 0x11580, 185},
2709 : : { 0x11581, 0x115ae, 1},
2710 : : { 0x115d8, 0x115db, 1},
2711 : : { 0x11600, 0x1162f, 1},
2712 : : { 0x11644, 0x11680, 60},
2713 : : { 0x11681, 0x116aa, 1},
2714 : : { 0x11700, 0x11719, 1},
2715 : : { 0x118a0, 0x118df, 1},
2716 : : { 0x118ff, 0x11ac0, 449},
2717 : : { 0x11ac1, 0x11af8, 1},
2718 : : { 0x12000, 0x12399, 1},
2719 : : { 0x12480, 0x12543, 1},
2720 : : { 0x13000, 0x1342e, 1},
2721 : : { 0x14400, 0x14646, 1},
2722 : : { 0x16800, 0x16a38, 1},
2723 : : { 0x16a40, 0x16a5e, 1},
2724 : : { 0x16ad0, 0x16aed, 1},
2725 : : { 0x16b00, 0x16b2f, 1},
2726 : : { 0x16b40, 0x16b43, 1},
2727 : : { 0x16b63, 0x16b77, 1},
2728 : : { 0x16b7d, 0x16b8f, 1},
2729 : : { 0x16f00, 0x16f44, 1},
2730 : : { 0x16f50, 0x16f93, 67},
2731 : : { 0x16f94, 0x16f9f, 1},
2732 : : { 0x1b000, 0x1b001, 1},
2733 : : { 0x1bc00, 0x1bc6a, 1},
2734 : : { 0x1bc70, 0x1bc7c, 1},
2735 : : { 0x1bc80, 0x1bc88, 1},
2736 : : { 0x1bc90, 0x1bc99, 1},
2737 : : { 0x1d400, 0x1d454, 1},
2738 : : { 0x1d456, 0x1d49c, 1},
2739 : : { 0x1d49e, 0x1d49f, 1},
2740 : : { 0x1d4a2, 0x1d4a5, 3},
2741 : : { 0x1d4a6, 0x1d4a9, 3},
2742 : : { 0x1d4aa, 0x1d4ac, 1},
2743 : : { 0x1d4ae, 0x1d4b9, 1},
2744 : : { 0x1d4bb, 0x1d4bd, 2},
2745 : : { 0x1d4be, 0x1d4c3, 1},
2746 : : { 0x1d4c5, 0x1d505, 1},
2747 : : { 0x1d507, 0x1d50a, 1},
2748 : : { 0x1d50d, 0x1d514, 1},
2749 : : { 0x1d516, 0x1d51c, 1},
2750 : : { 0x1d51e, 0x1d539, 1},
2751 : : { 0x1d53b, 0x1d53e, 1},
2752 : : { 0x1d540, 0x1d544, 1},
2753 : : { 0x1d546, 0x1d54a, 4},
2754 : : { 0x1d54b, 0x1d550, 1},
2755 : : { 0x1d552, 0x1d6a5, 1},
2756 : : { 0x1d6a8, 0x1d6c0, 1},
2757 : : { 0x1d6c2, 0x1d6da, 1},
2758 : : { 0x1d6dc, 0x1d6fa, 1},
2759 : : { 0x1d6fc, 0x1d714, 1},
2760 : : { 0x1d716, 0x1d734, 1},
2761 : : { 0x1d736, 0x1d74e, 1},
2762 : : { 0x1d750, 0x1d76e, 1},
2763 : : { 0x1d770, 0x1d788, 1},
2764 : : { 0x1d78a, 0x1d7a8, 1},
2765 : : { 0x1d7aa, 0x1d7c2, 1},
2766 : : { 0x1d7c4, 0x1d7cb, 1},
2767 : : { 0x1e800, 0x1e8c4, 1},
2768 : : { 0x1ee00, 0x1ee03, 1},
2769 : : { 0x1ee05, 0x1ee1f, 1},
2770 : : { 0x1ee21, 0x1ee22, 1},
2771 : : { 0x1ee24, 0x1ee27, 3},
2772 : : { 0x1ee29, 0x1ee32, 1},
2773 : : { 0x1ee34, 0x1ee37, 1},
2774 : : { 0x1ee39, 0x1ee3b, 2},
2775 : : { 0x1ee42, 0x1ee47, 5},
2776 : : { 0x1ee49, 0x1ee4d, 2},
2777 : : { 0x1ee4e, 0x1ee4f, 1},
2778 : : { 0x1ee51, 0x1ee52, 1},
2779 : : { 0x1ee54, 0x1ee57, 3},
2780 : : { 0x1ee59, 0x1ee61, 2},
2781 : : { 0x1ee62, 0x1ee64, 2},
2782 : : { 0x1ee67, 0x1ee6a, 1},
2783 : : { 0x1ee6c, 0x1ee72, 1},
2784 : : { 0x1ee74, 0x1ee77, 1},
2785 : : { 0x1ee79, 0x1ee7c, 1},
2786 : : { 0x1ee7e, 0x1ee80, 2},
2787 : : { 0x1ee81, 0x1ee89, 1},
2788 : : { 0x1ee8b, 0x1ee9b, 1},
2789 : : { 0x1eea1, 0x1eea3, 1},
2790 : : { 0x1eea5, 0x1eea9, 1},
2791 : : { 0x1eeab, 0x1eebb, 1},
2792 : : { 0x20000, 0x2a6d6, 1},
2793 : : { 0x2a700, 0x2b734, 1},
2794 : : { 0x2b740, 0x2b81d, 1},
2795 : : { 0x2b820, 0x2cea1, 1},
2796 : : { 0x2f800, 0x2fa1d, 1},
2797 : : };
2798 : :
2799 : : // A table of Unicode uppercase letters--Unicode code points
2800 : : // classified as "Letter, uppercase".
2801 : :
2802 : : static const Unicode_range unicode_uppercase_letters[] =
2803 : : {
2804 : : { 0x0041, 0x005a, 1},
2805 : : { 0x00c0, 0x00d6, 1},
2806 : : { 0x00d8, 0x00de, 1},
2807 : : { 0x0100, 0x0136, 2},
2808 : : { 0x0139, 0x0147, 2},
2809 : : { 0x014a, 0x0178, 2},
2810 : : { 0x0179, 0x017d, 2},
2811 : : { 0x0181, 0x0182, 1},
2812 : : { 0x0184, 0x0186, 2},
2813 : : { 0x0187, 0x0189, 2},
2814 : : { 0x018a, 0x018b, 1},
2815 : : { 0x018e, 0x0191, 1},
2816 : : { 0x0193, 0x0194, 1},
2817 : : { 0x0196, 0x0198, 1},
2818 : : { 0x019c, 0x019d, 1},
2819 : : { 0x019f, 0x01a0, 1},
2820 : : { 0x01a2, 0x01a6, 2},
2821 : : { 0x01a7, 0x01a9, 2},
2822 : : { 0x01ac, 0x01ae, 2},
2823 : : { 0x01af, 0x01b1, 2},
2824 : : { 0x01b2, 0x01b3, 1},
2825 : : { 0x01b5, 0x01b7, 2},
2826 : : { 0x01b8, 0x01bc, 4},
2827 : : { 0x01c4, 0x01cd, 3},
2828 : : { 0x01cf, 0x01db, 2},
2829 : : { 0x01de, 0x01ee, 2},
2830 : : { 0x01f1, 0x01f4, 3},
2831 : : { 0x01f6, 0x01f8, 1},
2832 : : { 0x01fa, 0x0232, 2},
2833 : : { 0x023a, 0x023b, 1},
2834 : : { 0x023d, 0x023e, 1},
2835 : : { 0x0241, 0x0243, 2},
2836 : : { 0x0244, 0x0246, 1},
2837 : : { 0x0248, 0x024e, 2},
2838 : : { 0x0370, 0x0372, 2},
2839 : : { 0x0376, 0x037f, 9},
2840 : : { 0x0386, 0x0388, 2},
2841 : : { 0x0389, 0x038a, 1},
2842 : : { 0x038c, 0x038e, 2},
2843 : : { 0x038f, 0x0391, 2},
2844 : : { 0x0392, 0x03a1, 1},
2845 : : { 0x03a3, 0x03ab, 1},
2846 : : { 0x03cf, 0x03d2, 3},
2847 : : { 0x03d3, 0x03d4, 1},
2848 : : { 0x03d8, 0x03ee, 2},
2849 : : { 0x03f4, 0x03f7, 3},
2850 : : { 0x03f9, 0x03fa, 1},
2851 : : { 0x03fd, 0x042f, 1},
2852 : : { 0x0460, 0x0480, 2},
2853 : : { 0x048a, 0x04c0, 2},
2854 : : { 0x04c1, 0x04cd, 2},
2855 : : { 0x04d0, 0x052e, 2},
2856 : : { 0x0531, 0x0556, 1},
2857 : : { 0x10a0, 0x10c5, 1},
2858 : : { 0x10c7, 0x10cd, 6},
2859 : : { 0x1e00, 0x1e94, 2},
2860 : : { 0x1e9e, 0x1efe, 2},
2861 : : { 0x1f08, 0x1f0f, 1},
2862 : : { 0x1f18, 0x1f1d, 1},
2863 : : { 0x1f28, 0x1f2f, 1},
2864 : : { 0x1f38, 0x1f3f, 1},
2865 : : { 0x1f48, 0x1f4d, 1},
2866 : : { 0x1f59, 0x1f5f, 2},
2867 : : { 0x1f68, 0x1f6f, 1},
2868 : : { 0x1fb8, 0x1fbb, 1},
2869 : : { 0x1fc8, 0x1fcb, 1},
2870 : : { 0x1fd8, 0x1fdb, 1},
2871 : : { 0x1fe8, 0x1fec, 1},
2872 : : { 0x1ff8, 0x1ffb, 1},
2873 : : { 0x2102, 0x2107, 5},
2874 : : { 0x210b, 0x210d, 1},
2875 : : { 0x2110, 0x2112, 1},
2876 : : { 0x2115, 0x2119, 4},
2877 : : { 0x211a, 0x211d, 1},
2878 : : { 0x2124, 0x212a, 2},
2879 : : { 0x212b, 0x212d, 1},
2880 : : { 0x2130, 0x2133, 1},
2881 : : { 0x213e, 0x213f, 1},
2882 : : { 0x2145, 0x2183, 62},
2883 : : { 0x2c00, 0x2c2e, 1},
2884 : : { 0x2c60, 0x2c62, 2},
2885 : : { 0x2c63, 0x2c64, 1},
2886 : : { 0x2c67, 0x2c6d, 2},
2887 : : { 0x2c6e, 0x2c70, 1},
2888 : : { 0x2c72, 0x2c75, 3},
2889 : : { 0x2c7e, 0x2c80, 1},
2890 : : { 0x2c82, 0x2ce2, 2},
2891 : : { 0x2ceb, 0x2ced, 2},
2892 : : { 0x2cf2, 0xa640, 31054},
2893 : : { 0xa642, 0xa66c, 2},
2894 : : { 0xa680, 0xa69a, 2},
2895 : : { 0xa722, 0xa72e, 2},
2896 : : { 0xa732, 0xa76e, 2},
2897 : : { 0xa779, 0xa77d, 2},
2898 : : { 0xa77e, 0xa786, 2},
2899 : : { 0xa78b, 0xa78d, 2},
2900 : : { 0xa790, 0xa792, 2},
2901 : : { 0xa796, 0xa7aa, 2},
2902 : : { 0xa7ab, 0xa7ad, 1},
2903 : : { 0xa7b0, 0xa7b1, 1},
2904 : : { 0xff21, 0xff3a, 1},
2905 : : { 0x10400, 0x10427, 1},
2906 : : { 0x118a0, 0x118bf, 1},
2907 : : { 0x1d400, 0x1d419, 1},
2908 : : { 0x1d434, 0x1d44d, 1},
2909 : : { 0x1d468, 0x1d481, 1},
2910 : : { 0x1d49c, 0x1d49e, 2},
2911 : : { 0x1d49f, 0x1d4a5, 3},
2912 : : { 0x1d4a6, 0x1d4a9, 3},
2913 : : { 0x1d4aa, 0x1d4ac, 1},
2914 : : { 0x1d4ae, 0x1d4b5, 1},
2915 : : { 0x1d4d0, 0x1d4e9, 1},
2916 : : { 0x1d504, 0x1d505, 1},
2917 : : { 0x1d507, 0x1d50a, 1},
2918 : : { 0x1d50d, 0x1d514, 1},
2919 : : { 0x1d516, 0x1d51c, 1},
2920 : : { 0x1d538, 0x1d539, 1},
2921 : : { 0x1d53b, 0x1d53e, 1},
2922 : : { 0x1d540, 0x1d544, 1},
2923 : : { 0x1d546, 0x1d54a, 4},
2924 : : { 0x1d54b, 0x1d550, 1},
2925 : : { 0x1d56c, 0x1d585, 1},
2926 : : { 0x1d5a0, 0x1d5b9, 1},
2927 : : { 0x1d5d4, 0x1d5ed, 1},
2928 : : { 0x1d608, 0x1d621, 1},
2929 : : { 0x1d63c, 0x1d655, 1},
2930 : : { 0x1d670, 0x1d689, 1},
2931 : : { 0x1d6a8, 0x1d6c0, 1},
2932 : : { 0x1d6e2, 0x1d6fa, 1},
2933 : : { 0x1d71c, 0x1d734, 1},
2934 : : { 0x1d756, 0x1d76e, 1},
2935 : : { 0x1d790, 0x1d7a8, 1},
2936 : : { 0x1d7ca, 0x1d7ca, 1},
2937 : : };
2938 : :
2939 : : // Return true if C is in RANGES.
2940 : :
2941 : : bool
2942 : 448290 : Lex::is_in_unicode_range(unsigned int c, const Unicode_range* ranges,
2943 : : size_t range_size)
2944 : : {
2945 : 448290 : if (c < 0x100)
2946 : : {
2947 : : // The common case is a small value, and we know that it will be
2948 : : // in the first few entries of the table. Do a linear scan
2949 : : // rather than a binary search.
2950 : 1263166 : for (size_t i = 0; i < range_size; ++i)
2951 : : {
2952 : 1263166 : const Unicode_range* p = &ranges[i];
2953 : 1263166 : if (c <= p->high)
2954 : : {
2955 : 448021 : if (c < p->low)
2956 : : return false;
2957 : 38991 : return (c - p->low) % p->stride == 0;
2958 : : }
2959 : : }
2960 : : return false;
2961 : : }
2962 : : else
2963 : : {
2964 : : size_t lo = 0;
2965 : : size_t hi = range_size;
2966 : 2171 : while (lo < hi)
2967 : : {
2968 : 2135 : size_t mid = lo + (hi - lo) / 2;
2969 : 2135 : const Unicode_range* p = &ranges[mid];
2970 : 2135 : if (c < p->low)
2971 : : hi = mid;
2972 : 633 : else if (c > p->high)
2973 : 400 : lo = mid + 1;
2974 : : else
2975 : 233 : return (c - p->low) % p->stride == 0;
2976 : : }
2977 : : return false;
2978 : : }
2979 : : }
2980 : :
2981 : : // Return whether C is a space character.
2982 : :
2983 : : bool
2984 : 366445 : Lex::is_unicode_space(unsigned int c)
2985 : : {
2986 : 366445 : return Lex::is_in_unicode_range(c, unicode_space,
2987 : 366445 : ARRAY_SIZE(unicode_space));
2988 : : }
2989 : :
2990 : : // Return whether C is a Unicode digit--a Unicode code point
2991 : : // classified as "Digit".
2992 : :
2993 : : bool
2994 : 5 : Lex::is_unicode_digit(unsigned int c)
2995 : : {
2996 : 5 : return Lex::is_in_unicode_range(c, unicode_digits,
2997 : 5 : ARRAY_SIZE(unicode_digits));
2998 : : }
2999 : :
3000 : : // Return whether C is a Unicode letter--a Unicode code point
3001 : : // classified as "Letter".
3002 : :
3003 : : bool
3004 : 39096 : Lex::is_unicode_letter(unsigned int c)
3005 : : {
3006 : 39096 : return Lex::is_in_unicode_range(c, unicode_letters,
3007 : 39096 : ARRAY_SIZE(unicode_letters));
3008 : : }
3009 : :
3010 : : // Return whether C is a Unicode uppercase letter. a Unicode code
3011 : : // point classified as "Letter, uppercase".
3012 : :
3013 : : bool
3014 : 42744 : Lex::is_unicode_uppercase(unsigned int c)
3015 : : {
3016 : 42744 : return Lex::is_in_unicode_range(c, unicode_uppercase_letters,
3017 : 42744 : ARRAY_SIZE(unicode_uppercase_letters));
3018 : : }
3019 : :
3020 : : // Return whether the identifier NAME should be exported. NAME is a
3021 : : // mangled name which includes only ASCII characters.
3022 : :
3023 : : bool
3024 : 0 : Lex::is_exported_mangled_name(const std::string& name)
3025 : : {
3026 : 0 : unsigned char c = name[0];
3027 : 0 : if (c != '.')
3028 : 0 : return c >= 'A' && c <= 'Z';
3029 : : else
3030 : : {
3031 : 0 : const char* p = name.data();
3032 : 0 : size_t len = name.length();
3033 : 0 : if (len < 4 || p[1] != '.' || (p[2] != 'u' && p[2] != 'U'))
3034 : : return false;
3035 : 0 : unsigned int ci = 0;
3036 : 0 : size_t want = (p[2] == 'u' ? 4 : 8);
3037 : 0 : if (len < want + 3)
3038 : : return false;
3039 : 0 : for (size_t i = 3; i < want; ++i)
3040 : : {
3041 : 0 : c = p[i];
3042 : 0 : if (!Lex::is_hex_digit(c))
3043 : : return false;
3044 : 0 : ci <<= 4;
3045 : 0 : ci |= Lex::hex_val(c);
3046 : : }
3047 : 0 : return Lex::is_unicode_uppercase(ci);
3048 : : }
3049 : : }
3050 : :
3051 : : // Return whether the identifier NAME should be exported. NAME is a
3052 : : // an unmangled utf-8 string and may contain non-ASCII characters.
3053 : :
3054 : : bool
3055 : 38723 : Lex::is_exported_name(const std::string& name)
3056 : : {
3057 : 38723 : unsigned int uchar;
3058 : 38723 : if (Lex::fetch_char(name.c_str(), &uchar) != 0)
3059 : 38723 : return Lex::is_unicode_letter(uchar) && Lex::is_unicode_uppercase(uchar);
3060 : : return false;
3061 : : }
3062 : :
3063 : : // Return whether the identifier NAME contains an invalid character.
3064 : : // This is based on how we handle invalid characters in
3065 : : // gather_identifier.
3066 : :
3067 : : bool
3068 : 3879948 : Lex::is_invalid_identifier(const std::string& name)
3069 : : {
3070 : 3879948 : return name.find("$INVALID$") != std::string::npos;
3071 : : }
|