Fix parser errors
This commit is contained in:
82
src/parse.c
82
src/parse.c
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include <ctype.h> // isspace, isdigit
|
#include <ctype.h> // isspace, isdigit
|
||||||
#include <err.h> // err, errx
|
#include <err.h> // err, errx
|
||||||
#include <stdlib.h> // exit, EXIT_SUCCESS, EXIT_FAILURE
|
|
||||||
#include <string.h> // strcmp
|
|
||||||
#include <stdarg.h> // va_list
|
#include <stdarg.h> // va_list
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> // exit, EXIT_SUCCESS, EXIT_FAILURE
|
||||||
|
#include <string.h> // strcmp
|
||||||
|
|
||||||
#include "json_obj.h"
|
#include "json_obj.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#define MALLOC_DIE 201
|
#define MALLOC_DIE 201
|
||||||
#define UNEXPECTED_CHAR 200
|
#define UNEXPECTED_CHAR 200
|
||||||
|
|
||||||
#define ERROR_CONTEXT_LEN 40
|
#define ERROR_CONTEXT_LEN 80
|
||||||
|
|
||||||
char* read_string(FILE* fp);
|
char* read_string(FILE* fp);
|
||||||
obj_t* read_object(FILE* fp);
|
obj_t* read_object(FILE* fp);
|
||||||
@@ -43,32 +43,32 @@ void print_array(struct json_value** arr, int cur_indent, int indent_amount);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Prints parser errors with surrounding context and
|
Prints parser errors with surrounding context and
|
||||||
terminates the program.
|
terminates the program.
|
||||||
|
|
||||||
exit_code - code to exit with
|
exit_code - code to exit with
|
||||||
fp - file causing parser errors
|
fp - file causing parser errors
|
||||||
format - error message format string
|
format - error message format string
|
||||||
... - format string arguments
|
... - format string arguments
|
||||||
*/
|
*/
|
||||||
__attribute__((__noreturn__))
|
__attribute__((__noreturn__)) void err_ctx(int exit_code, FILE* fp, const char* format, ...)
|
||||||
void err_ctx(int exit_code, FILE* fp, const char* format, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
static char context[ERROR_CONTEXT_LEN];
|
static char context[ERROR_CONTEXT_LEN];
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
fputc('\n', stderr);
|
||||||
vfprintf(stderr, format, args);
|
vfprintf(stderr, format, args);
|
||||||
fprintf(stderr, " (at index %zu)\n", ftell(fp));
|
fprintf(stderr, " (at index %zu)\n", ftell(fp));
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if(fseek(fp, -(ERROR_CONTEXT_LEN/2), SEEK_CUR) == 0) {
|
if (fseek(fp, -(ERROR_CONTEXT_LEN / 2), SEEK_CUR) == 0) {
|
||||||
size_t n_read = fread(context, sizeof(char), ERROR_CONTEXT_LEN, fp);
|
size_t n_read = fread(context, sizeof(char), ERROR_CONTEXT_LEN, fp);
|
||||||
|
|
||||||
fprintf(stderr, "\ncontext:\n");
|
fprintf(stderr, "\ncontext:\n");
|
||||||
|
|
||||||
int arrow_offset = 0;
|
int arrow_offset = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < ERROR_CONTEXT_LEN/2 && i < n_read; i++) {
|
for (i = 0; i < ERROR_CONTEXT_LEN / 2 && i < n_read; i++) {
|
||||||
switch (context[i]) {
|
switch (context[i]) {
|
||||||
case '\n':
|
case '\n':
|
||||||
fprintf(stderr, "\\n");
|
fprintf(stderr, "\\n");
|
||||||
@@ -128,6 +128,7 @@ char* read_string(FILE* fp)
|
|||||||
int c;
|
int c;
|
||||||
size_t i = 0, result_size = 16 * sizeof(char);
|
size_t i = 0, result_size = 16 * sizeof(char);
|
||||||
char* result = malloc_or_die(result_size);
|
char* result = malloc_or_die(result_size);
|
||||||
|
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -136,26 +137,29 @@ char* read_string(FILE* fp)
|
|||||||
result = realloc_or_die(result, result_size);
|
result = realloc_or_die(result, result_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = fgetc(fp);
|
||||||
|
|
||||||
if (escaped) {
|
if (escaped) {
|
||||||
result[i++] = 'c';
|
|
||||||
escaped = false;
|
escaped = false;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c = fgetc(fp)) {
|
|
||||||
case '\\':
|
|
||||||
escaped = true;
|
|
||||||
result[i++] = c;
|
result[i++] = c;
|
||||||
break;
|
} else {
|
||||||
default:
|
switch (c) {
|
||||||
result[i++] = c;
|
case '\\':
|
||||||
break;
|
escaped = true;
|
||||||
case '"':
|
result[i++] = c;
|
||||||
result[i++] = '\0';
|
break;
|
||||||
return realloc_or_die(result, i);
|
|
||||||
|
|
||||||
case EOF:
|
case '"':
|
||||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
result[i++] = '\0';
|
||||||
|
return realloc_or_die(result, i);
|
||||||
|
|
||||||
|
case EOF:
|
||||||
|
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||||
|
|
||||||
|
default:
|
||||||
|
result[i++] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,13 +251,13 @@ obj_t* read_object(FILE* fp)
|
|||||||
struct json_value** read_array(FILE* fp)
|
struct json_value** read_array(FILE* fp)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
size_t i = 0, output_size = 16 * sizeof(struct json_value*);
|
size_t i = 0, output_size = 16;
|
||||||
struct json_value** output = malloc_or_die(output_size);
|
struct json_value** output = malloc_or_die(output_size * sizeof(struct json_value*));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (i+1 >= output_size) {
|
if (i + 1 >= output_size) {
|
||||||
output_size *= 2;
|
output_size *= 2;
|
||||||
output = realloc_or_die(output, output_size);
|
output = realloc_or_die(output, output_size * sizeof(struct json_value*));
|
||||||
}
|
}
|
||||||
|
|
||||||
discard_whitespace(fp);
|
discard_whitespace(fp);
|
||||||
@@ -262,6 +266,7 @@ struct json_value** read_array(FILE* fp)
|
|||||||
switch (c) {
|
switch (c) {
|
||||||
case EOF:
|
case EOF:
|
||||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||||
|
break;
|
||||||
|
|
||||||
case ']':
|
case ']':
|
||||||
output[i] = NULL;
|
output[i] = NULL;
|
||||||
@@ -274,10 +279,9 @@ struct json_value** read_array(FILE* fp)
|
|||||||
ungetc(c, fp);
|
ungetc(c, fp);
|
||||||
output[i] = malloc_or_die(sizeof(struct json_value));
|
output[i] = malloc_or_die(sizeof(struct json_value));
|
||||||
*output[i] = parse_json_value(fp);
|
*output[i] = parse_json_value(fp);
|
||||||
|
i++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +325,7 @@ bool read_boolean(FILE* fp)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (strncmp(buf, t, sizeof(t)) == 0) {
|
if (strncmp(buf, t, sizeof(t)) == 0) {
|
||||||
ungetc('e', fp);
|
ungetc(buf[4], fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +333,7 @@ bool read_boolean(FILE* fp)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
fseek(fp, -sizeof(f), SEEK_CUR);
|
fseek(fp, -sizeof(f), SEEK_CUR);
|
||||||
err_ctx(UNEXPECTED_CHAR, fp, "(%s) unexpected symbol", __func__, ftell(fp));
|
err_ctx(UNEXPECTED_CHAR, fp, "(%s) unexpected symbol", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix int overflow
|
// TODO: fix int overflow
|
||||||
@@ -448,18 +452,18 @@ void print_array(struct json_value** arr, int cur_indent, int indent_amount)
|
|||||||
{
|
{
|
||||||
putchar('[');
|
putchar('[');
|
||||||
|
|
||||||
if(arr[0] == NULL) {
|
if (arr[0] == NULL) {
|
||||||
putchar(']');
|
putchar(']');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; arr[i+1] != NULL; i++) {
|
for (i = 0; arr[i + 1] != NULL; i++) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
add_indent(cur_indent);
|
add_indent(cur_indent);
|
||||||
print_json_value(*arr[i], cur_indent + indent_amount, indent_amount);
|
print_json_value(*arr[i], cur_indent + indent_amount, indent_amount);
|
||||||
if( arr[i+1] != NULL )
|
if (arr[i + 1] != NULL)
|
||||||
putchar(',');
|
putchar(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
src/util.c
15
src/util.c
@@ -19,12 +19,19 @@ void* malloc_or_die(size_t size)
|
|||||||
|
|
||||||
void* realloc_or_die(void* ptr, size_t size)
|
void* realloc_or_die(void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
ptr = realloc(ptr, size);
|
void* tmp = realloc(ptr, size);
|
||||||
|
|
||||||
if (ptr == NULL)
|
if (ptr == NULL) {
|
||||||
err(errno, "realloc_or_die failed");
|
if (errno != 0) {
|
||||||
|
free(ptr);
|
||||||
|
err(errno, "realloc_or_die failed");
|
||||||
|
}
|
||||||
|
|
||||||
return ptr;
|
fprintf(stderr, "\nrealloc_or_die returned NULL, ptr: %p size: %zu\n", ptr, size);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* calloc_or_die(size_t nmemb, size_t size)
|
void* calloc_or_die(size_t nmemb, size_t size)
|
||||||
|
|||||||
Reference in New Issue
Block a user