Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular error printing #50

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion src/bar_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void BarToken_destroy_at(BarToken* token) {
return;
}

int BarToken_print(BarToken* token, FILE* stream) {
int BarToken_print(const BarToken* token, FILE* stream) {

if(token == NULL || token->content == NULL || stream == NULL) {
return ERROR_CODE_INVALID_ARGUMENT;
Expand Down
2 changes: 1 addition & 1 deletion src/bar_token.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void BarToken_set_content(BarToken* token, char* content, size_t content_length)

void BarToken_destroy_at(BarToken* token);

int BarToken_print(BarToken* token, FILE* stream);
int BarToken_print(const BarToken* token, FILE* stream);

// --------
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/error_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ enum ErrorCodes {

ERROR_CODE_CONFIG_WRITE_AFTER_READ,

ERROR_CODE_NOTE_COMPILER_ERROR,

};

// --------
Expand Down
56 changes: 56 additions & 0 deletions src/error_messages.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <errno.h>
#include <string.h>

#include "error_codes.h"
#include "error_messages.h"

// --------

const char* get_error_message(int error_code) {

switch(error_code) {

case ERROR_CODE_UNKNOWN_SYSTEM_ERROR:
return "Unknown system error";

case ERROR_CODE_INTEGER_OVERFLOW:
return strerror(ERANGE);

case ERROR_CODE_MALLOC_FAILURE:
return strerror(ENOMEM);

case ERROR_CODE_OPEN_FAILURE:
return "Cannot open";

case ERROR_CODE_SDL_ERROR:
return "SDL error";

case ERROR_CODE_SUCCESS:
return "Success";

case ERROR_CODE_INVALID_STATE:
return "Encountered invalid state";

case ERROR_CODE_INVALID_ARGUMENT:
return strerror(EINVAL);

case ERROR_CODE_UNEXPECTED_EOF:
return "Unexpected end of file";

case ERROR_CODE_UNEXPECTED_CHARACTER:
return "Unexpected character";

case ERROR_CODE_UNEXPECTED_FOLLOW_UP_CHARACTER:
return "Unexpected follow-up character";

case ERROR_CODE_BAR_TOO_SHORT:
return "Bar too short";

case ERROR_CODE_BAR_TOO_LONG:
return "Bar too long";

default:
return "Unknown error";
}
}

9 changes: 9 additions & 0 deletions src/error_messages.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef ERROR_MESSAGES_H
#define ERROR_MESSAGES_H
// --------

const char* get_error_message(int error_code);

// --------
#endif

2 changes: 1 addition & 1 deletion src/instrument.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ int Instrument_add_notes_for_bar(Instrument* instrument, NoteProvider note_provi
}

if(status != 0) {
return status;
return ERROR_CODE_NOTE_COMPILER_ERROR;
}

if(!instrument_done) {
Expand Down
68 changes: 60 additions & 8 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <string.h>

#include "error_codes.h"
#include "error_messages.h"
#include "config.h"
#include "instrument.h"
#include "interpreter.h"
Expand All @@ -17,9 +18,11 @@
static bool destroy_token(Token* token);
static bool destroy_bar_token(BarToken* bar);

static int play_track_token(Token* track);
static int play_track_token(Interpreter* interpreter, Token* track);

static int play_bar_token(Player* player, Instrument* instrument, BarToken* bar);
static int play_bar_token(Interpreter* interpreter, Player* player, Instrument* instrument, BarToken* bar);

static int print_bar_length_error(const Interpreter* interpreter, FILE* stream, const BarToken* bar, int error_code);

// --------

Expand All @@ -32,7 +35,7 @@ static bool destroy_bar_token(BarToken* bar) {
BarToken_destroy_at(bar);
return true;
}
static int play_track_token(Token* track) {
static int play_track_token(Interpreter* interpreter, Token* track) {

if(track == NULL || track->type != TOKEN_TRACK) {
return ERROR_CODE_INVALID_ARGUMENT;
Expand Down Expand Up @@ -69,7 +72,7 @@ static int play_track_token(Token* track) {
}

while(status == 0 && destroy_bar_token(&bar) && !lexer.super.finished && (status = TrackLexer_get_next_bar(&lexer, &bar)) == 0) {
status = play_bar_token(&player, &instrument, &bar);
status = play_bar_token(interpreter, &player, &instrument, &bar);
}

if(status == 0) {
Expand All @@ -84,7 +87,7 @@ static int play_track_token(Token* track) {
return status;
}

static int play_bar_token(Player* player, Instrument* instrument, BarToken* bar) {
static int play_bar_token(Interpreter* interpreter, Player* player, Instrument* instrument, BarToken* bar) {

NoteCompiler compiler;
int status;
Expand All @@ -95,10 +98,35 @@ static int play_bar_token(Player* player, Instrument* instrument, BarToken* bar)
return ERROR_CODE_INVALID_ARGUMENT;
}

NoteCompiler_init_at(&compiler, (char*) (bar->content), bar->content_length);
status = NoteCompiler_init_at(&compiler, bar, interpreter->filename);
if(status != 0) {
return status;
}

status = Instrument_add_notes_for_bar(instrument, &NoteCompiler_get_next_note, &compiler);

if(status != 0) {

switch(status) {

case ERROR_CODE_NOTE_COMPILER_ERROR:

if(NoteCompiler_print_error(&compiler, stderr) == 0) {
interpreter->printed_err_msg = true;
}
break;

case ERROR_CODE_BAR_TOO_SHORT:
case ERROR_CODE_BAR_TOO_LONG:

if(print_bar_length_error(interpreter, stderr, bar, status) == 0) {
interpreter->printed_err_msg = true;
}
break;

default:
break;
}
return status;
}

Expand All @@ -110,6 +138,29 @@ static int play_bar_token(Player* player, Instrument* instrument, BarToken* bar)
return Player_play_bar(player);
}

static int print_bar_length_error(const Interpreter* interpreter, FILE* stream, const BarToken* bar, int error_code) {

int status = 0;

if(interpreter == NULL || stream == NULL || bar == NULL) {
return ERROR_CODE_INVALID_ARGUMENT;
}

if(bar->content == NULL) {
return ERROR_CODE_INVALID_STATE;
}

fprintf(stream, "%s:%u:%u: ", interpreter->filename, bar->line, bar->col);

fputs(get_error_message(error_code), stream);
fputs(":\n", stream);

status = BarToken_print(bar, stream);
fputs("\n", stream);

return status;
}

// --------

void Interpreter_init_at(Interpreter* interpreter) {
Expand All @@ -119,6 +170,7 @@ void Interpreter_init_at(Interpreter* interpreter) {
interpreter->error_state = INTERPRETER_ERROR_STATE_UNKNOWN_ERROR;
interpreter->finished = false;
interpreter->error = false;
interpreter->printed_err_msg = false;

return;
}
Expand Down Expand Up @@ -194,7 +246,7 @@ int Interpreter_interpret(Interpreter* interpreter, FILE* stream) {

case TOKEN_TRACK:

if((status = play_track_token(&token)) != 0) {
if((status = play_track_token(interpreter, &token)) != 0) {
interpreter->finished = true;
interpreter->error = true;
interpreter->error_state = INTERPRETER_ERROR_STATE_INTERNAL_ERROR;
Expand Down Expand Up @@ -223,7 +275,7 @@ int Interpreter_interpret(Interpreter* interpreter, FILE* stream) {
status = status != 0? status: ERROR_CODE_UNKNOWN_ERROR;
}

if(interpreter->error) {
if(interpreter->error && !interpreter->printed_err_msg) {

switch(interpreter->error_state) {

Expand Down
3 changes: 2 additions & 1 deletion src/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ typedef enum InterpreterState {

typedef enum InterpreterErrorState {
INTERPRETER_ERROR_STATE_UNKNOWN_ERROR = 0,
INTERPRETER_ERROR_STATE_UNEXPECTED_TOKEN,
INTERPRETER_ERROR_STATE_INTERNAL_ERROR,
INTERPRETER_ERROR_STATE_UNEXPECTED_TOKEN,
NUM_INTERPRETER_ERROR_STATES,
} InterpreterErrorState;

Expand All @@ -35,6 +35,7 @@ struct Interpreter {
InterpreterErrorState error_state;
bool finished;
bool error;
bool printed_err_msg;
};

// --------
Expand Down
66 changes: 56 additions & 10 deletions src/note_compiler.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <stdlib.h>

#include <string.h>

#include "error_codes.h"
#include "error_messages.h"
#include "note_conversion.h"
#include "note_compiler.h"

Expand All @@ -23,24 +23,24 @@ static int finish_note(NoteCompiler* compiler, Note* note);

static int advance(NoteCompiler* compiler) {

if(compiler->position >= compiler->bar_length) {
if(compiler->position >= compiler->bar->content_length) {
compiler->finished = true;
return END_OF_BAR;
}

compiler->symbol = (compiler->bar)[compiler->position];
compiler->symbol = (compiler->bar->content)[compiler->position];
(compiler->position)++;

return (char) (compiler->symbol);
}

static int peek(NoteCompiler* compiler) {

if(compiler->position >= compiler->bar_length) {
if(compiler->position >= compiler->bar->content_length) {
return END_OF_BAR;
}

return (char) ((compiler->bar)[compiler->position]);
return (char) ((compiler->bar->content)[compiler->position]);
}

static int finish_note(NoteCompiler* compiler, Note* note) {
Expand Down Expand Up @@ -145,18 +145,21 @@ static int finish_note(NoteCompiler* compiler, Note* note) {

// --------

int NoteCompiler_init_at(NoteCompiler* compiler, char* bar, size_t length) {
int NoteCompiler_init_at(NoteCompiler* compiler, BarToken* bar, char* filename) {

if(compiler == NULL || bar == NULL || bar->content == NULL || bar->content_length == 0) {
return ERROR_CODE_INVALID_ARGUMENT;
}

compiler->bar = bar;
compiler->state = NOTE_COMPILER_STATE_EXPECTING_NOTE;
compiler->bar_length = 0;
compiler->position = 0;
compiler->state = NOTE_COMPILER_STATE_EXPECTING_NOTE;
compiler->error_state = NOTE_COMPILER_ERROR_STATE_UNKNOWN_ERROR;
compiler->symbol = '\0';
compiler->finished = false;
compiler->error = false;

compiler->bar = bar;
compiler->bar_length = length;
compiler->filename = filename == NULL? "": filename;

return 0;
}
Expand Down Expand Up @@ -210,6 +213,7 @@ int NoteCompiler_get_next_note(void* compiler, Note* note, bool* finished) {
default:
comp->error = true;
comp->finished = true;
comp->error_state = NOTE_COMPILER_ERROR_STATE_UNEXPECTED_CHARACTER;
return ERROR_CODE_UNEXPECTED_CHARACTER;
}
default:
Expand All @@ -226,3 +230,45 @@ int NoteCompiler_get_next_note(void* compiler, Note* note, bool* finished) {
return 0;
}

int NoteCompiler_print_error(const NoteCompiler* compiler, FILE* stream) {

int status = 0;

if(compiler == NULL || !(compiler->error)) {
return ERROR_CODE_INVALID_ARGUMENT;
}

if(compiler->bar == NULL || compiler->bar->content == NULL) {
return ERROR_CODE_INVALID_STATE;
}

fprintf(stream, "%s:%u:%u: ", compiler->filename, compiler->bar->line, compiler->bar->col);

switch(compiler->error_state) {

case NOTE_COMPILER_ERROR_STATE_UNEXPECTED_CHARACTER:

fputs(get_error_message(ERROR_CODE_UNEXPECTED_CHARACTER), stream);
fputs(":\n", stream);

BarToken_print(compiler->bar, stream);

if(fprintf(stream, "\n%*s^", (int) (compiler->position - 1), " ") < 0) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're likely gonna use the exact same trick inside the token module; might be worth extracting the string formatting into a helper method.

return ERROR_CODE_UNKNOWN_SYSTEM_ERROR;
}

break;

default:

fputs("Unknown error when reading bar:\n", stream);
BarToken_print(compiler->bar, stream);

break;
}

fputs("\n", stream);

return status;
}

Loading