Support execution of command script arguments.

This commit is contained in:
Eric S. Raymond 2022-04-05 08:31:10 -04:00
parent 8378063198
commit bb2b8e0fca
7 changed files with 80 additions and 9 deletions

View file

@ -8,7 +8,7 @@ VERS=$(shell sed -n <NEWS '/^[0-9]/s/:.*//p' | head -1)
.PHONY: check coverage
CC?=gcc
CCFLAGS+=-std=c99 -D_DEFAULT_SOURCE -DVERSION=\"$(VERS)\" -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all $(CFLAGS)
CCFLAGS+=-std=c99 -D_DEFAULT_SOURCE -DVERSION=\"$(VERS)\" -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all $(CFLAGS) -g
LIBS=$(shell pkg-config --libs libedit)
INC+=$(shell pkg-config --cflags libedit)

View file

@ -5,7 +5,7 @@
advent - Colossal Cave Adventure
== SYNOPSIS ==
*advent* [-l logfile] [-o] [-r savefile]
*advent* [-l logfile] [-o] [-r savefile] [script...]
== DESCRIPTION ==
The original Colossal Cave Adventure from 1976-77 was the origin of all
@ -46,6 +46,10 @@ There have been no gameplay changes.
Also ignores new-school one-letter commands l, x, g, z, i. Also
case-smashes and truncates unrecognized text when echoed.
Normally, game input is taken from standard input. If script file
arguments are given, input is taken fron them instead. A script file
argument of '-' is taken as a directive to read from standard input.
== BUGS ==
The binary save file format is fragile, dependent on your machine word

View file

@ -45,6 +45,8 @@
* which has its own meaning. */
#define STASHED(obj) (-1 - game.prop[obj])
#define PROMPT "> "
/*
* DESTROY(N) = Get rid of an item by putting it in LOC_NOWHERE
* MOD(N,M) = Arithmetic modulus
@ -194,6 +196,10 @@ struct settings_t {
FILE *logfp;
bool oldstyle;
bool prompt;
char **argv;
int argc;
int optind;
FILE *scriptfp;
};
typedef struct {
@ -215,6 +221,7 @@ typedef struct {
extern struct game_t game;
extern struct settings_t settings;
extern char *myreadline(const char *);
extern bool get_command_input(command_t *);
extern void clear_command(command_t *);
extern void speak(const char*, ...);

12
cheat.c
View file

@ -12,6 +12,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <editline/readline.h>
#include "advent.h"
int main(int argc, char *argv[])
@ -96,3 +97,14 @@ int main(int argc, char *argv[])
return EXIT_SUCCESS;
}
/*
* Ugh...unused, but required for linkage.
* See thje actually useful version of this in main.c
*/
char *myreadline(const char *prompt)
{
return readline(prompt);
}

53
main.c
View file

@ -11,6 +11,8 @@
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <editline/readline.h>
#include "advent.h"
#include "dungeon.h"
@ -50,11 +52,11 @@ int main(int argc, char *argv[])
#ifndef ADVENT_NOSAVE
const char* opts = "l:or:";
const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename]\n";
const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename] [script...]\n";
FILE *rfp = NULL;
#else
const char* opts = "l:o";
const char* usage = "Usage: %s [-l logfilename] [-o]\n";
const char* usage = "Usage: %s [-l logfilename] [-o] [script...]\n";
#endif
while ((ch = getopt(argc, argv, opts)) != EOF) {
switch (ch) {
@ -95,6 +97,11 @@ int main(int argc, char *argv[])
}
}
/* copy inncation line part after switches */
settings.argc = argc - optind;
settings.argv = argv + optind;
settings.optind = 0;
/* Initialize game variables */
int seedval = initialise();
@ -129,6 +136,48 @@ int main(int argc, char *argv[])
terminate(quitgame);
}
char *myreadline(const char *prompt)
{
/*
* This function isbn't required for gameplay, readline() straight
* up would suffice for tat. It's where we interpret command-line
* logfiles for testing purposes.
*/
/* Normal case - no script arguments */
if (settings.argc == 0)
return readline(prompt);
for (;;) {
if (settings.scriptfp == NULL || feof(settings.scriptfp)) {
if (settings.optind >= settings.argc) {
return NULL;
}
char *next = settings.argv[settings.optind++];
if (settings.scriptfp != NULL && feof(settings.scriptfp))
fclose(settings.scriptfp);
if (strcmp(next, "-") == 0)
settings.scriptfp = stdin;
else
settings.scriptfp = fopen(next, "r");
}
if (isatty(fileno(settings.scriptfp))) {
return readline(prompt);
} else {
char *ln = fgets(malloc(BUFSIZ), BUFSIZ-1, settings.scriptfp);
if (ln != NULL) {
fputs(PROMPT, stdout);
fputs(ln, stdout);
return ln;
}
}
}
return NULL;
}
/* Check if this loc is eligible for any hints. If been here int
* enough, display. Ignore "HINTS" < 4 (special stuff, see database
* notes). */

4
misc.c
View file

@ -211,7 +211,7 @@ static int word_count(char* str)
static char* get_input(void)
{
// Set up the prompt
char input_prompt[] = "> ";
char input_prompt[] = PROMPT;
if (!settings.prompt)
input_prompt[0] = '\0';
@ -220,7 +220,7 @@ static char* get_input(void)
char* input;
while (true) {
input = readline(input_prompt);
input = myreadline(input_prompt);
if (input == NULL) // Got EOF; return with it.
return (input);

View file

@ -11,7 +11,6 @@
#include <stdlib.h>
#include <string.h>
#include <editline/readline.h>
#include <time.h>
#include <inttypes.h>
@ -74,7 +73,7 @@ int suspend(void)
game.saved = game.saved + 5;
while (fp == NULL) {
char* name = readline("\nFile name: ");
char* name = myreadline("\nFile name: ");
if (name == NULL)
return GO_TOP;
fp = fopen(name, WRITE_MODE);
@ -107,7 +106,7 @@ int resume(void)
}
while (fp == NULL) {
char* name = readline("\nFile name: ");
char* name = myreadline("\nFile name: ");
// Autocomplete can leave the input with an extra traoling space.
if (name != NULL && strlen(name) > 0 && name[strlen(name) - 1] == ' ')
name[strlen(name) - 1] = '\0';