diff options
Diffstat (limited to 'giscanner/scannerlexer.l')
-rw-r--r-- | giscanner/scannerlexer.l | 202 |
1 files changed, 157 insertions, 45 deletions
diff --git a/giscanner/scannerlexer.l b/giscanner/scannerlexer.l index a783ec06..42f85eab 100644 --- a/giscanner/scannerlexer.l +++ b/giscanner/scannerlexer.l @@ -31,11 +31,17 @@ %{ #include <ctype.h> #include <stdio.h> +#ifndef _WIN32 +#include <limits.h> +#endif #include <glib.h> #include "sourcescanner.h" #include "scannerparser.h" -#include "grealpath.h" + +#ifdef USE_WINDOWS +#include <windows.h> +#endif int lineno; char linebuf[2000]; @@ -51,6 +57,7 @@ static void parse_trigraph (GISourceScanner *scanner); static void process_linemarks (GISourceScanner *scanner); static int check_identifier (GISourceScanner *scanner, const char *); static int parse_ignored_macro (void); +static void print_error (GISourceScanner *scanner); %} %option nounput @@ -71,6 +78,7 @@ stringtext ([^\\\"])|(\\.) ++lineno; } "\\\n" { ++lineno; } + [\t\f\v\r ]+ { /* Ignore whitespace. */ } "/*" { parse_comment(scanner); } @@ -79,6 +87,14 @@ stringtext ([^\\\"])|(\\.) "#define "[a-zA-Z_][a-zA-Z_0-9]*"(" { yyless (yyleng - 1); return FUNCTION_MACRO; } "#define "[a-zA-Z_][a-zA-Z_0-9]* { return OBJECT_MACRO; } +"#ifdef"[\t ]+"__GI_SCANNER__"[\t ]?.*"\n" { return IFDEF_GI_SCANNER; } +"#ifndef"[\t ]+"__GI_SCANNER__"[\t ]?.*"\n" { return IFNDEF_GI_SCANNER; } +"#ifndef ".*"\n" { return IFNDEF_COND; } +"#ifdef ".*"\n" { return IFDEF_COND; } +"#if ".*"\n" { return IF_COND; } +"#elif ".*"\n" { return ELIF_COND; } +"#else".*"\n" { return ELSE_COND; } +"#endif".*"\n" { return ENDIF_COND; } "#pragma ".*"\n" { /* Ignore pragma. */ } "# "[0-9]+" ".*"\n" { process_linemarks(scanner); } @@ -134,21 +150,32 @@ stringtext ([^\\\"])|(\\.) "," { return ','; } "->" { return ARROW; } +"__asm"[\t\f\v\r ]+"volatile" { if (!parse_ignored_macro()) REJECT; } +"__asm__"[\t\f\v\r ]+"volatile" { if (!parse_ignored_macro()) REJECT; } "__asm" { if (!parse_ignored_macro()) REJECT; } "__asm__" { if (!parse_ignored_macro()) REJECT; } "__attribute__" { if (!parse_ignored_macro()) REJECT; } "__attribute" { if (!parse_ignored_macro()) REJECT; } "__const" { return CONST; } "__extension__" { return EXTENSION; } +"__inline__" { return INLINE; } "__inline" { return INLINE; } "__nonnull" { if (!parse_ignored_macro()) REJECT; } "__signed__" { return SIGNED; } "__restrict" { return RESTRICT; } "__typeof" { if (!parse_ignored_macro()) REJECT; } +"__volatile" { return VOLATILE; } +"__volatile__" { return VOLATILE; } "_Bool" { return BOOL; } "G_GINT64_CONSTANT" { return INTL_CONST; } "G_GUINT64_CONSTANT" { return INTUL_CONST; } + +"TRUE" { return BOOLEAN; } +"FALSE" { return BOOLEAN; } +"true" { return BOOLEAN; } +"false" { return BOOLEAN; } + [a-zA-Z_][a-zA-Z_0-9]* { if (scanner->macro_scan) return check_identifier(scanner, yytext); else REJECT; } "asm" { if (!parse_ignored_macro()) REJECT; } @@ -170,6 +197,10 @@ stringtext ([^\\\"])|(\\.) "if" { return IF; } "inline" { return INLINE; } "int" { return INT; } +"__uint128_t" { return INT; } +"__int128_t" { return INT; } +"__uint128" { return INT; } +"__int128" { return INT; } "long" { return LONG; } "register" { return REGISTER; } "restrict" { return RESTRICT; } @@ -202,7 +233,7 @@ stringtext ([^\\\"])|(\\.) "\""{stringtext}*"\"" { return STRING; } "L\""{stringtext}*"\"" { return STRING; } -. { if (yytext[0]) fprintf(stderr, "%s:%d: unexpected character `%c'\n", scanner->current_filename, lineno, yytext[0]); } +. { print_error(scanner); } %% @@ -212,54 +243,70 @@ yywrap (void) return 1; } - static void parse_comment (GISourceScanner *scanner) { - GString *string = NULL; int c1, c2; + GString *string = NULL; GISourceComment *comment; int comment_lineno; int skip = FALSE; - if (!g_list_find_custom (scanner->filenames, - scanner->current_filename, - (GCompareFunc)g_strcmp0)) { - skip = TRUE; - } else { - string = g_string_new ("/*"); - } - c1 = input(); c2 = input(); - comment_lineno = lineno; + if (c2 != EOF && (c1 == '*' && c2 != '*' && c2 != '/')) { + /* + * Store GTK-Doc comment blocks, + * starts with one '/' followed by exactly two '*' and not followed by a '/' + */ + if (!g_hash_table_contains (scanner->files, scanner->current_file)) { + skip = TRUE; + } else { + string = g_string_new (yytext); + } - while (c2 != EOF && !(c1 == '*' && c2 == '/')) - { - if (!skip) - g_string_append_c (string, c1); + comment_lineno = lineno; - if (c1 == '\n') - lineno++; + while (c2 != EOF && !(c1 == '*' && c2 == '/')) + { + if (!skip) + g_string_append_c (string, c1); - c1 = c2; - c2 = input(); - } + if (c1 == '\n') + lineno++; - if (skip) { - return; - } + c1 = c2; + c2 = input(); + } + + if (skip) { + return; + } - g_string_append (string, "*/"); + g_string_append (string, "*/"); - comment = g_slice_new (GISourceComment); - comment->comment = g_string_free (string, FALSE); - comment->line = comment_lineno; - comment->filename = g_strdup(scanner->current_filename); + comment = g_slice_new (GISourceComment); + comment->comment = g_string_free (string, FALSE); + comment->line = comment_lineno; + comment->filename = g_file_get_parse_name (scanner->current_file); - scanner->comments = g_slist_prepend (scanner->comments, - comment); + gi_source_scanner_take_comment (scanner, comment); + } else { + /* + * Ignore all other comment blocks + */ + while (c2 != EOF && !(c1 == '*' && c2 == '/')) + { + if (c1 == '\n') + lineno++; + + c1 = c2; + c2 = input(); + } + + return; + } } static int @@ -280,6 +327,58 @@ check_identifier (GISourceScanner *scanner, return IDENTIFIER; } +/* taken from glib/gfileutils.c */ +#if defined(MAXPATHLEN) +#define G_PATH_LENGTH MAXPATHLEN +#elif defined(PATH_MAX) +#define G_PATH_LENGTH PATH_MAX +#elif defined(_PC_PATH_MAX) +#define G_PATH_LENGTH sysconf(_PC_PATH_MAX) +#else +#define G_PATH_LENGTH 2048 +#endif + +static inline char * +_realpath (const char *path) +{ +#ifndef _WIN32 + char buffer[G_PATH_LENGTH]; + + return realpath (path, buffer) ? g_strdup (buffer) : NULL; +#else + /* We don't want to include <windows.h> as it clashes horribly + * with token names from scannerparser.h. So just declare + * GetFullPathNameA() here unless we already defined it, like + * in giscanner.c. + */ +#ifndef USE_WINDOWS + extern __stdcall GetFullPathNameA(const char*, int, char*, char**); +#endif + char *buffer; + char dummy; + int rc, len; + + rc = GetFullPathNameA (path, 1, &dummy, NULL); + if (rc == 0) + { + /* Weird failure, so just return the input path as such */ + return g_strdup (path); + } + + len = rc + 1; + buffer = g_malloc (len); + + rc = GetFullPathNameA (path, len, buffer, NULL); + if (rc == 0 || rc > len) + { + /* Weird failure again */ + g_free (buffer); + return g_strdup (path); + } + return buffer; +#endif +} + /* * # linenum "filename" flags * See http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html @@ -288,21 +387,24 @@ check_identifier (GISourceScanner *scanner, static void process_linemarks (GISourceScanner *scanner) { - char filename[1025]; - char *compress; + char escaped_filename[1025]; + char *filename; char *real; - sscanf(yytext, "# %d \"%1024[^\"]\"", &lineno, filename); - - compress = g_strcompress (filename); - real = g_realpath (filename); - if (real) { - g_free (scanner->current_filename); - scanner->current_filename = real; - } else { - g_free (real); - } - g_free (compress); + sscanf(yytext, "# %d \"%1024[^\"]\"", &lineno, escaped_filename); + filename = g_strcompress (escaped_filename); + + real = _realpath (filename); + if (real) + { + g_free (filename); + filename = real; + } + + if (scanner->current_file) + g_object_unref (scanner->current_file); + scanner->current_file = g_file_new_for_path (filename); + g_free (filename); } /* @@ -372,3 +474,13 @@ parse_trigraph (GISourceScanner *scanner) } g_strfreev (items); } + +static void +print_error (GISourceScanner *scanner) +{ + if (yytext[0]) { + char *filename = g_file_get_parse_name (scanner->current_file); + fprintf(stderr, "%s:%d: unexpected character `%c'\n", filename, lineno, yytext[0]); + g_free (filename); + } +} |