magic numbers, show usage, fixed linty warnings

Show usage when using bad parameter with ./advent
Converted magic numbers to enums for BUG().  Also bug now shows
stringify'ed version of bug enumeration (not just a number).
This commit is contained in:
Bob Little 2017-06-18 19:33:21 -04:00
parent 65e2e472dd
commit 04eca720d9
10 changed files with 140 additions and 116 deletions

2
.gitignore vendored
View file

@ -5,10 +5,10 @@ dungeon
*.o
*.html
database.h
database.c
advent.6
*.tar.gz
MANIFEST
*.adv
.*~
newdb.h
newdb.c

View file

@ -24,6 +24,8 @@
#
# To build with save/resume disabled, pass CCFLAGS="-D ADVENT_NOSAVE"
.PHONY: debug indent release refresh dist linty html clean
VERS=1.0
CC?=gcc
@ -118,7 +120,25 @@ refresh: advent.html
dist: advent-$(VERS).tar.gz
linty: CCFLAGS += -W -Wall -Wextra -Wundef -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wfloat-equal -Wcast-align -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-enum -Wwrite-strings -Wunreachable-code -Winit-self -Wpointer-arith -O2
linty: CCFLAGS += -W
linty: CCFLAGS += -Wall
linty: CCFLAGS += -Wextra
linty: CCFLAGS += -Wundef
linty: CCFLAGS += -Wstrict-prototypes
linty: CCFLAGS += -Wmissing-prototypes
linty: CCFLAGS += -Wmissing-declarations
linty: CCFLAGS += -Wshadow
linty: CCFLAGS += -Wfloat-equal
linty: CCFLAGS += -Wcast-align
linty: CCFLAGS += -Wwrite-strings
linty: CCFLAGS += -Waggregate-return
linty: CCFLAGS += -Wcast-qual
linty: CCFLAGS += -Wswitch-enum
linty: CCFLAGS += -Wwrite-strings
linty: CCFLAGS += -Wunreachable-code
linty: CCFLAGS += -Winit-self
linty: CCFLAGS += -Wpointer-arith
linty: CCFLAGS +=-O2
linty: advent
debug: CCFLAGS += -O0 --coverage -g

View file

@ -789,7 +789,7 @@ static int pour(token_t verb, token_t obj)
}
}
static int quit(FILE *input)
static int quit(void)
/* Quit. Intransitive only. Verify intent and exit if that's what he wants. */
{
if (YES(REALLY_QUIT, OK_MAN, OK_MAN))
@ -797,7 +797,7 @@ static int quit(FILE *input)
return GO_CLEAROBJ;
}
static int read(FILE *input, token_t verb, token_t obj)
static int read(token_t verb, token_t obj)
/* Read. Print stuff based on objtxt. Oyster (?) is special case. */
{
int spk = ACTSPK[verb];
@ -1100,7 +1100,7 @@ int action(FILE *input, enum speechpart part, long verb, token_t obj)
case 16: /* TOSS */
return GO_UNKNOWN;
case 17: /* QUIT */
return quit(input);
return quit();
case 18: /* FIND */
return GO_UNKNOWN;
case 19: /* INVEN */
@ -1120,15 +1120,15 @@ int action(FILE *input, enum speechpart part, long verb, token_t obj)
case 25: /* BRIEF */
return brief();
case 26: /* READ */
return read(input, verb, INTRANSITIVE);
return read(verb, INTRANSITIVE);
case 27: /* BREAK */
return GO_UNKNOWN;
case 28: /* WAKE */
return GO_UNKNOWN;
case 29: /* SUSP */
return suspend(input);
return suspend();
case 30: /* RESU */
return resume(input);
return resume();
case 31: /* FLY */
return fly(verb, INTRANSITIVE);
case 32: /* LISTE */
@ -1136,7 +1136,7 @@ int action(FILE *input, enum speechpart part, long verb, token_t obj)
case 33: /* ZZZZ */
return reservoir();
}
BUG(23);
BUG(INTRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST);
}
/* FALLTHRU */
case transitive:
@ -1210,7 +1210,7 @@ int action(FILE *input, enum speechpart part, long verb, token_t obj)
return GO_CLEAROBJ;
}
case 26: /* READ */
return read(input, verb, obj);
return read(verb, obj);
case 27: /* BREAK */
return vbreak(verb, obj);
case 28: /* WAKE */
@ -1232,13 +1232,13 @@ int action(FILE *input, enum speechpart part, long verb, token_t obj)
case 33: /* ZZZZ */
return reservoir();
}
BUG(24);
BUG(TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST);
case unknown:
/* Unknown verb, couldn't deduce object - might need hint */
SETPRM(1, WD1, WD1X);
RSPEAK(WHAT_DO);
return GO_CHECKHINT;
default:
BUG(99);
BUG(SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN);
}
}

