diff --git a/src/alu.c b/src/alu.c index 9c8e5ae..7b7c6f5 100644 --- a/src/alu.c +++ b/src/alu.c @@ -379,35 +379,35 @@ static void parse_quoted_character(char closing_quote) { intval_t value; - // FIXME - this will fail with backslash escaping! +// this can be used later on for real strings as well { + DYNABUF_CLEAR(GlobalDynaBuf); + if (Input_quoted_to_dynabuf(closing_quote)) + goto fail; // unterminated or escaping error - // read character to parse - make sure not at end of statement - if (GetQuotedByte() == CHAR_EOS) { - alu_state = STATE_ERROR; - return; - } - - // on empty string, complain - if (GotByte == closing_quote) { + // eat closing quote + GetByte(); + // now convert to unescaped version + if (Input_unescape_dynabuf()) + goto fail; // escaping error +// } + // too short? + if (GlobalDynaBuf->size == 0) { Throw_error(exception_missing_string); - alu_state = STATE_ERROR; - return; + goto fail; } + // too long? + if (GlobalDynaBuf->size != 1) + Throw_error("There's more than one character."); // parse character - value = (intval_t) encoding_encode_char(GotByte); - // Read closing quote (hopefully) - if (GetQuotedByte() == closing_quote) { - GetByte(); // if length == 1, proceed with next byte - } else { - if (GotByte) { - // if longer than one character - Throw_error("There's more than one character."); - alu_state = STATE_ERROR; - } - } + value = (intval_t) encoding_encode_char(GLOBALDYNABUF_CURRENT[0]); PUSH_INT_ARG(value, NUMBER_IS_DEFINED | NUMBER_FITS_BYTE, 0); // Now GotByte = char following closing quote (or CHAR_EOS on error) + return; + +fail: + PUSH_INT_ARG(0, NUMBER_IS_DEFINED | NUMBER_FITS_BYTE, 0); // dummy + alu_state = STATE_ERROR; } diff --git a/src/input.c b/src/input.c index 74867be..c070559 100644 --- a/src/input.c +++ b/src/input.c @@ -347,10 +347,38 @@ void Input_ensure_EOS(void) // Now GotByte = first char to test } } +// read string to dynabuf until closing quote is found +// returns 1 on errors (unterminated, escaping error) +int Input_quoted_to_dynabuf(char closing_quote) +{ + //DYNABUF_CLEAR(GlobalDynaBuf); // do not clear, caller might want to append to existing contents (TODO - check!) + for (;;) { + GetQuotedByte(); +// FIXME - this will fail with backslash escaping! +// it's not enough to check the previous char for backslash, because it might be an escaped backslash... + if (GotByte == closing_quote) + return 0; // ok + + if (GotByte == CHAR_EOS) + return 1; // unterminated string constant (GetQuotedByte will have complained already) + + DYNABUF_APPEND(GlobalDynaBuf, GotByte); + } +} + +// process backslash escapes in GlobalDynaBuf (so size might shrink) +// returns 1 on errors (escaping errors) +int Input_unescape_dynabuf(void) +{ + // FIXME - implement backslash escaping! + // TODO - shorten GlobalDynaBuf->size accordingly + return 0; +} + // Skip or store block (starting with next byte, so call directly after // reading opening brace). -// If "Store" is TRUE, the block is read into GlobalDynaBuf, then a copy -// is made and a pointer to that is returned. +// the block is read into GlobalDynaBuf. +// If "Store" is TRUE, then a copy is made and a pointer to that is returned. // If "Store" is FALSE, NULL is returned. // After calling this function, GotByte holds '}'. Unless EOF was found first, // but then a serious error would have been thrown. @@ -364,9 +392,8 @@ char *Input_skip_or_store_block(boolean store) DYNABUF_CLEAR(GlobalDynaBuf); do { byte = GetByte(); - // if wanted, store - if (store) - DYNABUF_APPEND(GlobalDynaBuf, byte); + // store + DYNABUF_APPEND(GlobalDynaBuf, byte); // now check for some special characters switch (byte) { case CHAR_EOF: // End-of-file in block? Sorry, no way. @@ -374,13 +401,8 @@ char *Input_skip_or_store_block(boolean store) case '"': // Quotes? Okay, read quoted stuff. case '\'': - do { - GetQuotedByte(); - // if wanted, store - if (store) - DYNABUF_APPEND(GlobalDynaBuf, GotByte); - // it's not enough to check the previous char for backslash, because it might be an escaped backslash... - } while ((GotByte != CHAR_EOS) && (GotByte != byte)); // FIXME - this would fail with backslash escaping! + Input_quoted_to_dynabuf(byte); + DYNABUF_APPEND(GlobalDynaBuf, GotByte); // add closing quote break; case CHAR_SOB: ++depth; @@ -419,7 +441,8 @@ void Input_until_terminator(char terminator) // Okay, read quoted stuff. GetQuotedByte(); // throws error on EOS DYNABUF_APPEND(GlobalDynaBuf, GotByte); - } while ((GotByte != CHAR_EOS) && (GotByte != byte)); // FIXME - this would fail with backslash escaping! +// FIXME - this would fail with backslash escaping! + } while ((GotByte != CHAR_EOS) && (GotByte != byte)); // on error, exit now, before calling GetByte() if (GotByte != byte) return; @@ -551,7 +574,7 @@ int Input_read_filename(boolean allow_library, boolean *uses_lib) return TRUE; } - // FIXME - this will fail with backslash escaping! +// FIXME - this will fail with backslash escaping! // read characters until closing quote (or EOS) is reached // append platform-converted characters to current string while ((GotByte != CHAR_EOS) && (GotByte != end_quote)) { diff --git a/src/input.h b/src/input.h index 0224d58..5166484 100644 --- a/src/input.h +++ b/src/input.h @@ -72,10 +72,19 @@ extern void Input_skip_remainder(void); // Ensure that the remainder of the current statement is empty, for example // after mnemonics using implied addressing. extern void Input_ensure_EOS(void); + +// read string to dynabuf until closing quote is found +// returns 1 on errors (unterminated, escaping error) +extern int Input_quoted_to_dynabuf(char closing_quote); + +// process backslash escapes in GlobalDynaBuf (so size might shrink) +// returns 1 on errors (escaping errors) +extern int Input_unescape_dynabuf(void); + // Skip or store block (starting with next byte, so call directly after // reading opening brace). -// If "Store" is TRUE, the block is read into GlobalDynaBuf, then a copy -// is made and a pointer to that is returned. +// the block is read into GlobalDynaBuf. +// If "Store" is TRUE, then a copy is made and a pointer to that is returned. // If "Store" is FALSE, NULL is returned. // After calling this function, GotByte holds '}'. Unless EOF was found first, // but then a serious error would have been thrown.