summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--configure.ac1
-rw-r--r--src/common.h52
-rw-r--r--src/lexer.l35
-rw-r--r--src/main.c21
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++;
}
diff --git a/src/main.c b/src/main.c
index fde8aef..2370f5a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;