View file

@ -1,4 +1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "common.h"
@ -106,7 +107,6 @@ extern long ATDWRF(long);
extern long SETBIT(long);
extern bool TSTBIT(long,int);
extern long RNDVOC(long,long);
extern void BUG(long) __attribute__((noreturn));
extern bool MAPLIN(FILE *);
extern void DATIME(long*, long*);
@ -117,8 +117,8 @@ extern unsigned long get_next_lcg_value(void);
extern long randrange(long);
extern long score(enum termination);
extern void terminate(enum termination) __attribute__((noreturn));
extern int suspend(FILE *);
extern int resume(FILE *);
extern int suspend(void);
extern int resume(void);
extern int restore(FILE *);
/*

View file

@ -1,3 +1,5 @@
#include <stdlib.h>
#include <stdio.h>
#include "common.h"
const char advent_to_ascii[] = {

View file

@ -1,3 +1,5 @@
#ifndef COMMON_H
#define COMMON_H
/* maximum size limits shared by dungeon compiler and runtime */
#define LOCSIZ 185
@ -6,3 +8,41 @@
extern const char advent_to_ascii[128];
extern const char ascii_to_advent[128];
enum bug_e {
MESSAGE_LINE_GT_70_CHARACTERS, // 0
NULL_LINE_IN_MESSAGE, // 1
TOO_MANY_WORDS_OF_MESSAGES, // 2
TOO_MANY_TRAVEL_OPTIONS, // 3
TOO_MANY_VOCABULARY_WORDS, // 4
REQUIRED_VOCABULARY_WORD_NOT_FOUND, // 5
TOO_MANY_RTEXT_MESSAGES, // 6
TOO_MANY_HINTS, // 7
LOCATION_HAS_CONDITION_BIT_BEING_SET_TWICE, // 8
INVALID_SECTION_NUMBER_IN_DATABASE, // 9
TOO_MANY_LOCATIONS, // 10
TOO_MANY_CLASS_OR_TURN_MESSAGES, // 11
SPECIAL_TRAVEL_500_GT_L_GT_300_EXCEEDS_GOTO_LIST = 20, // 20
RAN_OFF_END_OF_VOCABULARY_TABLE, // 21
VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3, // 22
INTRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST, // 23
TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST, // 24
CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION, // 25
LOCATION_HAS_NO_TRAVEL_ENTRIES, // 26
HINT_NUMBER_EXCEEDS_GOTO_LIST, // 27
INVALID_MOTH_RETURNED_BY_DATA_FUNCTION, // 28
TOO_MANY_PARAMETERS_GIVEN_TO_SETPRM, // 29
SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN=99, // 99
ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH, // 100
};
static inline void bug(enum bug_e num, const char *error_string) __attribute__((__noreturn__));
static inline void bug(enum bug_e num, const char *error_string)
{
fprintf(stderr, "Fatal error %d, %s.\n", num, error_string);
exit(EXIT_FAILURE);
}
#define BUG(x) bug(x, #x)
#endif

View file

