Print this page
new smatch


  76         if (no_lineno)
  77                 pos.line = 123456;
  78 
  79         pos.noexpand = 0;
  80         return pos;
  81 }
  82 
  83 const char *show_special(int val)
  84 {
  85         static char buffer[4];
  86 
  87         buffer[0] = val;
  88         buffer[1] = 0;
  89         if (val >= SPECIAL_BASE)
  90                 strcpy(buffer, (char *) combinations[val - SPECIAL_BASE]);
  91         return buffer;
  92 }
  93 
  94 const char *show_ident(const struct ident *ident)
  95 {
  96         static char buffer[256];



  97         if (!ident)
  98                 return "<noident>";

  99         sprintf(buffer, "%.*s", ident->len, ident->name);
 100         return buffer;
 101 }
 102 
 103 static char *charstr(char *ptr, unsigned char c, unsigned char escape, unsigned char next)
 104 {
 105         if (isprint(c)) {
 106                 if (c == escape || c == '\\')
 107                         *ptr++ = '\\';
 108                 *ptr++ = c;
 109                 return ptr;
 110         }
 111         *ptr++ = '\\';
 112         switch (c) {
 113         case '\n':
 114                 *ptr++ = 'n';
 115                 return ptr;
 116         case '\t':
 117                 *ptr++ = 't';
 118                 return ptr;
 119         }
 120         if (!isdigit(next))
 121                 return ptr + sprintf(ptr, "%o", c);
 122                 
 123         return ptr + sprintf(ptr, "%03o", c);
 124 }
 125 
 126 const char *show_string(const struct string *string)
 127 {
 128         static char buffer[4 * MAX_STRING + 3];
 129         char *ptr;
 130         int i;
 131 
 132         if (!string->length)
 133                 return "<bad_string>";
 134         ptr = buffer;
 135         *ptr++ = '"';
 136         for (i = 0; i < string->length-1; i++) {
 137                 const char *p = string->data + i;
 138                 ptr = charstr(ptr, p[0], '"', p[1]);
 139         }
 140         *ptr++ = '"';
 141         *ptr = '\0';
 142         return buffer;
 143 }
 144 
 145 static const char *show_char(const char *s, size_t len, char prefix, char delim)
 146 {
 147         static char buffer[MAX_STRING + 4];
 148         char *p = buffer;
 149         if (prefix)
 150                 *p++ = prefix;
 151         *p++ = delim;
 152         memcpy(p, s, len);


 432                 int c = stream->buffer[offset++];
 433                 static const char special[256] = {
 434                         ['\t'] = 1, ['\r'] = 1, ['\n'] = 1, ['\\'] = 1
 435                 };
 436                 if (!special[c]) {
 437                         stream->offset = offset;
 438                         stream->pos++;
 439                         return c;
 440                 }
 441         }
 442         return nextchar_slow(stream);
 443 }
 444 
 445 struct token eof_token_entry;
 446 
 447 static struct token *mark_eof(stream_t *stream)
 448 {
 449         struct token *end;
 450 
 451         end = alloc_token(stream);

 452         token_type(end) = TOKEN_STREAMEND;
 453         end->pos.newline = 1;
 454 
 455         eof_token_entry.next = &eof_token_entry;
 456         eof_token_entry.pos.newline = 1;
 457 
 458         end->next =  &eof_token_entry;
 459         *stream->tokenlist = end;
 460         stream->tokenlist = NULL;
 461         return end;
 462 }
 463 
 464 static void add_token(stream_t *stream)
 465 {
 466         struct token *token = stream->token;
 467 
 468         stream->token = NULL;
 469         token->next = NULL;
 470         *stream->tokenlist = token;
 471         stream->tokenlist = &token->next;
 472 }
 473 
 474 static void drop_token(stream_t *stream)
 475 {
 476         stream->newline |= stream->token->pos.newline;
 477         stream->whitespace |= stream->token->pos.whitespace;
 478         stream->token = NULL;
 479 }
 480 
 481 enum {
 482         Letter = 1,
 483         Digit = 2,
 484         Hex = 4,
 485         Exp = 8,
 486         Dot = 16,
 487         ValidSecond = 32,
 488         Quote = 64,
 489 };
 490 
 491 static const long cclass[257] = {
 492         ['0' + 1 ... '7' + 1] = Digit | Hex,    /* \<octal> */
 493         ['8' + 1 ... '9' + 1] = Digit | Hex,
 494         ['A' + 1 ... 'D' + 1] = Letter | Hex,
 495         ['E' + 1] = Letter | Hex | Exp, /* E<exp> */
 496         ['F' + 1] = Letter | Hex,
 497         ['G' + 1 ... 'O' + 1] = Letter,
 498         ['P' + 1] = Letter | Exp,       /* P<exp> */
 499         ['Q' + 1 ... 'Z' + 1] = Letter,
 500         ['a' + 1 ... 'b' + 1] = Letter | Hex, /* \a, \b */
 501         ['c' + 1 ... 'd' + 1] = Letter | Hex,
 502         ['e' + 1] = Letter | Hex | Exp,/* \e, e<exp> */
 503         ['f' + 1] = Letter | Hex,       /* \f */
 504         ['g' + 1 ... 'm' + 1] = Letter,
 505         ['n' + 1] = Letter,     /* \n */
 506         ['o' + 1] = Letter,
 507         ['p' + 1] = Letter | Exp,       /* p<exp> */
 508         ['q' + 1] = Letter,
 509         ['r' + 1] = Letter,     /* \r */
 510         ['s' + 1] = Letter,
 511         ['t' + 1] = Letter,     /* \t */
 512         ['u' + 1] = Letter,
 513         ['v' + 1] = Letter,     /* \v */
 514         ['w' + 1] = Letter,
 515         ['x' + 1] = Letter,     /* \x<hex> */
 516         ['y' + 1 ... 'z' + 1] = Letter,
 517         ['_' + 1] = Letter,
 518         ['.' + 1] = Dot | ValidSecond,
 519         ['=' + 1] = ValidSecond,
 520         ['+' + 1] = ValidSecond,
 521         ['-' + 1] = ValidSecond,
 522         ['>' + 1] = ValidSecond,
 523         ['<' + 1] = ValidSecond,
 524         ['&' + 1] = ValidSecond,
 525         ['|' + 1] = ValidSecond,
 526         ['#' + 1] = ValidSecond,
 527         ['\'' + 1] = Quote,
 528         ['"' + 1] = Quote,
 529 };
 530 
 531 /*
 532  * pp-number:
 533  *      digit
 534  *      . digit
 535  *      pp-number digit
 536  *      pp-number identifier-nodigit
 537  *      pp-number e sign
 538  *      pp-number E sign
 539  *      pp-number p sign
 540  *      pp-number P sign
 541  *      pp-number .
 542  */
 543 static int get_one_number(int c, int next, stream_t *stream)
 544 {
 545         struct token *token;
 546         static char buffer[4095];
 547         char *p = buffer, *buf, *buffer_end = buffer + sizeof (buffer);
 548         int len;
 549 
 550         *p++ = c;
 551         for (;;) {
 552                 long class =  cclass[next + 1];
 553                 if (!(class & (Dot | Digit | Letter)))
 554                         break;
 555                 if (p != buffer_end)
 556                         *p++ = next;
 557                 next = nextchar(stream);
 558                 if (class & Exp) {
 559                         if (next == '-' || next == '+') {
 560                                 if (p != buffer_end)
 561                                         *p++ = next;
 562                                 next = nextchar(stream);
 563                         }
 564                 }
 565         }
 566 
 567         if (p == buffer_end) {
 568                 sparse_error(stream_pos(stream), "number token exceeds %td characters",
 569                       buffer_end - buffer);
 570                 // Pretend we saw just "1".
 571                 buffer[0] = '1';
 572                 p = buffer + 1;
 573         }
 574 
 575         *p++ = 0;
 576         len = p - buffer;
 577         buf = __alloc_bytes(len);
 578         memcpy(buf, buffer, len);
 579 
 580         token = stream->token;
 581         token_type(token) = TOKEN_NUMBER;
 582         token->number = buf;
 583         add_token(stream);
 584 
 585         return next;
 586 }
 587 
 588 static int eat_string(int next, stream_t *stream, enum token_type type)
 589 {
 590         static char buffer[MAX_STRING];
 591         struct string *string;
 592         struct token *token = stream->token;
 593         int len = 0;
 594         int escape;
 595         int want_hex = 0;
 596         char delim = type < TOKEN_STRING ? '\'' : '"';
 597 
 598         for (escape = 0; escape || next != delim; next = nextchar(stream)) {
 599                 if (len < MAX_STRING)
 600                         buffer[len] = next;
 601                 len++;
 602                 if (next == '\n') {
 603                         warning(stream_pos(stream),
 604                                 "Newline in string or character constant");
 605                         if (delim == '\'') /* assume it's lost ' */
 606                                 break;
 607                 }
 608                 if (next == EOF) {
 609                         warning(stream_pos(stream),
 610                                 "End of file in middle of string");
 611                         return next;
 612                 }
 613                 if (!escape) {
 614                         if (want_hex && !(cclass[next + 1] & Hex))
 615                                 warning(stream_pos(stream),
 616                                         "\\x used with no following hex digits");
 617                         want_hex = 0;
 618                         escape = next == '\\';
 619                 } else {
 620                         escape = 0;
 621                         want_hex = next == 'x';
 622                 }
 623         }
 624         if (want_hex)
 625                 warning(stream_pos(stream),




  76         if (no_lineno)
  77                 pos.line = 123456;
  78 
  79         pos.noexpand = 0;
  80         return pos;
  81 }
  82 
  83 const char *show_special(int val)
  84 {
  85         static char buffer[4];
  86 
  87         buffer[0] = val;
  88         buffer[1] = 0;
  89         if (val >= SPECIAL_BASE)
  90                 strcpy(buffer, (char *) combinations[val - SPECIAL_BASE]);
  91         return buffer;
  92 }
  93 
  94 const char *show_ident(const struct ident *ident)
  95 {
  96         static char buff[4][256];
  97         static int n;
  98         char *buffer;
  99 
 100         if (!ident)
 101                 return "<noident>";
 102         buffer = buff[3 & ++n];
 103         sprintf(buffer, "%.*s", ident->len, ident->name);
 104         return buffer;
 105 }
 106 
 107 static char *charstr(char *ptr, unsigned char c, unsigned char escape, unsigned char next)
 108 {
 109         if (isprint(c)) {
 110                 if (c == escape || c == '\\')
 111                         *ptr++ = '\\';
 112                 *ptr++ = c;
 113                 return ptr;
 114         }
 115         *ptr++ = '\\';
 116         switch (c) {
 117         case '\n':
 118                 *ptr++ = 'n';
 119                 return ptr;
 120         case '\t':
 121                 *ptr++ = 't';
 122                 return ptr;
 123         }
 124         if (!isdigit(next))
 125                 return ptr + sprintf(ptr, "%o", c);
 126                 
 127         return ptr + sprintf(ptr, "%03o", c);
 128 }
 129 
 130 const char *show_string(const struct string *string)
 131 {
 132         static char buffer[4 * MAX_STRING + 3];
 133         char *ptr;
 134         int i;
 135 
 136         if (!string || !string->length)
 137                 return "<bad_string>";
 138         ptr = buffer;
 139         *ptr++ = '"';
 140         for (i = 0; i < string->length-1; i++) {
 141                 const char *p = string->data + i;
 142                 ptr = charstr(ptr, p[0], '"', p[1]);
 143         }
 144         *ptr++ = '"';
 145         *ptr = '\0';
 146         return buffer;
 147 }
 148 
 149 static const char *show_char(const char *s, size_t len, char prefix, char delim)
 150 {
 151         static char buffer[MAX_STRING + 4];
 152         char *p = buffer;
 153         if (prefix)
 154                 *p++ = prefix;
 155         *p++ = delim;
 156         memcpy(p, s, len);


 436                 int c = stream->buffer[offset++];
 437                 static const char special[256] = {
 438                         ['\t'] = 1, ['\r'] = 1, ['\n'] = 1, ['\\'] = 1
 439                 };
 440                 if (!special[c]) {
 441                         stream->offset = offset;
 442                         stream->pos++;
 443                         return c;
 444                 }
 445         }
 446         return nextchar_slow(stream);
 447 }
 448 
 449 struct token eof_token_entry;
 450 
 451 static struct token *mark_eof(stream_t *stream)
 452 {
 453         struct token *end;
 454 
 455         end = alloc_token(stream);
 456         eof_token_entry.pos = end->pos;
 457         token_type(end) = TOKEN_STREAMEND;
 458         end->pos.newline = 1;
 459 
 460         eof_token_entry.next = &eof_token_entry;
 461         eof_token_entry.pos.newline = 1;
 462 
 463         end->next =  &eof_token_entry;
 464         *stream->tokenlist = end;
 465         stream->tokenlist = NULL;
 466         return end;
 467 }
 468 
 469 static void add_token(stream_t *stream)
 470 {
 471         struct token *token = stream->token;
 472 
 473         stream->token = NULL;
 474         token->next = NULL;
 475         *stream->tokenlist = token;
 476         stream->tokenlist = &token->next;
 477 }
 478 
 479 static void drop_token(stream_t *stream)
 480 {
 481         stream->newline |= stream->token->pos.newline;
 482         stream->whitespace |= stream->token->pos.whitespace;
 483         stream->token = NULL;
 484 }
 485 
 486 enum {
 487         Letter = 1,
 488         Digit = 2,
 489         Hex = 4,
 490         Exp = 8,
 491         Dot = 16,
 492         ValidSecond = 32,
 493         Quote = 64,
 494 };
 495 
 496 static const char cclass[257] = {
 497         ['0' + 1 ... '9' + 1] = Digit | Hex,

 498         ['A' + 1 ... 'D' + 1] = Letter | Hex,
 499         ['E' + 1] = Letter | Hex | Exp, /* E<exp> */
 500         ['F' + 1] = Letter | Hex,
 501         ['G' + 1 ... 'O' + 1] = Letter,
 502         ['P' + 1] = Letter | Exp,       /* P<exp> */
 503         ['Q' + 1 ... 'Z' + 1] = Letter,
 504         ['a' + 1 ... 'd' + 1] = Letter | Hex,
 505         ['e' + 1] = Letter | Hex | Exp, /* e<exp> */
 506         ['f' + 1] = Letter | Hex,
 507         ['g' + 1 ... 'o' + 1] = Letter,



 508         ['p' + 1] = Letter | Exp,       /* p<exp> */
 509         ['q' + 1 ... 'z' + 1] = Letter,








 510         ['_' + 1] = Letter,
 511         ['.' + 1] = Dot | ValidSecond,
 512         ['=' + 1] = ValidSecond,
 513         ['+' + 1] = ValidSecond,
 514         ['-' + 1] = ValidSecond,
 515         ['>' + 1] = ValidSecond,
 516         ['<' + 1] = ValidSecond,
 517         ['&' + 1] = ValidSecond,
 518         ['|' + 1] = ValidSecond,
 519         ['#' + 1] = ValidSecond,
 520         ['\'' + 1] = Quote,
 521         ['"' + 1] = Quote,
 522 };
 523 
 524 /*
 525  * pp-number:
 526  *      digit
 527  *      . digit
 528  *      pp-number digit
 529  *      pp-number identifier-nodigit
 530  *      pp-number e sign
 531  *      pp-number E sign
 532  *      pp-number p sign
 533  *      pp-number P sign
 534  *      pp-number .
 535  */
 536 static int get_one_number(int c, int next, stream_t *stream)
 537 {
 538         struct token *token;
 539         static char buffer[4095];
 540         char *p = buffer, *buffer_end = buffer + sizeof (buffer);

 541 
 542         *p++ = c;
 543         for (;;) {
 544                 long class =  cclass[next + 1];
 545                 if (!(class & (Dot | Digit | Letter)))
 546                         break;
 547                 if (p != buffer_end)
 548                         *p++ = next;
 549                 next = nextchar(stream);
 550                 if (class & Exp) {
 551                         if (next == '-' || next == '+') {
 552                                 if (p != buffer_end)
 553                                         *p++ = next;
 554                                 next = nextchar(stream);
 555                         }
 556                 }
 557         }
 558 
 559         if (p == buffer_end) {
 560                 sparse_error(stream_pos(stream), "number token exceeds %td characters",
 561                       buffer_end - buffer);
 562                 // Pretend we saw just "1".
 563                 buffer[0] = '1';
 564                 p = buffer + 1;
 565         }
 566 
 567         *p++ = 0;




 568         token = stream->token;
 569         token_type(token) = TOKEN_NUMBER;
 570         token->number = xmemdup(buffer, p - buffer);
 571         add_token(stream);
 572 
 573         return next;
 574 }
 575 
 576 static int eat_string(int next, stream_t *stream, enum token_type type)
 577 {
 578         static char buffer[MAX_STRING];
 579         struct string *string;
 580         struct token *token = stream->token;
 581         int len = 0;
 582         int escape;
 583         int want_hex = 0;
 584         char delim = type < TOKEN_STRING ? '\'' : '"';
 585 
 586         for (escape = 0; escape || next != delim; next = nextchar(stream)) {
 587                 if (len < MAX_STRING)
 588                         buffer[len] = next;
 589                 len++;
 590                 if (next == '\n') {
 591                         warning(stream_pos(stream),
 592                                 "missing terminating %c character", delim);
 593                         /* assume delimiter is lost */
 594                         break;
 595                 }
 596                 if (next == EOF) {
 597                         warning(stream_pos(stream),
 598                                 "End of file in middle of string");
 599                         return next;
 600                 }
 601                 if (!escape) {
 602                         if (want_hex && !(cclass[next + 1] & Hex))
 603                                 warning(stream_pos(stream),
 604                                         "\\x used with no following hex digits");
 605                         want_hex = 0;
 606                         escape = next == '\\';
 607                 } else {
 608                         escape = 0;
 609                         want_hex = next == 'x';
 610                 }
 611         }
 612         if (want_hex)
 613                 warning(stream_pos(stream),