X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=misc.c;h=4fa173d91f4d5b9ba457954cf136e408ef562600;hb=6e6722220613eae112a683e722a0e78d4b426455;hp=dc6cec50a2704b1631ab23f5a8af3ace5a27f71d;hpb=6af38a92f60179af2b4eed23e508160a347da432;p=open-adventure.git diff --git a/misc.c b/misc.c index dc6cec5..4fa173d 100644 --- a/misc.c +++ b/misc.c @@ -10,7 +10,7 @@ #include "advent.h" #include "dungeon.h" -char* xstrdup(const char* s) +static char* xstrdup(const char* s) { char* ptr = strdup(s); if (ptr == NULL) { @@ -22,7 +22,7 @@ char* xstrdup(const char* s) return (ptr); } -void* xmalloc(size_t size) +static void* xmalloc(size_t size) { void* ptr = malloc(size); if (ptr == NULL) { @@ -35,7 +35,7 @@ void* xmalloc(size_t size) return (ptr); } -void packed_to_token(long packed, char token[6]) +void packed_to_token(long packed, char token[TOKLEN+1]) { // The advent->ascii mapping. const char advent_to_ascii[] = { @@ -60,14 +60,15 @@ void packed_to_token(long packed, char token[6]) // Replace trailing whitespace with \0. for (int i = 4; i >= 0; --i) { - if (token[i] == ' ' || token[i] == '\t') + if (token[i] == ' ' || + token[i] == '\t') token[i] = '\0'; else break; } } -long token_to_packed(const char token[6]) +long token_to_packed(const char token[]) { const char ascii_to_advent[] = { 63, 63, 63, 63, 63, 63, 63, 63, @@ -91,49 +92,26 @@ long token_to_packed(const char token[6]) }; size_t t_len = strlen(token); + if (t_len > TOKLEN) + t_len = TOKLEN; long packed = 0; for (size_t i = 0; i < t_len; ++i) { - char mapped = ascii_to_advent[(int) token[i]]; + char mapped = ascii_to_advent[(int) toupper(token[i])]; packed |= (mapped << (6 * i)); } return (packed); } -void tokenize(char* raw, long tokens[4]) +void tokenize(char* raw, struct command_t *cmd) { - // set each token to 0 - for (int i = 0; i < 4; ++i) - tokens[i] = 0; + memset(cmd, '\0', sizeof(struct command_t)); - // grab the first two words - char* words[2]; - words[0] = (char*) xmalloc(strlen(raw) + 1); - words[1] = (char*) xmalloc(strlen(raw) + 1); - int word_count = sscanf(raw, "%s%s", words[0], words[1]); - - // make space for substrings and zero it out - char chunk_data[][6] = { - {"\0\0\0\0\0"}, - {"\0\0\0\0\0"}, - {"\0\0\0\0\0"}, - {"\0\0\0\0\0"}, - }; - - // break the words into up to 4 5-char substrings - sscanf(words[0], "%5s%5s", chunk_data[0], chunk_data[1]); - if (word_count == 2) - sscanf(words[1], "%5s%5s", chunk_data[2], chunk_data[3]); - free(words[0]); - free(words[1]); - - // uppercase all the substrings - for (int i = 0; i < 4; ++i) - for (unsigned int j = 0; j < strlen(chunk_data[i]); ++j) - chunk_data[i][j] = (char) toupper(chunk_data[i][j]); + /* FIXME: put a bound prefix on the %s to prevent buffer overflow */ + int word_count = sscanf(raw, "%s%s", cmd->raw1, cmd->raw2); // pack the substrings - for (int i = 0; i < 4; ++i) - tokens[i] = token_to_packed(chunk_data[i]); + cmd->wd1 = token_to_packed(cmd->raw1); + cmd->wd2 = token_to_packed(cmd->raw2); } /* Hide the fact that wods are corrently packed longs */ @@ -153,7 +131,7 @@ void wordclear(token_t *v) *v = 0; } -/* I/O routines (speak, pspeak, rspeak, get_input, yes) */ +/* I/O routines (speak, pspeak, rspeak, sspeak, get_input, yes) */ void vspeak(const char* msg, bool blank, va_list ap) { @@ -166,7 +144,7 @@ void vspeak(const char* msg, bool blank, va_list ap) return; if (blank == true) - printf("\n"); + printf("\n"); int msglen = strlen(msg); @@ -225,7 +203,8 @@ void vspeak(const char* msg, bool blank, va_list ap) } // All-lowercase specifier. - if (msg[i] == 'L' || msg[i] == 'C') { + if (msg[i] == 'L' || + msg[i] == 'C') { packed_to_token(arg, renderp); /* unpack directly to destination */ int len = strlen(renderp); for (int j = 0; j < len; ++j) { @@ -256,6 +235,16 @@ void speak(const char* msg, ...) va_end(ap); } +void sspeak(const long msg, ...) +{ + va_list ap; + va_start(ap, msg); + fputc('\n', stdout); + vprintf(arbitrary_messages[msg], ap); + fputc('\n', stdout); + va_end(ap); +} + void pspeak(vocab_t msg, enum speaktype mode, int skip, bool blank, ...) /* Find the skip+1st message from msg and print it. Modes are: * feel = for inventory, what you can touch @@ -267,19 +256,19 @@ void pspeak(vocab_t msg, enum speaktype mode, int skip, bool blank, ...) va_start(ap, blank); switch (mode) { case touch: - vspeak(objects[msg].inventory, blank, ap); + vspeak(objects[msg].inventory, blank, ap); break; case look: - vspeak(objects[msg].descriptions[skip], blank, ap); + vspeak(objects[msg].descriptions[skip], blank, ap); break; case hear: - vspeak(objects[msg].sounds[skip], blank, ap); + vspeak(objects[msg].sounds[skip], blank, ap); break; case study: - vspeak(objects[msg].texts[skip], blank, ap); + vspeak(objects[msg].texts[skip], blank, ap); break; case change: - vspeak(objects[msg].changes[skip], blank, ap); + vspeak(objects[msg].changes[skip], blank, ap); break; } va_end(ap); @@ -387,10 +376,12 @@ bool silent_yes() free(firstword); - if (yes == 0 || y == 0) { + if (yes == 0 || + y == 0) { outcome = true; break; - } else if (no == 0 || n == 0) { + } else if (no == 0 || + n == 0) { outcome = false; break; } else @@ -434,11 +425,13 @@ bool yes(const char* question, const char* yes_response, const char* no_response free(firstword); - if (yes == 0 || y == 0) { + if (yes == 0 || + y == 0) { speak(yes_response); outcome = true; break; - } else if (no == 0 || n == 0) { + } else if (no == 0 || + n == 0) { speak(no_response); outcome = false; break; @@ -457,7 +450,9 @@ int get_motion_vocab_id(const char* word) { for (int i = 0; i < NMOTIONS; ++i) { for (int j = 0; j < motions[i].words.n; ++j) { - if (strcasecmp(word, motions[i].words.strs[j]) == 0 && (strlen(word) > 1 || strchr(ignore, word[0]) == NULL || !settings.oldstyle)) + if (strcasecmp(word, motions[i].words.strs[j]) == 0 && (strlen(word) > 1 || + strchr(ignore, word[0]) == NULL || + !settings.oldstyle)) return (i); } } @@ -483,7 +478,9 @@ int get_action_vocab_id(const char* word) { for (int i = 0; i < NACTIONS; ++i) { for (int j = 0; j < actions[i].words.n; ++j) { - if (strcasecmp(word, actions[i].words.strs[j]) == 0 && (strlen(word) > 1 || strchr(ignore, word[0]) == NULL || !settings.oldstyle)) + if (strcasecmp(word, actions[i].words.strs[j]) == 0 && (strlen(word) > 1 || + strchr(ignore, word[0]) == NULL || + !settings.oldstyle)) return (i); } } @@ -669,7 +666,7 @@ long randrange(long range) return range * get_next_lcg_value() / game.lcg_m; } -void make_zzword(char zzword[6]) +void make_zzword(char zzword[TOKLEN+1]) { for (int i = 0; i < 5; ++i) { zzword[i] = 'A' + randrange(26);