| /* Utility functions for scan-decls and fix-header programs. |
| Copyright (C) 1993, 1994, 1998, 2002, 2003, 2007, 2008 |
| Free Software Foundation, Inc. |
| |
| This program is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by the |
| Free Software Foundation; either version 3, or (at your option) any |
| later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "bconfig.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tm.h" |
| #include "scan.h" |
| |
| int lineno = 1; |
| int source_lineno = 1; |
| sstring source_filename; |
| |
| void |
| make_sstring_space (sstring *str, int count) |
| { |
| int cur_pos = str->ptr - str->base; |
| int cur_size = str->limit - str->base; |
| int new_size = cur_pos + count + 100; |
| |
| if (new_size <= cur_size) |
| return; |
| |
| str->base = (char *) xrealloc (str->base, new_size); |
| str->ptr = str->base + cur_size; |
| str->limit = str->base + new_size; |
| } |
| |
| void |
| sstring_append (sstring *dst, sstring *src) |
| { |
| char *d, *s; |
| int count = SSTRING_LENGTH (src); |
| |
| MAKE_SSTRING_SPACE (dst, count + 1); |
| d = dst->ptr; |
| s = src->base; |
| while (--count >= 0) *d++ = *s++; |
| dst->ptr = d; |
| *d = 0; |
| } |
| |
| int |
| scan_ident (FILE *fp, sstring *s, int c) |
| { |
| s->ptr = s->base; |
| if (ISIDST (c)) |
| { |
| for (;;) |
| { |
| SSTRING_PUT (s, c); |
| c = getc (fp); |
| if (c == EOF || ! ISIDNUM (c)) |
| break; |
| } |
| } |
| MAKE_SSTRING_SPACE (s, 1); |
| *s->ptr = 0; |
| return c; |
| } |
| |
| int |
| scan_string (FILE *fp, sstring *s, int init) |
| { |
| int c; |
| |
| for (;;) |
| { |
| c = getc (fp); |
| if (c == EOF || c == '\n') |
| break; |
| if (c == init) |
| { |
| c = getc (fp); |
| break; |
| } |
| if (c == '\\') |
| { |
| c = getc (fp); |
| if (c == EOF) |
| break; |
| if (c == '\n') |
| continue; |
| } |
| SSTRING_PUT (s, c); |
| } |
| MAKE_SSTRING_SPACE (s, 1); |
| *s->ptr = 0; |
| return c; |
| } |
| |
| /* Skip horizontal white spaces (spaces, tabs, and C-style comments). */ |
| |
| int |
| skip_spaces (FILE *fp, int c) |
| { |
| for (;;) |
| { |
| if (c == ' ' || c == '\t') |
| c = getc (fp); |
| else if (c == '/') |
| { |
| c = getc (fp); |
| if (c != '*') |
| { |
| ungetc (c, fp); |
| return '/'; |
| } |
| c = getc (fp); |
| for (;;) |
| { |
| if (c == EOF) |
| return EOF; |
| else if (c != '*') |
| { |
| if (c == '\n') |
| source_lineno++, lineno++; |
| c = getc (fp); |
| } |
| else if ((c = getc (fp)) == '/') |
| return getc (fp); |
| } |
| } |
| else |
| break; |
| } |
| return c; |
| } |
| |
| int |
| read_upto (FILE *fp, sstring *str, int delim) |
| { |
| int ch; |
| |
| for (;;) |
| { |
| ch = getc (fp); |
| if (ch == EOF || ch == delim) |
| break; |
| SSTRING_PUT (str, ch); |
| } |
| MAKE_SSTRING_SPACE (str, 1); |
| *str->ptr = 0; |
| return ch; |
| } |
| |
| int |
| get_token (FILE *fp, sstring *s) |
| { |
| int c; |
| |
| s->ptr = s->base; |
| retry: |
| c = ' '; |
| c = skip_spaces (fp, c); |
| if (c == '\n') |
| { |
| source_lineno++; |
| lineno++; |
| goto retry; |
| } |
| if (c == '#') |
| { |
| c = get_token (fp, s); |
| if (c == INT_TOKEN) |
| { |
| source_lineno = atoi (s->base) - 1; /* '\n' will add 1 */ |
| get_token (fp, &source_filename); |
| } |
| for (;;) |
| { |
| c = getc (fp); |
| if (c == EOF) |
| return EOF; |
| if (c == '\n') |
| { |
| source_lineno++; |
| lineno++; |
| goto retry; |
| } |
| } |
| } |
| if (c == EOF) |
| return EOF; |
| if (ISDIGIT (c)) |
| { |
| do |
| { |
| SSTRING_PUT (s, c); |
| c = getc (fp); |
| } while (c != EOF && ISDIGIT (c)); |
| ungetc (c, fp); |
| c = INT_TOKEN; |
| goto done; |
| } |
| if (ISIDST (c)) |
| { |
| c = scan_ident (fp, s, c); |
| ungetc (c, fp); |
| return IDENTIFIER_TOKEN; |
| } |
| if (c == '\'' || c == '"') |
| { |
| c = scan_string (fp, s, c); |
| ungetc (c, fp); |
| return c == '\'' ? CHAR_TOKEN : STRING_TOKEN; |
| } |
| SSTRING_PUT (s, c); |
| done: |
| MAKE_SSTRING_SPACE (s, 1); |
| *s->ptr = 0; |
| return c; |
| } |
| |
| unsigned int |
| hashstr (const char *str, unsigned int len) |
| { |
| unsigned int n = len; |
| unsigned int r = 0; |
| const unsigned char *s = (const unsigned char *) str; |
| |
| do |
| r = r * 67 + (*s++ - 113); |
| while (--n); |
| return r + len; |
| } |