@ -3,7 +3,6 @@
* defining (mostly) invariant state. A couple of slots are messed with
* at runtime.
*/
#include "common.h"
#define LINESIZE 100
#define RTXSIZ 277
@ -20,6 +19,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include "common.h"
// Global variables for use in functions below that can gradually disappear as code is cleaned up
static long LNLENG;
@ -114,38 +114,6 @@ static long GETTXT(long SKIP, long ONEWRD, long UPPER)
return (TEXT);
}
static 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 */
fprintf(stderr, "Fatal error %ld. See source code for interpretation.\n", NUM);
exit(EXIT_FAILURE);
}
static void MAPLIN(FILE *OPENED)
{
/* Read a line of input, from the specified input source,
@ -236,12 +204,15 @@ static void read_messages(FILE* database, long sect)
long loc;
LINUSE = KK;
loc = GETNUM(database);
if (LNLENG >= LNPOSN + 70)BUG(0);
if (LNLENG >= LNPOSN + 70)
BUG(MESSAGE_LINE_GT_70_CHARACTERS);
if (loc == -1) return;
if (LNLENG < LNPOSN)BUG(1);
if (LNLENG < LNPOSN)
BUG(NULL_LINE_IN_MESSAGE);
do {
KK = KK + 1;
if (KK >= LINSIZ)BUG(2);
if (KK >= LINSIZ)
BUG(TOO_MANY_WORDS_OF_MESSAGES);
LINES[KK] = GETTXT(false, false, false);
} while (LINES[KK] != -1);
LINES[LINUSE] = KK;
@ -250,20 +221,23 @@ static void read_messages(FILE* database, long sect)
LINES[LINUSE] = -KK;
if (sect == 14) {
TRNVLS = TRNVLS + 1;
if (TRNVLS > TRNSIZ)BUG(11);
if (TRNVLS > TRNSIZ)
BUG(TOO_MANY_CLASS_OR_TURN_MESSAGES);
TTEXT[TRNVLS] = LINUSE;
TRNVAL[TRNVLS] = loc;
continue;
}
if (sect == 10) {
CLSSES = CLSSES + 1;
if (CLSSES > CLSMAX)BUG(11);
if (CLSSES > CLSMAX)
BUG(TOO_MANY_CLASS_OR_TURN_MESSAGES);
CTEXT[CLSSES] = LINUSE;
CVAL[CLSSES] = loc;
continue;
}
if (sect == 6) {
if (loc > RTXSIZ)BUG(6);
if (loc > RTXSIZ)
BUG(TOO_MANY_RTEXT_MESSAGES);
RTEXT[loc] = LINUSE;
continue;
}
@ -271,7 +245,8 @@ static void read_messages(FILE* database, long sect)
if (loc > 0 && loc <= NOBJECTS)PTEXT[loc] = LINUSE;
continue;
}
if (loc > LOCSIZ)BUG(10);
if (loc > LOCSIZ)
BUG(TOO_MANY_LOCATIONS);
if (sect == 1) {
LTEXT[loc] = LINUSE;
continue;
@ -300,7 +275,8 @@ static void read_section3_stuff(FILE* database)
while ((L = GETNUM(NULL)) != 0) {
TRAVEL[TRVS] = newloc * 1000 + L;
TRVS = TRVS + 1;
if (TRVS == TRVSIZ)BUG(3);
if (TRVS == TRVSIZ)
BUG(TOO_MANY_TRAVEL_OPTIONS);
}
TRAVEL[TRVS - 1] = -TRAVEL[TRVS - 1];
}
@ -316,7 +292,7 @@ static void read_vocabulary(FILE* database)
if (KTAB[TABNDX] == -1) return;
ATAB[TABNDX] = GETTXT(true, true, true);
} /* end loop */
BUG(4);
BUG(TOO_MANY_VOCABULARY_WORDS);
}
/* Read in the initial locations for each object. Also the immovability info.
@ -347,7 +323,8 @@ static void read_conditions(FILE* database)
while ((K = GETNUM(database)) != -1) {
long loc;
while ((loc = GETNUM(NULL)) != 0) {
if (is_set(COND[loc], K)) BUG(8);
if (is_set(COND[loc], K))
BUG(LOCATION_HAS_CONDITION_BIT_BEING_SET_TWICE);
COND[loc] = COND[loc] + (1l << K);
}
}
@ -360,7 +337,8 @@ static void read_hints(FILE* database)
long K;
HNTMAX = 0;
while ((K = GETNUM(database)) != -1) {
if (K <= 0 || K > HNTSIZ)BUG(7);
if (K <= 0 || K > HNTSIZ)
BUG(TOO_MANY_HINTS);
for (int I = 1; I <= 4; I++) {
HINTS[K][I] = GETNUM(NULL);
} /* end loop */
@ -473,7 +451,7 @@ static int read_database(FILE* database)
read_messages(database, sect);
break;
default:
BUG(9);
BUG(INVALID_SECTION_NUMBER_IN_DATABASE);
}
}
}

