#include "linenoise/linenoise.h"
#include "newdb.h"
+void* xmalloc(size_t size)
+{
+ void* ptr = malloc(size);
+ if (ptr == NULL) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(EXIT_FAILURE);
+ }
+ return (ptr);
+}
+
char* xstrdup(const char* s)
{
char* ptr = strdup(s);
* are stored into PARMS(first) and PARMS(first+1). */
{
if (first >= MAXPARMS)
- BUG(29);
+ BUG(TOO_MANY_PARAMETERS_GIVEN_TO_SETPRM);
else {
PARMS[first] = p1;
PARMS[first + 1] = p2;
for (;;) {
if (game.blklin)
- TYPE0();
+ fputc('\n', stdout);;
if (!MAPLIN(input))
return false;
*pword1 = GETTXT(true, true, true);
}
}
-long YES(FILE *input, vocab_t x, vocab_t y, vocab_t z)
+void echo_input(FILE* destination, char* input_prompt, char* input)
+{
+ size_t len = strlen(input_prompt) + strlen(input) + 1;
+ char* prompt_and_input = (char*) xmalloc(len);
+ strcpy(prompt_and_input, input_prompt);
+ strcat(prompt_and_input, input);
+ fprintf(destination, "%s\n", prompt_and_input);
+ free(prompt_and_input);
+}
+
+char* get_input()
+{
+ // Set up the prompt
+ char input_prompt[] = "> ";
+ if (!prompt)
+ input_prompt[0] = '\0';
+
+ // Print a blank line if game.blklin tells us to.
+ if (game.blklin == true)
+ printf("\n");
+
+ char* input;
+ while (true) {
+ if (editline)
+ input = linenoise(input_prompt);
+ else {
+ input = NULL;
+ size_t n = 0;
+ if (isatty(0))
+ printf("%s", input_prompt);
+ IGNORE(getline(&input, &n, stdin));
+ }
+
+ if (input == NULL) // Got EOF; quit.
+ exit(EXIT_SUCCESS);
+ else if (input[0] == '#') // Ignore comments.
+ continue;
+ else // We have a 'normal' line; leave the loop.
+ break;
+ }
+
+ // Strip trailing newlines from the input
+ input[strcspn(input, "\n")] = 0;
+
+ linenoiseHistoryAdd(input);
+
+ if (!isatty(0))
+ echo_input(stdout, input_prompt, input);
+
+ if (logfp)
+ echo_input(logfp, input_prompt, input);
+
+ return (input);
+}
+
+bool YES(const char* question, const char* yes_response, const char* no_response)
/* Print message X, wait for yes/no answer. If yes, print Y and return true;
* if no, print Z and return false. */
{
- token_t reply, junk1, junk2, junk3;
+ char* reply;
+ bool outcome;
for (;;) {
- RSPEAK(x);
- GETIN(input, &reply, &junk1, &junk2, &junk3);
- if (reply == MAKEWD(250519) || reply == MAKEWD(25)) {
- RSPEAK(y);
- return true;
- }
- if (reply == MAKEWD(1415) || reply == MAKEWD(14)) {
- RSPEAK(z);
- return false;
- }
- RSPEAK(PLEASE_ANSWER);
+ speak(question);
+
+ reply = get_input();
+
+ char* firstword = (char*) xmalloc(strlen(reply));
+ sscanf(reply, "%s", firstword);
+
+ for (int i = 0; i < (int)strlen(firstword); ++i)
+ firstword[i] = tolower(firstword[i]);
+
+ int yes = strncmp("yes", firstword, sizeof("yes") - 1);
+ int y = strncmp("y", firstword, sizeof("y") - 1);
+ int no = strncmp("no", firstword, sizeof("no") - 1);
+ int n = strncmp("n", firstword, sizeof("n") - 1);
+
+ free(firstword);
+
+ if (yes == 0 || y == 0) {
+ speak(yes_response);
+ outcome = true;
+ break;
+ } else if (no == 0 || n == 0) {
+ speak(no_response);
+ outcome = false;
+ break;
+ } else
+ RSPEAK(PLEASE_ANSWER);
}
+ linenoiseFree(reply);
+ return (outcome);
}
-/* Line-parsing routines (GETTXT, MAKEWD, PUTTXT, SHFTXT, TYPE0) */
+/* Line-parsing routines (GETTXT, MAKEWD, PUTTXT, SHFTXT) */
long GETTXT(bool skip, bool onewrd, bool upper)
/* Take characters from an input line and pack them into 30-bit words.
return word;
}
-void TYPE0(void)
-/* Type a blank line. This procedure is provided as a convenience for callers
- * who otherwise have no use for MAPCOM. */
-{
- long temp;
-
- temp = LNLENG;
- LNLENG = 0;
- TYPE();
- LNLENG = temp;
- return;
-}
-
/* Data structure routines */
long VOCAB(long id, long init)
lexeme = -1;
if (init < 0)
return (lexeme);
- BUG(5);
+ BUG(REQUIRED_VOCABULARY_WORD_NOT_FOUND);
}
if (init >= 0 && KTAB[i] / 1000 != init)
continue;
return (lexeme);
}
}
- BUG(21);
+ BUG(RAN_OFF_END_OF_VOCABULARY_TABLE);
}
void JUGGLE(long object)
}
/* Utility routines (SETBIT, TSTBIT, set_seed, get_next_lcg_value,
- * randrange, RNDVOC, BUG) */
+ * randrange, RNDVOC) */
long SETBIT(long bit)
/* Returns 2**bit for use in constructing bit-masks. */
return rnd;
}
-void BUG(long num)
-/* The following conditions are currently considered fatal bugs. Numbers < 20
- * are detected while reading the database; the others occur at "run time".
- * 0 Message line > 70 characters
- * 1 Null line in message
- * 2 Too many words of messages
- * 3 Too many travel options
- * 4 Too many vocabulary words
- * 5 Required vocabulary word not found
- * 6 Too many RTEXT messages
- * 7 Too many hints
- * 8 Location has cond bit being set twice
- * 9 Invalid section number in database
- * 10 Too many locations
- * 11 Too many class or turn messages
- * 20 Special travel (500>L>300) exceeds goto list
- * 21 Ran off end of vocabulary table
- * 22 Vocabulary type (N/1000) not between 0 and 3
- * 23 Intransitive action verb exceeds goto list
- * 24 Transitive action verb exceeds goto list
- * 25 Conditional travel entry with no alternative
- * 26 Location has no travel entries
- * 27 Hint number exceeds goto list
- * 28 Invalid month returned by date function
- * 29 Too many parameters given to SETPRM */
-{
-
- printf("Fatal error %ld. See source code for interpretation.\n", num);
- exit(0);
-}
-/* Machine dependent routines (MAPLIN, TYPE, SAVEIO) */
+/* Machine dependent routines (MAPLIN, SAVEIO) */
bool MAPLIN(FILE *fp)
{
* 63 = percent (%) [ASCII 45 octal, 37 decimal]
* 64-73 = digits, 0 through 9
* Remaining characters can be translated any way that is convenient;
- * The "TYPE" routine below is used to map them back to characters when
- * necessary. The above mappings are required so that certain special
+ * The above mappings are required so that certain special
* characters are known to fit in 6 bits and/or can be easily spotted.
* Array elements beyond the end of the line should be filled with 0,
* and LNLENG should be set to the index of the last character.
}
}
-void TYPE(void)
-/* Type the first "LNLENG" characters stored in inline, mapping them
- * from integers to text per the rules described above. INLINE
- * may be changed by this routine. */
-{
- long i;
-
- if (LNLENG == 0) {
- printf("\n");
- return;
- }
-
- for (i = 1; i <= LNLENG; i++) {
- INLINE[i] = advent_to_ascii[(int) INLINE[i]];
- }
- INLINE[LNLENG + 1] = 0;
- printf("%s\n", INLINE + 1);
- return;
-}
-
void DATIME(long* d, long* t)
{
struct timeval tv;
*t = (long) tv.tv_usec;
}
+void bug(enum bugtype num, const char *error_string)
+{
+ fprintf(stderr, "Fatal error %d, %s.\n", num, error_string);
+ exit(EXIT_FAILURE);
+}
+
/* end */