diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/common.h | 52 | ||||
-rw-r--r-- | src/lexer.l | 35 | ||||
-rw-r--r-- | src/main.c | 21 |
5 files changed, 91 insertions, 19 deletions
diff --git a/Makefile.am b/Makefile.am index 84eb618..3a4e879 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src parser_CFLAGS = $(WARN_CFLAGS) parser_SOURCES = \ src/main.c \ + src/common.h \ src/draw.c \ src/ast.h \ src/ast.c \ diff --git a/configure.ac b/configure.ac index d6c1942..13d9fc4 100644 --- a/configure.ac +++ b/configure.ac @@ -37,6 +37,7 @@ esac # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. +AC_FUNC_STRERROR_R AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..d657a37 --- /dev/null +++ b/src/common.h @@ -0,0 +1,52 @@ +#ifndef CCMMC_HEADER_COMMON_H +#define CCMMC_HEADER_COMMON_H + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// The name of this program, which can be used in error messages +#define name ccmmc_main_name +extern const char *ccmmc_main_name; + +// Calculate the length of an array +#define SIZEOF_ARRAY(x) (sizeof(x)/sizeof(x[0])) + +// Make sure that we have a POSIX-compatible strerror_r function +#ifndef HAVE_STRERROR_R +# error "strerror_r() is not available" +#endif +#ifndef HAVE_DECL_STRERROR_R +# error "strerror_r() is not declared" +#endif +#ifdef STRERROR_R_CHAR_P +# ifdef _GNU_SOURCE +# error "_GNU_SOURCE must not be defined" +# else +# error "This program doesn't work with GNU-specific strerror_r()" +# endif +#endif + +// Make multi-thread error reporting easier +#define ERR_LEN 1024 +#define ERR_DECL char err[ERR_LEN] +#define ERR_MSG get_err_msg(errno, err, ERR_LEN) + +static char *get_err_msg(int num, char *buf, size_t len) { + int errno_save = errno; + if (strerror_r (num, buf, len) != 0) + snprintf (buf, len, "Unknown error %d", num); + errno = errno_save; + return buf; +} + +#define ERR_FATAL_CHECK(result, function) \ + if (result == NULL) { \ + ERR_DECL; \ + fprintf(stderr, "%s: " #function ": %s\n", name, ERR_MSG); \ + exit(1); \ + } + +#endif +// vim: set sw=4 ts=4 sts=4 et: diff --git a/src/lexer.l b/src/lexer.l index 6ed99dc..ed0fc34 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -1,6 +1,11 @@ %option noyywrap %{ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "ast.h" +#include "common.h" #include "libparser_a-parser.h" #include "symbol-table.h" @@ -8,8 +13,6 @@ #include <stdlib.h> #include <string.h> -#define SIZE_OF_ARR(x) (sizeof(x)/sizeof(x[0])) - int line_number = 1; %} @@ -59,21 +62,21 @@ ERROR . {WS} {} {ID} { - int i; + size_t i; char *reserved[] = {"return", "typedef", "if", "else", "int", "float", "for", "void", "while"}; enum yytokentype reserved_token[] = {RETURN, TYPEDEF, IF, ELSE, INT, FLOAT, FOR, VOID, WHILE}; static_assert( - SIZE_OF_ARR(reserved) == SIZE_OF_ARR(reserved_token), + SIZEOF_ARRAY(reserved) == SIZEOF_ARRAY(reserved_token), "Reserved words array and reserved tokens array " "must have the same size"); - for (i = 0; i < SIZE_OF_ARR(reserved); i++) + for (i = 0; i < SIZEOF_ARRAY(reserved); i++) if (strcmp(yytext, reserved[i]) == 0) return reserved_token[i]; - if (i == SIZE_OF_ARR(reserved)) { - CcmmcSymbol * ptr; + if (i == SIZEOF_ARRAY(reserved)) { + CcmmcSymbol *ptr; ptr = ccmmc_symbol_table_lookup(yytext); if (ptr == NULL) ccmmc_symbol_table_insert_id(yytext, line_number); @@ -81,15 +84,13 @@ ERROR . ptr->counter++; } yylval.lexeme = strdup(yytext); - if (yylval.lexeme == NULL) { - fputs("strdup() failed\n", stderr); - exit(1); - } + ERR_FATAL_CHECK(yylval.lexeme, strdup); return ID; } {CONST_INT} { CON_Type *p; - p = (CON_Type *)malloc(sizeof(CON_Type)); + p = malloc(sizeof(CON_Type)); + ERR_FATAL_CHECK(p, malloc); p->const_type = INTEGERC; p->const_u.intval = atoi(yytext); yylval.const1 = p; @@ -97,7 +98,8 @@ ERROR . } {CONST_FLOAT} { CON_Type *p; - p = (CON_Type *)malloc(sizeof(CON_Type)); + p = malloc(sizeof(CON_Type)); + ERR_FATAL_CHECK(p, malloc); p->const_type = FLOATC; p->const_u.fval = atof(yytext); yylval.const1 = p; @@ -105,15 +107,16 @@ ERROR . } {CONST_STRING} { CON_Type *p; - p = (CON_Type *)malloc(sizeof(CON_Type)); + p = malloc(sizeof(CON_Type)); + ERR_FATAL_CHECK(p, malloc); p->const_type = STRINGC; p->const_u.sc = strdup(yytext); + ERR_FATAL_CHECK(p->const_u.sc, strdup); yylval.const1 = p; return CONST; } {COMMENT} { - int i; - for (i = 0; yytext[i]; i++) + for (size_t i = 0; yytext[i] != '\0'; i++) if (yytext[i] == '\n') line_number++; } @@ -3,25 +3,40 @@ #endif #include "ast.h" +#include "common.h" #include "libparser_a-parser.h" +#include <errno.h> +#include <locale.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> + extern FILE *yyin; extern AST_NODE *prog; +const char *ccmmc_main_name; + int main (int argc, char **argv) { + ERR_DECL; + setlocale (LC_ALL, ""); + name = strrchr (argv[0], '/'); + name = name == NULL ? name : name + 1; + if (argc != 2) { - fputs("usage: parser [source file]\n", stderr); + fprintf(stderr, "Usage: %s SOURCE\n", name); exit(1); } - yyin = fopen(argv[1],"r"); + + const char *filename = argv[1]; + yyin = fopen(filename, "r"); if (yyin == NULL) { - fputs("Error opening source file.\n", stderr); + fprintf(stderr, "%s: %s: %s\n", name, filename, ERR_MSG); exit(1); } + yyparse(); printGV(prog, NULL); return 0; |