50
main.c
View file

@ -66,7 +66,7 @@ static void sig_handler(int signo)
* 15-treasure version (adventure) by Don Woods, April-June 1977
* 20-treasure version (rev 2) by Don Woods, August 1978
* Errata fixed: 78/12/25
* Revived 2017 as Open Advebture.
* Revived 2017 as Open Adventure.
*/
static bool do_command(FILE *);
@ -102,6 +102,19 @@ int main(int argc, char *argv[])
case 's':
editline = false;
break;
default:
fprintf(stderr,
"Usage: %s [-l logfilename] [-o] [-r restorefilename] [-s] \n", argv[0]);
fprintf(stderr,
" where -l creates a log file of your game named as specified'\n");
fprintf(stderr,
" -o 'oldstyle' (no prompt, no command editing, displays 'Initialising...')\n");
fprintf(stderr,
" -r indicates restoring from specified saved game file\n");
fprintf(stderr,
" -s indicates playing with command editing suppressed\n");
exit(-1);
break;
}
}
@ -174,7 +187,7 @@ static bool fallback_handler(char *buf)
* all come back here eventually to finish the loop. Ignore
* "HINTS" < 4 (special stuff, see database notes).
*/
static void checkhints(FILE *cmdin)
static void checkhints(void)
{
if (COND[game.loc] >= game.conds) {
for (int hint = 1; hint <= HNTMAX; hint++) {
@ -245,7 +258,7 @@ static void checkhints(FILE *cmdin)
game.hintlc[hint] = 0;
return;
default:
BUG(27);
BUG(HINT_NUMBER_EXCEEDS_GOTO_LIST);
break;
}
@ -474,7 +487,7 @@ static bool dwarfmove(void)
* without the lamp!). game.oldloc is zapped so he can't just
* "retreat". */
static void croak(FILE *cmdin)
static void croak(void)
/* Okay, he's dead. Let's get on with it. */
{
++game.numdie;
@ -511,12 +524,12 @@ static void croak(FILE *cmdin)
* him, so we need game.oldlc2, which is the last place he was
* safe.) */
static bool playermove(FILE *cmdin, token_t verb, int motion)
static bool playermove(token_t verb, int motion)
{
int scratchloc, k2, kk = KEY[game.loc];
game.newloc = game.loc;
if (kk == 0)
BUG(26);
BUG(LOCATION_HAS_NO_TRAVEL_ENTRIES);
if (motion == NUL)
return true;
else if (motion == BACK) {
@ -625,7 +638,8 @@ static bool playermove(FILE *cmdin, token_t verb, int motion)
break;
L12:
do {
if (TRAVEL[kk] < 0)BUG(25);
if (TRAVEL[kk] < 0)
BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION);
++kk;
game.newloc = labs(TRAVEL[kk]) / 1000;
} while
@ -687,10 +701,10 @@ static bool playermove(FILE *cmdin, token_t verb, int motion)
game.fixed[BEAR] = -1;
game.prop[BEAR] = 3;
game.oldlc2 = game.newloc;
croak(cmdin);
croak();
}
}
BUG(20);
BUG(SPECIAL_TRAVEL_500_GT_L_GT_300_EXCEEDS_GOTO_LIST);
}
} while
(false);
@ -928,13 +942,13 @@ static bool do_command(FILE *cmdin)
game.loc = game.newloc;
if (!dwarfmove())
croak(cmdin);
croak();
/* Describe the current location and (maybe) get next command. */
for (;;) {
if (game.loc == 0)
croak(cmdin);
croak();
const char* msg = locations[game.loc].description.small;
if (MOD(game.abbrev[game.loc], game.abbnum) == 0 || msg == 0)
msg = locations[game.loc].description.big;
@ -944,7 +958,7 @@ static bool do_command(FILE *cmdin)
if (game.wzdark && PCT(35)) {
RSPEAK(PIT_FALL);
game.oldlc2 = game.loc;
croak(cmdin);
croak();
continue; /* back to top of main interpreter loop */
}
msg = arbitrary_messages[PITCH_DARK];
@ -952,7 +966,7 @@ static bool do_command(FILE *cmdin)
if (TOTING(BEAR))RSPEAK(TAME_BEAR);
speak(msg);
if (FORCED(game.loc)) {
if (playermove(cmdin, verb, 1))
if (playermove(verb, 1))
return true;
else
continue; /* back to top of main interpreter loop */
@ -967,7 +981,7 @@ L2012:
obj = 0;
L2600:
checkhints(cmdin);
checkhints();
/* If closing time, check for any objects being toted with
* game.prop < 0 and set the prop to -1-game.prop. This way
@ -1062,7 +1076,7 @@ Lookup:
kmod = MOD(defn, 1000);
switch (defn / 1000) {
case 0:
if (playermove(cmdin, verb, kmod))
if (playermove(verb, kmod))
return true;
else
continue; /* back to top of main interpreter loop */
@ -1078,7 +1092,7 @@ Lookup:
RSPEAK(kmod);
goto L2012;
default:
BUG(22);
BUG(VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3);
}
Laction:
@ -1086,7 +1100,7 @@ Laction:
case GO_TERMINATE:
return true;
case GO_MOVE:
playermove(cmdin, verb, NUL);
playermove(verb, NUL);
return true;
case GO_TOP:
continue; /* back to top of main interpreter loop */
@ -1116,7 +1130,7 @@ Laction:
RSPEAK(DWARVES_AWAKEN);
terminate(endgame);
default:
BUG(99);
BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH);
}
}
}

