/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefiting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************
* 1stMud ROM Derivative (c) 2001-2004 by Markanth *
* http://www.firstmud.com/ <markanth@firstmud.com> *
* By using this code you have agreed to follow the term of *
* the 1stMud license in ../doc/1stMud/LICENSE *
***************************************************************************/
#include "merc.h"
#include "recycle.h"
void write_string(FileData * fp, const char *name, const char *str,
const char *def)
{
if (NullStr(name))
f_printf(fp, "%s~" LF, fix_string(str));
else if (!NullStr(str) && (NullStr(def) || str_cmp(str, def)))
f_printf(fp, "%s%s%s~" LF, name, format_tabs(strlen(name)),
fix_string(str));
}
void write_word(FileData * fp, const char *name, const char *str,
const char *def)
{
if (NullStr(name))
f_printf(fp, "'%s'" LF, fix_string(str));
else if (!NullStr(str) && (NullStr(def) || str_cmp(str, def)))
f_printf(fp, "%s%s'%s'" LF, name, format_tabs(strlen(name)),
fix_string(str));
}
void write_bit(FileData * fp, const char *name, flag_t bit, flag_t def)
{
if (NullStr(name))
f_printf(fp, "%s" LF, write_flags(bit));
else if (bit != def)
f_printf(fp, "%s%s%s" LF, name, format_tabs(strlen(name)),
write_flags(bit));
}
void write_header(FileData * fp, const char *head)
{
if (!NullStr(head))
f_printf(fp, "%s%s", head, format_tabs(strlen(head)));
}
void f_writef(FileData * fp, const char *name, const char *format, ...)
{
if (!NullStr(format))
{
va_list args;
char buf[MPL];
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (!NullStr(name))
f_printf(fp, name);
f_printf(fp, "%s%s", format_tabs(strlen(name)), buf);
}
else if (!NullStr(name))
{
f_printf(fp, name);
}
}
void write_time(FileData * fp, const char *name, time_t time, bool fTime)
{
if (!NullStr(name))
f_printf(fp, "%s%s", name, format_tabs(strlen(name)));
else
f_printf(fp, " ");
f_printf(fp, TIME_T_FMT, time);
f_printf(fp, " (%s)" LF,
!fTime ? str_time(time, -1, NULL) : timestr(current_time - time,
false));
}
void read_time(FileData * fp, time_t * tptr)
{
*tptr = read_long(fp);
read_to_eol(fp);
}
void read_dice(FileData * fp, int *dice)
{
int i;
for (i = 0; i < DICE_MAX - 1; i++)
{
dice[i] = read_number(fp);
read_letter(fp);
}
dice[i] = read_number(fp);
}
void write_dice(FileData * fp, int *dice)
{
int i;
for (i = 0; i < DICE_MAX - 1; i++)
{
f_printf(fp, "%dd", dice[i]);
}
f_printf(fp, "%d", dice[i]);
}
bool is_space(char c)
{
if (isspace(c))
{
switch (c)
{
case CUSTOMSTART:
case CUSTOMEND:
case MXP_BEGc:
case MXP_ENDc:
return false;
default:
return true;
}
}
else
return false;
}
#define MLR (MAX_STRING_LENGTH * 25)
const char *read_file(FileData * fp)
{
char buf[MLR + 2];
char c;
size_t i = 0;
bool sFull = false;
memset(buf, 0, sizeof(buf));
for (;;)
{
if (i >= MLR && !sFull)
{
bugf("file size exceeded %d maximum.", MLR);
sFull = true;
}
switch (c = f_getc(fp))
{
default:
if (!sFull)
{
buf[i] = c;
i++;
}
break;
case '\n':
if (!sFull)
{
buf[i] = '\n';
i++;
buf[i] = '\r';
i++;
}
break;
case '\r':
break;
case NUL:
return str_dup(buf);
}
}
}
FILE *file_open(const char *file, const char *mode)
{
FILE *fp;
if (fpReserve != NULL)
{
fclose(fpReserve);
fpReserve = NULL;
}
if (!(fp = fopen(file, mode)))
{
fpReserve = fopen(NULL_FILE, "r");
return NULL;
}
return fp;
}
void file_close(FILE * fp)
{
if (fp != NULL)
{
fflush(fp);
fclose(fp);
}
fp = NULL;
if (fpReserve == NULL)
fpReserve = fopen(NULL_FILE, "r");
}
char read_letter(FileData * fp)
{
char c;
do
{
c = f_getc(fp);
}
while (is_space(c));
return c;
}
int read_number(FileData * fp)
{
int number;
bool sign;
char c;
do
{
c = f_getc(fp);
}
while (is_space(c));
number = 0;
sign = false;
if (c == '+')
{
c = f_getc(fp);
}
else if (c == '-')
{
sign = true;
c = f_getc(fp);
}
if (!isdigit(c))
{
bugf("bad format '%c'... %s.", c,
AttemptJump ? "attempting longjmp" : "aborting");
if (AttemptJump)
{
longjmp(jump_env, 1);
}
else
abort();
}
while (isdigit(c))
{
number = number * 10 + c - '0';
c = f_getc(fp);
}
if (sign)
number = 0 - number;
if (c == '|')
number += read_number(fp);
else if (c != ' ')
f_ungetc(c, fp);
return number;
}
long read_long(FileData * fp)
{
long number;
bool sign;
char c;
do
{
c = f_getc(fp);
}
while (is_space(c));
number = 0;
sign = false;
if (c == '+')
{
c = f_getc(fp);
}
else if (c == '-')
{
sign = true;
c = f_getc(fp);
}
if (!isdigit(c))
{
bugf("bad format '%c'... %s.", c,
AttemptJump ? "attempting longjmp" : "aborting");
if (AttemptJump)
{
longjmp(jump_env, 1);
}
else
abort();
}
while (isdigit(c))
{
number = number * 10 + c - '0';
c = f_getc(fp);
}
if (sign)
number = 0 - number;
if (c == '|')
number += read_long(fp);
else if (c != ' ')
f_ungetc(c, fp);
return number;
}
flag_t read_flag(FileData * fp)
{
flag_t number;
flag_t flag;
flag_t temp = 1;
char c;
bool negative = false;
do
{
c = f_getc(fp);
}
while (is_space(c));
if (c != '+')
{
if (c == '-')
{
negative = true;
c = f_getc(fp);
}
number = 0;
if (!isdigit(c))
{
while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
number += flag_convert(c);
c = f_getc(fp);
}
}
while (isdigit(c))
{
number = number * 10 + c - '0';
c = f_getc(fp);
}
if (c == '|')
number += read_flag(fp);
else if (c != ' ')
f_ungetc(c, fp);
if (negative)
return -1 * number;
return number;
}
else
{
number = 0;
flag = 0;
do
{
c = f_getc(fp);
flag += (temp << number) * (c == 'Y');
number++;
}
while (c == 'Y' || c == 'n');
if (c == '\n' || c == '\r')
f_ungetc(c, fp);
return flag;
}
}
void read_to_eol(FileData * fp)
{
char c;
do
{
c = f_getc(fp);
}
while (c != '\n' && c != '\r');
do
{
c = f_getc(fp);
}
while (c == '\n' || c == '\r');
f_ungetc(c, fp);
return;
}
char *read_word(FileData * fp)
{
static char word[MIL];
char *pword;
char cEnd;
do
{
if (f_eof(fp))
{
bug("EOF encountered on read.");
if (run_level == RUNLEVEL_BOOTING)
exit(1);
word[0] = NUL;
return word;
}
cEnd = f_getc(fp);
}
while (is_space(cEnd));
if (cEnd == '\'' || cEnd == '"')
{
pword = word;
}
else
{
word[0] = cEnd;
pword = word + 1;
cEnd = ' ';
}
for (; pword < word + MIL; pword++)
{
*pword = f_getc(fp);
if (cEnd == ' ' ? is_space(*pword) : *pword == cEnd)
{
if (cEnd == ' ')
f_ungetc(*pword, fp);
*pword = NUL;
return word;
}
}
bugf("word too long... %s.",
AttemptJump ? "attempting longjmp" : "aborting");
if (AttemptJump)
{
longjmp(jump_env, 1);
}
else
abort();
return NULL;
}
const char *read_string(FileData * fp)
{
static char buf[MLR + 2];
size_t i = 0;
register char c;
bool sFull = false;
do
{
c = f_getc(fp);
}
while (is_space(c));
if (c == '~')
return str_dup("");
buf[i++] = c;
for (;;)
{
if (i >= MLR && !sFull)
{
bugf("String [%20.20s...] exceeded [%d] MLR", buf, MLR);
sFull = true;
}
switch (c = f_getc(fp))
{
default:
if (!sFull)
{
buf[i++] = c;
}
break;
case NUL:
bugf("EOF reached... %s.",
AttemptJump ? "attempting longjmp" : "aborting");
if (AttemptJump)
{
longjmp(jump_env, 1);
}
else
abort();
break;
case '\n':
if (!sFull)
{
buf[i++] = '\n';
buf[i++] = '\r';
}
break;
case '\r':
break;
case '~':
buf[i] = NUL;
return str_dup(buf);
break;
}
}
}
void read_strfree(FileData * fp, const char **pstr)
{
free_string(*pstr);
*pstr = read_string(fp);
}
const char *read_line(FileData * fp)
{
static char line[MSL];
char *pline;
char c;
int ln;
pline = line;
line[0] = NUL;
ln = 0;
do
{
if (f_eof(fp))
{
bug("EOF encountered on read.");
strcpy(line, "");
return line;
}
c = f_getc(fp);
}
while (is_space(c));
f_ungetc(c, fp);
do
{
if (f_eof(fp))
{
bug("EOF encountered on read.");
*pline = NUL;
return line;
}
c = f_getc(fp);
*pline++ = c;
ln++;
if (ln >= (MSL - 1))
{
bug("line too long");
break;
}
}
while (c != '\n' && c != '\r');
do
{
c = f_getc(fp);
}
while (c == '\n' || c == '\r');
f_ungetc(c, fp);
*pline = NUL;
return line;
}
#ifdef STFILEIO
stFile *stopen(const char *file, const char *mode)
{
struct stat buf;
FileData *stfp;
if (NullStr(file))
return NULL;
stfp = new_stfile();
if (stfp == NULL)
return NULL;
stfp->file = str_dup(file);
stfp->mode = str_dup(mode);
if (mode[0] == NUL || tolower(mode[0]) == 'r')
{
if (stat(file, &buf) == -1 || !S_ISREG(buf.st_mode))
{
free_stfile(stfp);
return NULL;
}
if ((stfp->stream = file_open(file, mode)) == NULL)
{
free_stfile(stfp);
return NULL;
}
stfp->pos = 0;
stfp->size = buf.st_size;
alloc_mem(stfp->str, char, stfp->size + 1);
fread(stfp->str, stfp->size + 1, 1, stfp->stream);
stfp->str[stfp->size] = NUL;
}
else
{
static int count = 0;
++count, count %= 999;
#if !defined WIN32 && !defined __CYGWIN__
stfp->temp = str_dupf("%s.tmp%03d", stfp->file, count);
if ((stfp->stream = file_open(stfp->temp, mode)) == NULL)
#else
if ((stfp->stream = file_open(stfp->file, mode)) == NULL)
#endif
{
free_stfile(stfp);
return NULL;
}
}
Link(stfp, stfile, next, prev);
return stfp;
}
int stclose(stFile * fp)
{
#if !defined WIN32 && !defined __CYGWIN__
if (!NullStr(fp->temp) && rename(fp->temp, fp->file) == -1)
{
bugf("error renaming %s -> %s", fp->temp, fp->file);
}
#endif
free_stfile(fp);
fp = NULL;
return 0;
}
int stflush(stFile * fp)
{
if (fp != NULL)
{
if (!NullStr(fp->mode) && fp->mode[0] != 'r')
{
fprintf(fp->stream, "%s\n", fp->str);
}
fflush(fp->stream);
}
else
for (fp = stfile_first; fp; fp = fp->next)
stflush(fp);
return 0;
}
int steof(FileData * fp)
{
return (fp->pos >= fp->size) ? EOF : 0;
}
int stgetc(FileData * fp)
{
char c = fp->str[fp->pos];
if (!steof(fp))
fp->pos++;
return c;
}
int stungetc(int c, stFile * fp)
{
if (fp->pos > 0)
fp->pos--;
return fp->str[fp->pos];
}
size_t stread(void *ptr, size_t size, size_t nmemb, stFile * fp)
{
size_t nsize;
if (!fp->str || steof(fp))
return 0;
nsize = Min(fp->pos + size, fp->size);
memcpy(ptr, &fp->str[fp->pos], nsize);
return nsize;
}
int stprintf(stFile * fp, const char *fmt, ...)
{
va_list args;
int len;
if (!fp || NullStr(fmt) || NullStr(fp->mode)
|| tolower(fp->mode[0]) == 'r' || !fp->stream)
return 0;
va_start(args, fmt);
len = vfprintf(fp->stream, fmt, args);
va_end(args);
return len;
}
int stseek(stFile * fp, long offset, int whence)
{
if (!fp)
return -1;
switch (whence)
{
case SEEK_SET:
fp->pos = 0;
break;
default:
case SEEK_CUR:
break;
case SEEK_END:
fp->pos = fp->size;
break;
}
if (fp->pos + offset < 0 || fp->pos + offset >= fp->size)
return -1;
fp->pos += offset;
return 0;
}
#endif