diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-09-04 02:09:26 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-09-04 02:09:26 +0200 |
commit | bee6d0881334d4d043ace36428b7aa3cdd73f23c (patch) | |
tree | 7602cd01ded22ef02fbe5ae7d998db92f4b05e08 | |
parent | f55b2684b01bd402d75bc21231f970546962bee0 (diff) |
Improve interactive usage
-rw-r--r-- | src/lexer.l | 13 | ||||
-rw-r--r-- | src/main.c | 48 | ||||
-rw-r--r-- | src/parser.y | 5 | ||||
-rw-r--r-- | src/pinocchio.h | 5 |
4 files changed, 61 insertions, 10 deletions
diff --git a/src/lexer.l b/src/lexer.l index 3bbfd12..ed8d599 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -1,13 +1,18 @@ %option noinput %option nounput %option noyywrap +%option yylineno %{ #include <err.h> +#include <stdlib.h> #include "parser.h" +#include "pinocchio.h" #define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; + +extern const char *current_file; %} %% @@ -20,7 +25,7 @@ \<=>|⇔ { return EQUIV; } \( { return OPAR; } \) { return CPAR; } -\n { return EOL; } /* Only eat one NL for better interactive usage */ +\n { return EOL; } [a-zA-Z] { yylval.ch = *yytext; return IDENT; @@ -28,7 +33,9 @@ [ \t]+ ; - /* TODO: Swap ‘-’ for name of the input file */ -. { errx(1, "%s:%d: Unrecognized character ‘%c’", "-", yylineno, *yytext); } +. { + user_error("%s:%d: Unrecognized character ‘%c’", + current_file, yylineno, *yytext); +} %% @@ -2,11 +2,13 @@ #include <err.h> #include <langinfo.h> #include <locale.h> +#include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "lexer.h" #include "parser.h" @@ -17,7 +19,10 @@ # define __has_builtin(x) (0) #endif -static bool utf8; +static int rv; +static bool interactive, utf8; + +const char *current_file; static bool eqnsolve(eqn_t *, uint64_t, uint64_t); static int eqnprint(eqn_t *); @@ -41,11 +46,31 @@ main(int argc, char **argv) { setlocale(LC_ALL, ""); utf8 = strcmp(nl_langinfo(CODESET), "UTF-8") == 0; - if (argc > 1) { - if ((yyin = fopen(argv[1], "r")) == NULL) - err(1, "fopen: %s", argv[1]); + interactive = isatty(STDIN_FILENO); + + if (argc == 1) { + current_file = "-"; + for (;;) { + int ret = yyparse(); + if (ret == 0) + break; + rv = EXIT_FAILURE; + } + } else for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-") == 0) + yyin = stdin; + else if ((yyin = fopen(argv[i], "r")) == NULL) { + warn("fopen: %s", argv[1]); + rv = EXIT_FAILURE; + continue; + } + + current_file = argv[1]; + yyparse(); + fclose(yyin); } - return yyparse(); + + return rv; } void @@ -204,3 +229,16 @@ eqnfree(eqn_t *e) } free(e); } + +void +user_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); + if (interactive) + rv = EXIT_FAILURE; + else + exit(EXIT_FAILURE); +} diff --git a/src/parser.y b/src/parser.y index ae31d16..503c2e4 100644 --- a/src/parser.y +++ b/src/parser.y @@ -10,6 +10,8 @@ static ast_t astmerge(int, ast_t, ast_t); static void *xmalloc(size_t); static void yyerror(const char *); + +extern const char *current_file; %} %code requires { @@ -105,6 +107,5 @@ xmalloc(size_t n) void yyerror(const char *s) { - /* TODO: Get filename */ - errx(1, "-:%d: %s\n", yylloc.first_line, s); + user_error("%s:%d: %s", current_file, yylloc.first_line, s); } diff --git a/src/pinocchio.h b/src/pinocchio.h index 0c19def..fb74f3c 100644 --- a/src/pinocchio.h +++ b/src/pinocchio.h @@ -20,5 +20,10 @@ typedef struct { } ast_t; void astprocess(ast_t); +void user_error(const char *, ...) +#if __GNUC__ + __attribute__((format(printf, 1, 2))) +#endif + ; #endif /* !PINOCCIO_H */ |