42
misc.c
View file

@ -153,7 +153,7 @@ void SETPRM(long first, long p1, long p2)
* 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;
@ -228,7 +228,7 @@ char* get_input()
size_t n = 0;
if (isatty(0))
printf("%s", input_prompt);
getline(&input, &n, stdin);
IGNORE(getline(&input, &n, stdin));
}
if (input == NULL) // Got EOF; quit.
@ -268,7 +268,7 @@ bool YES(vocab_t question, vocab_t yes_response, vocab_t no_response)
char* firstword = (char*) xmalloc(strlen(reply));
sscanf(reply, "%s", firstword);
for (int i = 0; i < strlen(firstword); ++i)
for (int i = 0; i < (int)strlen(firstword); ++i)
firstword[i] = tolower(firstword[i]);
int yes = strncmp("yes", firstword, sizeof("yes") - 1);
@ -384,7 +384,7 @@ 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;
@ -395,7 +395,7 @@ long VOCAB(long id, long init)
return (lexeme);
}
}
BUG(21);
BUG(RAN_OFF_END_OF_VOCABULARY_TABLE);
}
void JUGGLE(long object)
@ -497,7 +497,7 @@ long ATDWRF(long where)
}
/* 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. */
@ -559,36 +559,6 @@ long RNDVOC(long second, long force)
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, SAVEIO) */

View file

@ -30,7 +30,7 @@ struct save_t {
struct save_t save;
/* Suspend and resume */
int suspend(FILE *input)
int suspend(void)
{
/* Suspend. Offer to save things in a file, but charging
* some points (so can't win by using saved games to retry
@ -71,7 +71,7 @@ int suspend(FILE *input)
exit(0);
}
int resume(FILE *input)
int resume(void)
{
/* Resume. Read a suspended game back from a file.
* If ADVENT_NOSAVE is defined, do nothing instead. */