Logo Search packages:      
Sourcecode: jnethack version File versions  Download package

makedefs.c

/*    SCCS Id: @(#)makedefs.c 3.2   96/10/29    */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) M. Stephenson, 1990, 1991.                   */
/* Copyright (c) Dean Luick, 1990.                      */
/* NetHack may be freely redistributed.  See license for details. */

/*
**    Japanese version Copyright (c) Issei Numata 1994-1999
**    changing point is marked `JP' (94/1/6)
**    JNetHack may be freely redistributed.  See license for details. 
*/

#define MAKEDEFS_C      /* use to conditionally include file sections */
/* #define DEBUG /* uncomment for debugging info */

#include "config.h"
#include "permonst.h"
#include "objclass.h"
#include "monsym.h"
#include "artilist.h"
#include "dungeon.h"
#include "obj.h"
#include "monst.h"
#include "you.h"
#include "flag.h"
#include "dlb.h"

/* version information */
#ifdef SHORT_FILENAMES
#include "patchlev.h"
#include "../japanese/jpatchle.h"
#else
#include "patchlevel.h"
/*JP*/
#include "../japanese/jpatchlevel.h"
#endif

#ifdef NEWSOS4
#include <ctype.h>
#endif

#ifdef MAC
# ifdef applec    /* Means the MPW compiler, I hope */
#  define MPWTOOL
#include <CursorCtl.h>
#include <string.h>
#include <ctype.h>
# else            /* MAC without MPWTOOL */
#  define MACsansMPWTOOL
# endif
#endif /* MAC */

#ifndef MPWTOOL
# define SpinCursor(x)
#endif

#define Fprintf   (void) fprintf
#define Fclose    (void) fclose
#define Unlink    (void) unlink
#if !defined(AMIGA) || defined(AZTEC_C)
#define rewind(fp) fseek((fp),0L,SEEK_SET)      /* guarantee a return value */
#endif

#if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN)
static      const char  SCCS_Id[] = "@(#)makedefs.c\t3.2\t95/06/10";
#endif

      /* names of files to be generated */
#define DATE_FILE "date.h"
#define MONST_FILE      "pm.h"
#define ONAME_FILE      "onames.h"
#define OPTIONS_FILE    "options"
/*JP
#define ORACLE_FILE     "oracles"
*/
#define ORACLE_FILE     "joracles"
#define DATA_FILE "data"
/*JP
#define RUMOR_FILE      "rumors"
*/
#define RUMOR_FILE      "jrumors"
#define DGN_I_FILE      "dungeon.def"
#define DGN_O_FILE      "dungeon.pdf"
#define MON_STR_C "monstr.c"
#define QTXT_I_FILE     "quest.txt"
#define QTXT_O_FILE     "quest.dat"
#define VIS_TAB_H "vis_tab.h"
#define VIS_TAB_C "vis_tab.c"
/*
** JP
*/
#define JOBJ_FILE "jtrnsobj.dat"
#define JMON_FILE "jtrnsmon.dat"
#define JDATA           "jdata.h"

      /* locations for those files */
#ifdef AMIGA
# define FILE_PREFIX
# define INCLUDE_TEMPLATE     "NH:include/t.%s"
# define SOURCE_TEMPLATE      "NH:src/%s"
# define DGN_TEMPLATE         "NH:dat/%s"  /* where dungeon.pdf file goes */
# define DATA_TEMPLATE        "NH:slib/%s"
# define DATA_IN_TEMPLATE     "NH:dat/%s"
#else
# ifdef MAC
#   define INCLUDE_TEMPLATE   ":include:%s"
#   define SOURCE_TEMPLATE    ":src:%s"
#   define DGN_TEMPLATE       ":dat:%s"  /* where dungeon.pdf file goes */
#   define DATA_TEMPLATE      ":lib:%s"
#   define DATA_IN_TEMPLATE   ":dat:%s"
# else /* MAC */
#  ifdef OS2
#   define INCLUDE_TEMPLATE   "..\\include\\%s"
#   define SOURCE_TEMPLATE    "..\\src\\%s"
#   define DGN_TEMPLATE       "..\\dat\\%s"  /* where dungeon.pdf file goes */
#   define DATA_TEMPLATE      "..\\dat\\%s"
#   define DATA_IN_TEMPLATE   "..\\dat\\%s"
#  else /* OS2 */
#   define INCLUDE_TEMPLATE   "../include/%s"
#   define SOURCE_TEMPLATE    "../src/%s"
#   define DGN_TEMPLATE       "../dat/%s"  /* where dungeon.pdf file goes */
#   define DATA_TEMPLATE      "../dat/%s"
#   define DATA_IN_TEMPLATE   "../dat/%s"
#  endif /* OS2 */
# endif /* MAC */
#endif      /* AMIGA */

static const char
    *Dont_Edit_Code =
      "/* This source file is generated by 'makedefs'.  Do not edit. */\n",
    *Dont_Edit_Data =
      "#\tThis data file is generated by 'makedefs'.  Do not edit. \n";

static struct version_info version;
static struct version_info jversion;

/* definitions used for vision tables */
#define TEST_WIDTH  COLNO
#define TEST_HEIGHT ROWNO
#define BLOCK_WIDTH (TEST_WIDTH + 10)
#define BLOCK_HEIGHT TEST_HEIGHT    /* don't need extra spaces */
#define MAX_ROW (BLOCK_HEIGHT + TEST_HEIGHT)
#define MAX_COL (BLOCK_WIDTH + TEST_WIDTH)
/* Use this as an out-of-bound value in the close table.  */
#define CLOSE_OFF_TABLE_STRING "99" /* for the close table */
#define FAR_OFF_TABLE_STRING "0xff" /* for the far table */

#define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0))
#ifdef VISION_TABLES
static char xclear[MAX_ROW][MAX_COL];
#endif
/*-end of vision defs-*/

static char in_line[256], filename[60];

#ifdef FILE_PREFIX
            /* if defined, a first argument not starting with - is
             * taken as a text string to be prepended to any
             * output filename generated */
char *file_prefix="";
#endif

#ifdef MACsansMPWTOOL
int FDECL(main, (void));
#else
int FDECL(main, (int,char **));
#endif
void FDECL(do_makedefs, (char *));
void NDECL(do_objs);
void NDECL(do_data);
void NDECL(do_dungeon);
void NDECL(do_date);
void NDECL(do_options);
void NDECL(do_monstr);
void NDECL(do_permonst);
void NDECL(do_questtxt);
void NDECL(do_rumors);
void NDECL(do_oracles);
void NDECL(do_vision);
/*JP*/
void NDECL(do_japanese);

extern void NDECL(monst_init);            /* monst.c */
extern void NDECL(objects_init);    /* objects.c */

static void NDECL(make_version);
static char *FDECL(version_id_string, (char *,const char *));
/*JP*/
static char *FDECL(jversion_id_string, (char *,const char *));
static char *FDECL(xcrypt, (const char *));
static int FDECL(check_control, (char *));
static char *FDECL(without_control, (char *));
static boolean FDECL(d_filter, (char *));
static boolean FDECL(h_filter, (char *));
static boolean FDECL(ranged_attk,(struct permonst*));
static int FDECL(mstrength,(struct permonst *));

static boolean FDECL(qt_comment, (char *));
static boolean FDECL(qt_control, (char *));
static int FDECL(get_hdr, (CHAR_P));
static boolean FDECL(known_id, (CHAR_P));
static boolean FDECL(new_id, (CHAR_P));
static boolean FDECL(known_msg, (CHAR_P,char *));
static void FDECL(new_msg, (char *));
static void FDECL(do_qt_control, (char *));
static void FDECL(do_qt_text, (char *));
static void NDECL(adjust_qt_hdrs);
static void NDECL(put_qt_hdrs);

#ifdef VISION_TABLES
static void NDECL(H_close_gen);
static void NDECL(H_far_gen);
static void NDECL(C_close_gen);
static void NDECL(C_far_gen);
static int FDECL(clear_path, (int,int,int,int));
#endif

static char *FDECL(tmpdup, (const char *));
static char *FDECL(limit, (char *,int));
static char *FDECL(eos, (char *));

/* input, output, tmp */
static FILE *ifp, *ofp, *tfp;

#ifdef __BORLANDC__
extern unsigned _stklen = STKSIZ;
#endif


#ifdef MACsansMPWTOOL
int
main(void)
{
    const char *def_options = "odemvpqrhz";
    char buf[100];
    int len;

    printf("Enter options to run: [%s] ", def_options);
    fflush(stdout);
    fgets(buf, 100, stdin);
    len = strlen(buf);
    if (len <= 1)
      Strcpy(buf, def_options);
    else
      buf[len-1] = 0;               /* remove return */

    do_makedefs(buf);
    exit(EXIT_SUCCESS);
    return 0;
}

#else /* ! MAC */

int
/*Er __cdecl        */
main(int argc, char **argv)
{
      if ( (argc != 2)
#ifdef FILE_PREFIX
            && (argc != 3)
#endif
      ) {
          Fprintf(stderr, "Bad arg count (%d).\n", argc-1);
          (void) fflush(stderr);
          return 1;
      }

#ifdef FILE_PREFIX
      if(argc >=2 && argv[1][0]!='-'){
          file_prefix=argv[1];
          argc--;argv++;
      }
#endif
      do_makedefs(&argv[1][1]);
      exit(EXIT_SUCCESS);
      /*NOTREACHED*/
      return 0;
}

#endif

void
do_makedefs(options)
char  *options;
{
      boolean more_than_one;

      /* Note:  these initializers don't do anything except guarantee that
            we're linked properly.
      */
      monst_init();
      objects_init();

      /* construct the current version number */
      make_version();


      more_than_one = strlen(options) > 1;
      while (*options) {
          if (more_than_one)
            Fprintf(stderr, "makedefs -%c\n", *options);

          switch (*options) {
            case 'o':
            case 'O':   do_objs();
                        break;
            case 'd':
            case 'D':   do_data();
                        break;
            case 'e':
            case 'E':   do_dungeon();
                        break;
            case 'm':
            case 'M':   do_monstr();
                        break;
            case 'v':
            case 'V':   do_date();
                        do_options();
                        break;
            case 'p':
            case 'P':   do_permonst();
                        break;
            case 'q':
            case 'Q':   do_questtxt();
                        break;
            case 'r':
            case 'R':   do_rumors();
                        break;
            case 'h':
            case 'H':   do_oracles();
                        break;
            case 'z':
            case 'Z':   do_vision();
                        break;
/*JP*/
            case 'j':
            case 'J':   do_japanese();
                        break;

            default:    Fprintf(stderr,   "Unknown option '%c'.\n",
                              *options);
                        (void) fflush(stderr);
                        exit(EXIT_FAILURE);
            
          }
          options++;
      }
      if (more_than_one) Fprintf(stderr, "Completed.\n");   /* feedback */

}


/* trivial text encryption routine which can't be broken with `tr' */
static
char *xcrypt(const char *str)
{                       /* duplicated in src/hacklib.c */
      static char buf[BUFSZ];
      register const char *p;
      register char *q;
      register int bitmask;

      for (bitmask = 1, p = str, q = buf; *p; q++) {
            *q = *p++;
            if (*q & (32|64)) *q ^= bitmask;
            if ((bitmask <<= 1) >= 32) bitmask = 1;
      }
      *q = '\0';
      return buf;
}

void
do_rumors(void)
{
      char  infile[60];
      long  true_rumor_size;

      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename,file_prefix);
#endif
      Sprintf(eos(filename), DATA_TEMPLATE, RUMOR_FILE);
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }
      Fprintf(ofp,Dont_Edit_Data);

      Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
      Strcat(infile, ".tru");
      if (!(ifp = fopen(infile, RDTMODE))) {
            perror(infile);
            Fclose(ofp);
            Unlink(filename); /* kill empty output file */
            exit(EXIT_FAILURE);
      }
      /* get size of true rumors file */
#ifndef VMS
      (void) fseek(ifp, 0L, SEEK_END);
      true_rumor_size = ftell(ifp);
#else
      /* seek+tell is only valid for stream format files; since rumors.%%%
         might be in record format, count the actual data bytes instead.
       */
      true_rumor_size = 0;
      while (fgets(in_line, sizeof in_line, ifp) != 0)
            true_rumor_size += strlen(in_line); /* includes newline */
#endif /* VMS */
      Fprintf(ofp,"%06lx\n", true_rumor_size);
      (void) fseek(ifp, 0L, SEEK_SET);

      /* copy true rumors */
      while (fgets(in_line, sizeof in_line, ifp) != 0)
            (void) fputs(xcrypt(in_line), ofp);


      Fclose(ifp);

      Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
      Strcat(infile, ".fal");
      if (!(ifp = fopen(infile, RDTMODE))) {
            perror(infile);
            Fclose(ofp);
            Unlink(filename); /* kill incomplete output file */
            exit(EXIT_FAILURE);
      }

      /* copy false rumors */
      while (fgets(in_line, sizeof in_line, ifp) != 0)
            (void) fputs(xcrypt(in_line), ofp);

      Fclose(ifp);
      Fclose(ofp);
      return;
}

static void
make_version(void)
{
/*JP*/
      register int i;

      /*
       * integer version number
       */
      version.incarnation = ((unsigned long)VERSION_MAJOR << 24) |
                        ((unsigned long)VERSION_MINOR << 16) |
                        ((unsigned long)PATCHLEVEL << 8) |
                        ((unsigned long)EDITLEVEL);
      jversion.incarnation = ((long)JVERSION_MAJOR << 24) |
                        ((long)JVERSION_MINOR << 16) |
                        ((long)JPATCHLEVEL << 8) |
                        ((long)JEDITLEVEL);

      /*
       * encoded feature list
       * Note:  if any of these magic numbers are changed or reassigned,
       * EDITLEVEL in patchlevel.h should be incremented at the same time.
       * The actual values have no special meaning, and the category
       * groupings are just for convenience.
       */
      version.feature_set = (unsigned long)(0L
            /* levels and/or topology (0..4) */
#ifdef REINCARNATION
                  | (1L <<  1)
#endif
#ifdef SINKS
                  | (1L <<  2)
#endif
            /* monsters (5..9) */
#ifdef KOPS
                  | (1L <<  6)
#endif
#ifdef MAIL
                  | (1L <<  7)
#endif
            /* objects (10..14) */
#ifdef TOURIST
                  | (1L << 10)
#endif
            /* flag bits and/or other global variables (15..26) */
#ifdef TEXTCOLOR
                  | (1L << 17)
#endif
#ifdef INSURANCE
                  | (1L << 18)
#endif
#ifdef ELBERETH
                  | (1L << 19)
#endif
#ifdef EXP_ON_BOTL
                  | (1L << 20)
#endif
#ifdef SCORE_ON_BOTL
                  | (1L << 21)
#endif
#ifdef WEAPON_SKILLS
                  | (1L << 22)
#endif
#ifdef TIMED_DELAY
                  | (1L << 23)
#endif
            /* data format [COMPRESS excluded] (27..31) */
#ifdef ZEROCOMP
                  | (1L << 27)
#endif
#ifdef RLECOMP
                  | (1L << 28)
#endif
                  );
      /*
       * Value used for object & monster sanity check.
       *    (NROFARTIFACTS<<24) | (NUM_OBJECTS<<12) | (NUMMONS<<0)
       */
      for (i = 1; artifact_names[i]; i++) continue;
      version.entity_count = (unsigned long)(i - 1);
      for (i = 1; objects[i].oc_class != ILLOBJ_CLASS; i++) continue;
      version.entity_count = (version.entity_count << 12) | (unsigned long)i;
      for (i = 0; mons[i].mlet; i++) continue;
      version.entity_count = (version.entity_count << 12) | (unsigned long)i;
      /*
       * Value used for compiler (word size/field alignment/padding) check.
       */
      version.struct_sizes = (((unsigned long)sizeof (struct flag)  << 24) |
                        ((unsigned long)sizeof (struct obj)   << 17) |
                        ((unsigned long)sizeof (struct monst) << 10) |
                        ((unsigned long)sizeof (struct you)));
      return;
}

/* this code used to be in src/version.c */
static char *
version_id_string(outbuf, build_date)
char *outbuf;
const char *build_date;
{
      Sprintf(outbuf,
#ifdef BETA
# ifdef PORT_SUB_ID
            "%s NetHack %s Beta Version %d.%d.%d-%d - last build %s.",
# else
            "%s NetHack Beta Version %d.%d.%d-%d - last build %s.",
# endif
#else
# ifdef PORT_SUB_ID
            "%s NetHack %s Version %d.%d.%d - last build %s.",
# else
            "%s NetHack Version %d.%d.%d - last build %s.",
# endif
#endif
            PORT_ID,
#ifdef PORT_SUB_ID
            PORT_SUB_ID,
#endif
            VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
#ifdef BETA
            EDITLEVEL,
#endif
            build_date);
      return outbuf;
}

/*JP*/
static char *
jversion_id_string(outbuf, build_date)
char *outbuf;
const char *build_date;
{
      Sprintf(outbuf,
#ifdef BETA
# ifdef PORT_SUB_ID
            "%s JNetHack %s Beta Version %d.%d.%d-%d - last build %s.",
# else
            "%s JNetHack Beta Version %d.%d.%d-%d - last build %s.",
# endif
#else
# ifdef PORT_SUB_ID
            "%s JNetHack %s Version %d.%d.%d - last build %s.",
# else
            "%s JNetHack Version %d.%d.%d - last build %s.",
# endif
#endif
            PORT_ID,
#ifdef PORT_SUB_ID
            PORT_SUB_ID,
#endif
            JVERSION_MAJOR, JVERSION_MINOR, JPATCHLEVEL,
#ifdef BETA
            JEDITLEVEL,
#endif
            build_date);
      return outbuf;
}

void
do_date(void)
{
      long clocktim = 0;
      char *c, cbuf[60], buf[BUFSZ];
      const char *ul_sfx;

      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename,file_prefix);
#endif
      Sprintf(eos(filename), INCLUDE_TEMPLATE, DATE_FILE);
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }
      Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.2\t96/05/17 */\n\n");
      Fprintf(ofp,Dont_Edit_Code);

#ifdef KR1ED
      (void) time(&clocktim);
/*JP*/
      Fprintf(ofp,"#define JVERSION_NUMBER 0x%08lxL\n", jversion.incarnation);
      Strcpy(cbuf, ctime(&clocktim));
#else
      (void) time((time_t *)&clocktim);
      Strcpy(cbuf, ctime((time_t *)&clocktim));
#endif
      for (c = cbuf; *c != '\n'; c++) continue;
      *c = 0;     /* strip off the '\n' */
      Fprintf(ofp,"#define BUILD_DATE \"%s\"\n", cbuf);
      Fprintf(ofp,"#define BUILD_TIME (%ldL)\n", clocktim);
      Fprintf(ofp,"\n");
#ifdef NHSTDC
      ul_sfx = "UL";
#else
      ul_sfx = "L";
#endif
      Fprintf(ofp,"#define VERSION_NUMBER 0x%08lx%s\n",
            version.incarnation, ul_sfx);
      Fprintf(ofp,"#define VERSION_FEATURES 0x%08lx%s\n",
            version.feature_set, ul_sfx);
      Fprintf(ofp,"#define VERSION_SANITY1 0x%08lx%s\n",
            version.entity_count, ul_sfx);
      Fprintf(ofp,"#define VERSION_SANITY2 0x%08lx%s\n",
            version.struct_sizes, ul_sfx);
      Fprintf(ofp,"\n");
      Fprintf(ofp,"#define VERSION_ID \\\n \"%s\"\n",
            version_id_string(buf, cbuf));
/*JP*/
      Fprintf(ofp,"#define JVERSION_ID \\\n \"%s\"\n",
            jversion_id_string(buf, cbuf));
      Fprintf(ofp,"\n");
#ifdef AMIGA
      {
      struct tm *tm = localtime((time_t *) &clocktim);
      Fprintf(ofp,"#define AMIGA_VERSION_STRING ");
      Fprintf(ofp,"\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n",
            VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
            tm->tm_mday, tm->tm_mon+1, tm->tm_year);
      }
#endif
      Fclose(ofp);
      return;
}

static const char *build_opts[] = {
#ifdef AMIGA_WBENCH
            "Amiga WorkBench support",
#endif
#ifdef ANSI_DEFAULT
            "ANSI default terminal",
#endif
#ifdef TEXTCOLOR
            "color",
#endif
#ifdef COM_COMPL
            "command line completion",
#endif
#ifdef COMPRESS
            "data file compression",
#endif
#ifdef DLB
            "data librarian",
#endif
#ifdef WIZARD
            "debug mode",
#endif
#ifdef ELBERETH
            "Elbereth",
#endif
#ifdef EXP_ON_BOTL
            "experience points on status line",
#endif
#ifdef FIGHTER
            "fighter",
#endif
#ifdef MFLOPPY
            "floppy drive support",
#endif
#ifdef INSURANCE
            "insurance files for recovering from crashes",
#endif
#ifdef KOPS
            "Keystone Kops",
#endif
#ifdef LOGFILE
            "log file",
#endif
#ifdef MAIL
            "mail daemon",
#endif
#ifdef GNUDOS
            "MSDOS protected mode",
#endif
#ifdef NEWS
            "news file",
#endif
#ifdef OVERLAY
# ifdef MOVERLAY
            "MOVE overlays",
# else
#  ifdef VROOMM
            "VROOMM overlays",
#  else
            "overlays",
#  endif
# endif
#endif
#ifdef REDO
            "redo command",
#endif
#ifdef REINCARNATION
            "rogue level",
#endif
#ifdef SCORE_ON_BOTL
            "score on status line",
#endif
#ifdef CLIPPING
            "screen clipping",
#endif
#ifdef NO_TERMS
# ifdef MAC
            "screen control via mactty",
# endif
# ifdef SCREEN_8514
            "screen control via 8514/A graphics",
# endif
# ifdef SCREEN_BIOS
            "screen control via BIOS",
# endif
# ifdef SCREEN_DJGPPFAST
            "screen control via DJGPP fast",
# endif
# ifdef SCREEN_VESA
            "screen control via VESA graphics",
# endif
# ifdef SCREEN_VGA
            "screen control via VGA graphics",
# endif
# ifdef WIN32CON
            "screen control via WIN32 console I/O",
# endif
#endif
#ifdef SEDUCE
            "seduction",
#endif
#ifdef SHELL
            "shell command",
#endif
#ifdef SINKS
            "sinks",
#endif
#ifdef SUSPEND
            "suspend command",
#endif
#ifdef TERMINFO
            "terminal info library",
#else
# if defined(TERMLIB) || (!defined(MICRO) && defined(TTY_GRAPHICS))
            "terminal capability library",
# endif
#endif
#ifdef TIMED_DELAY
            "timed wait for display effects",
#endif
#ifdef TOURIST
            "tourists",
#endif
#ifdef VISION_TABLES
            "vision tables",
#endif
#ifdef WALLIFIED_MAZE
            "walled mazes",
#endif
#ifdef WEAPON_SKILLS
            "weapon proficiency",
#endif
#ifdef ZEROCOMP
            "zero-compressed save files",
#endif
            "basic NetHack features"
      };

static const char *window_opts[] = {
#ifdef TTY_GRAPHICS
            "traditional tty-based graphics",
#endif
#ifdef X11_GRAPHICS
            "X11",
#endif
#ifdef MAC
            "Mac",
#endif
#ifdef AMIGA_INTUITION
            "Amiga Intuition",
#endif
#ifdef WIN32_GRAPHICS
            "Win32",
#endif
            0
      };

void
do_options(void)
{
      register int i, length;
      register const char *str, *indent = "    ";

      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename,file_prefix);
#endif
      Sprintf(eos(filename), DATA_TEMPLATE, OPTIONS_FILE);
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }

      Fprintf(ofp,
#ifdef BETA
            "\n    NetHack version %d.%d.%d [beta]\n",
#else
            "\n    NetHack version %d.%d.%d\n",
#endif
            VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);

      Fprintf(ofp,"\nOptions compiled into this edition:\n");

      length = COLNO + 1;     /* force 1st item onto new line */
      for (i = 0; i < SIZE(build_opts); i++) {
          str = build_opts[i];
          if (length + strlen(str) > COLNO - 5)
            Fprintf(ofp,"\n%s", indent),  length = strlen(indent);
          else
            Fprintf(ofp," "),  length++;
          Fprintf(ofp,"%s", str),  length += strlen(str);
          Fprintf(ofp,(i < SIZE(build_opts) - 1) ? "," : "."),  length++;
      }

      Fprintf(ofp,"\n\nSupported windowing systems:\n");

      length = COLNO + 1;     /* force 1st item onto new line */
      for (i = 0; i < SIZE(window_opts) - 1; i++) {
          str = window_opts[i];
          if (length + strlen(str) > COLNO - 5)
            Fprintf(ofp,"\n%s", indent),  length = strlen(indent);
          else
            Fprintf(ofp," "),  length++;
          Fprintf(ofp,"%s", str),  length += strlen(str);
          Fprintf(ofp, ","),  length++;
      }
      Fprintf(ofp, "\n%swith a default of %s.", indent, DEFAULT_WINDOW_SYS);

/*JP*/
/* internal kcode */
/* IC=0 EUC */
/* IC=1 SJIS */
#define IC ((unsigned char)("漢"[0])==0x8a)

      Fprintf(ofp,"\n\nInternal Kanji Code:\n\n");
      Fprintf(ofp,"%s%s\n", indent, IC ? "SJIS" : "EUC");

      Fprintf(ofp,"\n\n");

      Fclose(ofp);
      return;
}

/* routine to decide whether to discard something from data.base */
static boolean
d_filter(char *line)
{
    if (*line == '#') return TRUE;  /* ignore comment lines */
    return FALSE;
}

   /*
    *
      New format (v3.1) of 'data' file which allows much faster lookups [pr]
"do not edit"           first record is a comment line
01234567          hexadecimal formatted offset to text area
name-a                  first name of interest
123,4             offset to name's text, and number of lines for it
name-b                  next name of interest
name-c                  multiple names which share same description also
456,7             share a single offset,count line
.                 sentinel to mark end of names
789,0             dummy record containing offset, count of EOF
text-a                  4 lines of descriptive text for name-a
text-a                  at file position 0x01234567L + 123L
text-a
text-a
text-b/text-c           7 lines of text for names-b and -c
text-b/text-c           at fseek(0x01234567L + 456L)
...
    *
    */

void
do_data(void)
{
      char  infile[60], tempfile[60];
      boolean ok;
      long  txt_offset;
      int   entry_cnt, line_cnt;

      Sprintf(tempfile, DATA_TEMPLATE, "database.tmp");
      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename,file_prefix);
#endif
      Sprintf(eos(filename), DATA_TEMPLATE, DATA_FILE);
      Sprintf(infile, DATA_IN_TEMPLATE, DATA_FILE);
      Strcat(infile,
#ifdef SHORT_FILENAMES
            ".bas"
#else
            ".base"
#endif
            );
      if (!(ifp = fopen(infile, RDTMODE))) {          /* data.base */
            perror(infile);
            exit(EXIT_FAILURE);
      }
      if (!(ofp = fopen(filename, WRTMODE))) {  /* data */
            perror(filename);
            Fclose(ifp);
            exit(EXIT_FAILURE);
      }
      if (!(tfp = fopen(tempfile, WRTMODE))) {  /* database.tmp */
            perror(tempfile);
            Fclose(ifp);
            Fclose(ofp);
            Unlink(filename);
            exit(EXIT_FAILURE);
      }

      /* output a dummy header record; we'll rewind and overwrite it later */
      Fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, 0L);

      entry_cnt = line_cnt = 0;
      /* read through the input file and split it into two sections */
      while (fgets(in_line, sizeof in_line, ifp)) {
/*JP*/
          unsigned char uc;
          uc = *((unsigned char *)in_line);
          if (d_filter(in_line)) continue;
/*JP      if (*in_line > ' ') {     /* got an entry name */
          if (uc > ' ') {     /* got an entry name */
            /* first finish previous entry */
            if (line_cnt)  Fprintf(ofp, "%d\n", line_cnt),  line_cnt = 0;
            /* output the entry name */
            (void) fputs(in_line, ofp);
            entry_cnt++;            /* update number of entries */
          } else if (entry_cnt) {   /* got some descriptive text */
            /* update previous entry with current text offset */
            if (!line_cnt)  Fprintf(ofp, "%ld,", ftell(tfp));
            /* save the text line in the scratch file */
            (void) fputs(in_line, tfp);
            line_cnt++;       /* update line counter */
          }
      }
      /* output an end marker and then record the current position */
      if (line_cnt)  Fprintf(ofp, "%d\n", line_cnt);
      Fprintf(ofp, ".\n%ld,%d\n", ftell(tfp), 0);
      txt_offset = ftell(ofp);
      Fclose(ifp);            /* all done with original input file */

      /* reprocess the scratch file; 1st format an error msg, just in case */
      Sprintf(in_line, "rewind of \"%s\"", tempfile);
      if (rewind(tfp) != 0)  goto dead_data;
      /* copy all lines of text from the scratch file into the output file */
      while (fgets(in_line, sizeof in_line, tfp))
          (void) fputs(in_line, ofp);

      /* finished with scratch file */
      Fclose(tfp);
      Unlink(tempfile); /* remove it */

      /* update the first record of the output file; prepare error msg 1st */
      Sprintf(in_line, "rewind of \"%s\"", filename);
      ok = (rewind(ofp) == 0);
      if (ok) {
         Sprintf(in_line, "header rewrite of \"%s\"", filename);
         ok = (fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, txt_offset) >= 0);
      }
      if (!ok) {
dead_data:  perror(in_line);  /* report the problem */
          /* close and kill the aborted output file, then give up */
          Fclose(ofp);
          Unlink(filename);
          exit(EXIT_FAILURE);
      }

      /* all done */
      Fclose(ofp);

      return;
}

/* routine to decide whether to discard something from oracles.txt */
static boolean
h_filter(char *line)
{
    static boolean skip = FALSE;
    char tag[sizeof in_line];

    SpinCursor(3);

    if (*line == '#') return TRUE;  /* ignore comment lines */
    if (sscanf(line, "----- %s", tag) == 1) {
      skip = FALSE;
#ifndef SINKS
      if (!strcmp(tag, "SINKS")) skip = TRUE;
#endif
#ifndef ELBERETH
      if (!strcmp(tag, "ELBERETH")) skip = TRUE;
#endif
    } else if (skip && !strncmp(line, "-----", 5))
      skip = FALSE;
    return skip;
}

static const char *special_oracle[] = {
/*JP
      "\"...it is rather disconcerting to be confronted with the",
      "following theorem from [Baker, Gill, and Solovay, 1975].",
      "",
      "Theorem 7.18  There exist recursive languages A and B such that",
      "  (1)  P(A) == NP(A), and",
      "  (2)  P(B) != NP(B)",
      "",
      "This provides impressive evidence that the techniques that are",
      "currently available will not suffice for proving that P != NP or          ",
      "that P == NP.\"  [Garey and Johnson, p. 185.]"
*/
      "「次の定理[Baker, Gill, and Solovay, 1975]に直面することは",
      "むしろ困惑することである.",
      "",
      "定理 7.18 次のような再帰的言語 A,Bが存在する",
      "  (1)  P(A) == NP(A),かつ",
      "  (2)  P(B) != NP(B)",
      "",
      "これは現在 P != NPであるかまたは P == NPであるかを証明する",
        "有効な手法がないことを強く示している.」",
        "[Garey and Johnson, p. 185.]"
};

/*
   The oracle file consists of a "do not edit" comment, a decimal count N
   and set of N+1 hexadecimal fseek offsets, followed by N multiple-line
   records, separated by "---" lines.  The first oracle is a special case.
   The input data contains just those multi-line records, separated by
   "-----" lines.
 */

void
do_oracles(void)
{
      char  infile[60], tempfile[60];
      boolean in_oracle, ok;
      long  txt_offset, offset, fpos;
      int   oracle_cnt;
      register int i;

      Sprintf(tempfile, DATA_TEMPLATE, "oracles.tmp");
      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename, file_prefix);
#endif
      Sprintf(eos(filename), DATA_TEMPLATE, ORACLE_FILE);
      Sprintf(infile, DATA_IN_TEMPLATE, ORACLE_FILE);
      Strcat(infile, ".txt");
      if (!(ifp = fopen(infile, RDTMODE))) {
            perror(infile);
            exit(EXIT_FAILURE);
      }
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            Fclose(ifp);
            exit(EXIT_FAILURE);
      }
      if (!(tfp = fopen(tempfile, WRTMODE))) {  /* oracles.tmp */
            perror(tempfile);
            Fclose(ifp);
            Fclose(ofp);
            Unlink(filename);
            exit(EXIT_FAILURE);
      }

      /* output a dummy header record; we'll rewind and overwrite it later */
      Fprintf(ofp, "%s%5d\n", Dont_Edit_Data, 0);

      /* handle special oracle; it must come first */
      (void) fputs("---\n", tfp);
      Fprintf(ofp, "%05lx\n", ftell(tfp));  /* start pos of special oracle */
      for (i = 0; i < SIZE(special_oracle); i++) {
          (void) fputs(xcrypt(special_oracle[i]), tfp);
          (void) fputc('\n', tfp);
      }
      SpinCursor(3);

      oracle_cnt = 1;
      (void) fputs("---\n", tfp);
      Fprintf(ofp, "%05lx\n", ftell(tfp));      /* start pos of first oracle */
      in_oracle = FALSE;

      while (fgets(in_line, sizeof in_line, ifp)) {
          SpinCursor(3);

          if (h_filter(in_line)) continue;
          if (!strncmp(in_line, "-----", 5)) {
            if (!in_oracle) continue;
            in_oracle = FALSE;
            oracle_cnt++;
            (void) fputs("---\n", tfp);
            Fprintf(ofp, "%05lx\n", ftell(tfp));
            /* start pos of this oracle */
          } else {
            in_oracle = TRUE;
            (void) fputs(xcrypt(in_line), tfp);
          }
      }

      if (in_oracle) {  /* need to terminate last oracle */
          oracle_cnt++;
          (void) fputs("---\n", tfp);
          Fprintf(ofp, "%05lx\n", ftell(tfp));  /* eof position */
      }

      /* record the current position */
      txt_offset = ftell(ofp);
      Fclose(ifp);            /* all done with original input file */

      /* reprocess the scratch file; 1st format an error msg, just in case */
      Sprintf(in_line, "rewind of \"%s\"", tempfile);
      if (rewind(tfp) != 0)  goto dead_data;
      /* copy all lines of text from the scratch file into the output file */
      while (fgets(in_line, sizeof in_line, tfp))
          (void) fputs(in_line, ofp);

      /* finished with scratch file */
      Fclose(tfp);
      Unlink(tempfile); /* remove it */

      /* update the first record of the output file; prepare error msg 1st */
      Sprintf(in_line, "rewind of \"%s\"", filename);
      ok = (rewind(ofp) == 0);
      if (ok) {
          Sprintf(in_line, "header rewrite of \"%s\"", filename);
          ok = (fprintf(ofp, "%s%5d\n", Dont_Edit_Data, oracle_cnt) >=0);
      }
      if (ok) {
          Sprintf(in_line, "data rewrite of \"%s\"", filename);
          for (i = 0; i <= oracle_cnt; i++) {
#ifndef VMS /* alpha/vms v1.0; this fflush seems to confuse ftell */
            if (!(ok = (fflush(ofp) == 0))) break;
#endif
            if (!(ok = (fpos = ftell(ofp)) >= 0)) break;
            if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
            if (!(ok = (fscanf(ofp, "%5lx", &offset) == 1))) break;
            if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
            if (!(ok = (fprintf(ofp, "%05lx\n", offset + txt_offset) >= 0)))
                break;
          }
      }
      if (!ok) {
dead_data:  perror(in_line);  /* report the problem */
          /* close and kill the aborted output file, then give up */
          Fclose(ofp);
          Unlink(filename);
          exit(EXIT_FAILURE);
      }

      /* all done */
      Fclose(ofp);

      return;
}


static      struct deflist {

      const char  *defname;
      boolean     true_or_false;
} deflist[] = {
#ifdef REINCARNATION
            {     "REINCARNATION", TRUE },
#else
            {     "REINCARNATION", FALSE },
#endif
            { 0, 0 } };

static int
check_control(char *s)
{
      int   i;

      if(s[0] != '%') return(-1);

      for(i = 0; deflist[i].defname; i++)
          if(!strncmp(deflist[i].defname, s+1, strlen(deflist[i].defname)))
            return(i);

      return(-1);
}

static char *
without_control(char *s)
{
      return(s + 1 + strlen(deflist[check_control(in_line)].defname));
}

void
do_dungeon(void)
{
      int rcnt = 0;

      Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
      if (!(ifp = fopen(filename, RDTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }
      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename, file_prefix);
#endif
      Sprintf(eos(filename), DGN_TEMPLATE, DGN_O_FILE);
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }
      Fprintf(ofp,Dont_Edit_Data);

      while (fgets(in_line, sizeof in_line, ifp) != 0) {
          SpinCursor(3);

          rcnt++;
          if(in_line[0] == '#') continue; /* discard comments */
recheck:
          if(in_line[0] == '%') {
            int i = check_control(in_line);
            if(i >= 0) {
                if(!deflist[i].true_or_false)  {
                  while (fgets(in_line, sizeof in_line, ifp) != 0)
                      if(check_control(in_line) != i) goto recheck;
                } else
                  (void) fputs(without_control(in_line),ofp);
            } else {
                Fprintf(stderr, "Unknown control option '%s' in file %s at line %d.\n",
                      in_line, DGN_I_FILE, rcnt);
                exit(EXIT_FAILURE);
            }
          } else
            (void) fputs(in_line,ofp);
      }
      Fclose(ifp);
      Fclose(ofp);

      return;
}

static boolean
ranged_attk(register struct permonst *ptr)      /* returns TRUE if monster can attack at range */
                                    
{
      register int      i, j;
      register int atk_mask = (1<<AT_BREA) | (1<<AT_SPIT) | (1<<AT_GAZE);

      for(i = 0; i < NATTK; i++) {
          if((j=ptr->mattk[i].aatyp) >= AT_WEAP || (atk_mask & (1<<j)))
            return TRUE;
      }

      return(FALSE);
}

/* This routine is designed to return an integer value which represents
 * an approximation of monster strength.  It uses a similar method of
 * determination as "experience()" to arrive at the strength.
 */
static int
mstrength(struct permonst *ptr)
{
      int   i, tmp2, n, tmp = ptr->mlevel;

      if(tmp > 49)            /* special fixed hp monster */
          tmp = 2*(tmp - 6) / 4;

/*    For creation in groups */
      n = (!!(ptr->geno & G_SGROUP));
      n += (!!(ptr->geno & G_LGROUP)) << 1;

/*    For ranged attacks */
      if (ranged_attk(ptr)) n++;

/*    For higher ac values */
      n += (ptr->ac < 4);
      n += (ptr->ac < 0);

/*    For very fast monsters */
      n += (ptr->mmove >= 18);

/*    For each attack and "special" attack */
      for(i = 0; i < NATTK; i++) {

          tmp2 = ptr->mattk[i].aatyp;
          n += (tmp2 > 0);
          n += (tmp2 == AT_MAGC);
          n += (tmp2 == AT_WEAP && (ptr->mflags2 & M2_STRONG));
      }

/*    For each "special" damage type */
      for(i = 0; i < NATTK; i++) {

          tmp2 = ptr->mattk[i].adtyp;
          if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_DRST)
            || (tmp2 == AD_DRDX) || (tmp2 == AD_DRCO) || (tmp2 == AD_WERE))
                  n += 2;
          else if (strcmp(ptr->mname, "grid bug")) n += (tmp2 != AD_PHYS);
          n += ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
      }

/*    Leprechauns are special cases.  They have many hit dice so they
      can hit and are hard to kill, but they don't really do much damage. */
      if (!strcmp(ptr->mname, "leprechaun")) n -= 2;

/*    Finally, adjust the monster level  0 <= n <= 24 (approx.) */
      if(n == 0) tmp--;
      else if(n >= 6) tmp += ( n / 2 );
      else tmp += ( n / 3 + 1);

      return((tmp >= 0) ? tmp : 0);
}

void
do_monstr(void)
{
    register struct permonst *ptr;
    register int i, j;

    /*
     * create the source file, "monstr.c"
     */
    filename[0]='\0';
#ifdef FILE_PREFIX
    Strcat(filename, file_prefix);
#endif
    Sprintf(eos(filename), SOURCE_TEMPLATE, MON_STR_C);
    if (!(ofp = fopen(filename, WRTMODE))) {
      perror(filename);
      exit(EXIT_FAILURE);
    }
    Fprintf(ofp,Dont_Edit_Code);
    Fprintf(ofp,"#include \"config.h\"\n");
    Fprintf(ofp,"\nint monstr[] = {\n");
    for (ptr = &mons[0], j = 0; ptr->mlet; ptr++) {

      SpinCursor(3);

      i = mstrength(ptr);
      Fprintf(ofp,"%2d,%c", i, (++j & 15) ? ' ' : '\n');
    }
    /* might want to insert a final 0 entry here instead of just newline */
    Fprintf(ofp,"%s};\n", (j & 15) ? "\n" : "");

    Fprintf(ofp,"\nvoid NDECL(monstr_init);\n");
    Fprintf(ofp,"\nvoid\n");
    Fprintf(ofp,"monstr_init()\n");
    Fprintf(ofp,"{\n");
    Fprintf(ofp,"    return;\n");
    Fprintf(ofp,"}\n");
    Fprintf(ofp,"\n/*monstr.c*/\n");

    Fclose(ofp);
    return;
}

void
do_permonst(void)
{
      int   i;
      char  *c, *nam;

      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename, file_prefix);
#endif
      Sprintf(eos(filename), INCLUDE_TEMPLATE, MONST_FILE);
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }
      Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.2\t94/09/10 */\n\n");
      Fprintf(ofp,Dont_Edit_Code);
      Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n");

      if (strcmp(mons[0].mname, "playermon") != 0)
            Fprintf(ofp,"\n#define\tPM_PLAYERMON\t(-1)");

      for (i = 0; mons[i].mlet; i++) {
            SpinCursor(3);
            Fprintf(ofp,"\n#define\tPM_");
            if (mons[i].mlet == S_HUMAN &&
                        !strncmp(mons[i].mname, "were", 4))
                Fprintf(ofp, "HUMAN_");
            for (nam = c = tmpdup(mons[i].mname); *c; c++)
                if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
                else if (*c < 'A' || *c > 'Z') *c = '_';
            Fprintf(ofp,"%s\t%d", nam, i);
      }
      Fprintf(ofp,"\n\n#define\tNUMMONS\t%d\n", i);
      Fprintf(ofp,"\n#endif /* PM_H */\n");
      Fclose(ofp);
      return;
}


/*    Start of Quest text file processing. */
#include "qtext.h"

static struct qthdr     qt_hdr;
static struct msghdr    msg_hdr[N_HDR];
static struct qtmsg     *curr_msg;

static int  qt_line;

static boolean    in_msg;
#define NO_MSG    1     /* strlen of a null line returned by fgets() */

static boolean
qt_comment(char *s)
{
      if(s[0] == '#') return(TRUE);
      return((boolean)(!in_msg  && strlen(s) == NO_MSG));
}

static boolean
qt_control(char *s)
{
      return((boolean)(s[0] == '%' && (s[1] == 'C' || s[1] == 'E')));
}

static int
get_hdr(c)
     char c;
{
      int   i;

      for(i = 0; i < qt_hdr.n_hdr; i++)
          if(c == qt_hdr.id[i]) return (++i);

      return(0);
}

static boolean
known_id(c)
     char c;
{
      return((boolean)(get_hdr(c) > 0));
}

static boolean
new_id(c)
     char c;
{
      if(qt_hdr.n_hdr >= N_HDR) {

          Fprintf(stderr, OUT_OF_HEADERS, qt_line);
          return(FALSE);
      }

      qt_hdr.id[qt_hdr.n_hdr] = c;
      msg_hdr[qt_hdr.n_hdr].n_msg = 0;
      qt_hdr.offset[qt_hdr.n_hdr++] = 0L;
      return(TRUE);
}

static boolean
known_msg(c, s)
     char c;
     char *s;
{
      int i = get_hdr(c) - 1,
          j, n = atoi(s);

      for(j = 0; j < msg_hdr[i].n_msg; j++)
          if(msg_hdr[i].qt_msg[j].msgnum == n) return(TRUE);

      return(FALSE);
}


static void
new_msg(char *s)
{
      struct      qtmsg *qt_msg;
      int   i = get_hdr(s[4]) - 1;

      if(msg_hdr[i].n_msg >= N_MSG) {
            Fprintf(stderr, OUT_OF_MESSAGES, qt_line);
      } else {
            qt_msg = &(msg_hdr[i].qt_msg[msg_hdr[i].n_msg++]);
            qt_msg->msgnum = atoi(s+5);
            qt_msg->delivery = s[2];
            qt_msg->offset = qt_msg->size = 0L;

            curr_msg = qt_msg;
      }
}

static void
do_qt_control(char *s)
{
      switch(s[1]) {

          case 'C':     if(in_msg) {
                      Fprintf(stderr, CREC_IN_MSG, qt_line);
                      break;
                  } else {
                      in_msg = TRUE;
                      if(!known_id(s[4]))
                        if(!new_id(s[4])) break;
                      if(known_msg(s[4],&s[5]))
                        Fprintf(stderr, DUP_MSG, qt_line);
                      else new_msg(s);
                  }
                  break;

          case 'E':     if(!in_msg) {
                      Fprintf(stderr, END_NOT_IN_MSG, qt_line);
                      break;
                  } else in_msg = FALSE;
                  break;

          default:      Fprintf(stderr, UNREC_CREC, qt_line);
                  break;
      }
}

static void
do_qt_text(char *s)
{
      curr_msg->size += strlen(s);
}

static void
adjust_qt_hdrs(void) {

      int   i, j;
      long  count = 0L,
            hdr_offset = sizeof(int) +
                       (sizeof(char) + sizeof(long)) * qt_hdr.n_hdr;

      for(i = 0; i < qt_hdr.n_hdr; i++) {

          qt_hdr.offset[i] = hdr_offset;
          hdr_offset += sizeof(int) + sizeof(struct qtmsg) * msg_hdr[i].n_msg;
      }

      for(i = 0; i < qt_hdr.n_hdr; i++)
          for(j = 0; j < msg_hdr[i].n_msg; j++) {

            msg_hdr[i].qt_msg[j].offset = hdr_offset + count;
            count += msg_hdr[i].qt_msg[j].size;
          }
}

static void
put_qt_hdrs(void) {

      int   i;

      /*
       *    The main header record.
       */
#ifdef DEBUG
      Fprintf(stderr, "%ld: header info.\n", ftell(ofp));
#endif
      (void) fwrite((genericptr_t)&(qt_hdr.n_hdr), sizeof(int), 1, ofp);
      (void) fwrite((genericptr_t)&(qt_hdr.id[0]), sizeof(char),
                                          qt_hdr.n_hdr, ofp);
      (void) fwrite((genericptr_t)&(qt_hdr.offset[0]), sizeof(long),
                                          qt_hdr.n_hdr, ofp);
#ifdef DEBUG
      for(i = 0; i < qt_hdr.n_hdr; i++)
            Fprintf(stderr, "%c @ %ld, ", qt_hdr.id[i], qt_hdr.offset[i]);

      Fprintf(stderr, "\n");
#endif

      /*
       *    The individual class headers.
       */
      for(i = 0; i < qt_hdr.n_hdr; i++) {

#ifdef DEBUG
          Fprintf(stderr, "%ld: %c header info.\n", ftell(ofp),
                qt_hdr.id[i]);
#endif
          (void) fwrite((genericptr_t)&(msg_hdr[i].n_msg), sizeof(int),
                                          1, ofp);
          (void) fwrite((genericptr_t)&(msg_hdr[i].qt_msg[0]),
                      sizeof(struct qtmsg), msg_hdr[i].n_msg, ofp);
#ifdef DEBUG
          { int j;
            for(j = 0; j < msg_hdr[i].n_msg; j++)
            Fprintf(stderr, "msg %d @ %ld (%ld)\n",
                  msg_hdr[i].qt_msg[j].msgnum,
                  msg_hdr[i].qt_msg[j].offset,
                  msg_hdr[i].qt_msg[j].size);
          }
#endif
      }
}

void
do_questtxt(void)
{
      Sprintf(filename, DATA_IN_TEMPLATE, QTXT_I_FILE);
      if(!(ifp = fopen(filename, RDTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }

      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename, file_prefix);
#endif
      Sprintf(eos(filename), DATA_TEMPLATE, QTXT_O_FILE);
      if(!(ofp = fopen(filename, WRBMODE))) {
            perror(filename);
            Fclose(ifp);
            exit(EXIT_FAILURE);
      }

      qt_hdr.n_hdr = 0;
      qt_line = 0;
      in_msg = FALSE;

      while (fgets(in_line, 80, ifp) != 0) {
          SpinCursor (3);

          qt_line++;
          if(qt_control(in_line)) do_qt_control(in_line);
          else if(qt_comment(in_line)) continue;
          else              do_qt_text(in_line);
      }

      (void) rewind(ifp);
      in_msg = FALSE;
      adjust_qt_hdrs();
      put_qt_hdrs();
      while (fgets(in_line, 80, ifp) != 0) {

            if(qt_control(in_line)) {
                in_msg = (in_line[1] == 'C');
                continue;
            } else if(qt_comment(in_line)) continue;
#ifdef DEBUG
            Fprintf(stderr, "%ld: %s", ftell(stdout), in_line);
#endif
            (void) fputs(xcrypt(in_line), ofp);
      }
      Fclose(ifp);
      Fclose(ofp);
      return;
}


static      char  temp[32];

static char *
limit(char *name, int pref)   /* limit a name to 30 characters length */
            
           
{
      (void) strncpy(temp, name, pref ? 26 : 30);
      temp[pref ? 26 : 30] = 0;
      return temp;
}

void
do_objs(void)
{
      int i, sum = 0;
      char *c, *objnam;
      int nspell = 0;
      int prefix = 0;
      char class = '\0';
      boolean     sumerr = FALSE;

      filename[0]='\0';
#ifdef FILE_PREFIX
      Strcat(filename, file_prefix);
#endif
      Sprintf(eos(filename), INCLUDE_TEMPLATE, ONAME_FILE);
      if (!(ofp = fopen(filename, WRTMODE))) {
            perror(filename);
            exit(EXIT_FAILURE);
      }
      Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.2\t94/09/10 */\n\n");
      Fprintf(ofp,Dont_Edit_Code);
      Fprintf(ofp,"#ifndef ONAMES_H\n#define ONAMES_H\n\n");

      for(i = 0; !i || objects[i].oc_class != ILLOBJ_CLASS; i++) {
            SpinCursor(3);

            objects[i].oc_name_idx = objects[i].oc_descr_idx = i; /* init */
            if (!(objnam = tmpdup(OBJ_NAME(objects[i])))) continue;

            /* make sure probabilities add up to 1000 */
            if(objects[i].oc_class != class) {
                  if (sum && sum != 1000) {
                      Fprintf(stderr, "prob error for class %d (%d%%)",
                            class, sum);
                      (void) fflush(stderr);
                      sumerr = TRUE;
                  }
                  class = objects[i].oc_class;
                  sum = 0;
            }

            for (c = objnam; *c; c++)
                if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
                else if (*c < 'A' || *c > 'Z') *c = '_';

            switch (class) {
                case WAND_CLASS:
                  Fprintf(ofp,"#define\tWAN_"); prefix = 1; break;
                case RING_CLASS:
                  Fprintf(ofp,"#define\tRIN_"); prefix = 1; break;
                case POTION_CLASS:
                  Fprintf(ofp,"#define\tPOT_"); prefix = 1; break;
                case SPBOOK_CLASS:
                  Fprintf(ofp,"#define\tSPE_"); prefix = 1; nspell++; break;
                case SCROLL_CLASS:
                  Fprintf(ofp,"#define\tSCR_"); prefix = 1; break;
                case AMULET_CLASS:
                  /* avoid trouble with stupid C preprocessors */
                  Fprintf(ofp,"#define\t");
                  if(objects[i].oc_material == PLASTIC) {
                      Fprintf(ofp,"FAKE_AMULET_OF_YENDOR\t%d\n", i);
                      prefix = -1;
                      break;
                  }
                  break;
                case GEM_CLASS:
                  /* avoid trouble with stupid C preprocessors */
                  if(objects[i].oc_material == GLASS) {
                      Fprintf(ofp,"/* #define\t%s\t%d */\n",
                                          objnam, i);
                      prefix = -1;
                      break;
                  }
                default:
                  Fprintf(ofp,"#define\t");
            }
            if (prefix >= 0)
                  Fprintf(ofp,"%s\t%d\n", limit(objnam, prefix), i);
            prefix = 0;

            sum += objects[i].oc_prob;
      }

      /* check last set of probabilities */
      if (sum && sum != 1000) {
          Fprintf(stderr, "prob error for class %d (%d%%)", class, sum);
          (void) fflush(stderr);
          sumerr = TRUE;
      }

      Fprintf(ofp,"#define\tLAST_GEM\t(JADE)\n");
      Fprintf(ofp,"#define\tMAXSPELL\t%d\n", nspell+1);
      Fprintf(ofp,"#define\tNUM_OBJECTS\t%d\n", i);

      Fprintf(ofp, "\n/* Artifacts (unique objects) */\n\n");

      for (i = 1; artifact_names[i]; i++) {
            SpinCursor(3);

            for (c = objnam = tmpdup(artifact_names[i]); *c; c++)
                if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
                else if (*c < 'A' || *c > 'Z') *c = '_';

            if (!strncmp(objnam, "THE_", 4))
                  objnam += 4;
#ifdef TOURIST
            /* fudge _platinum_ YENDORIAN EXPRESS CARD */
            if (!strncmp(objnam, "PLATINUM_", 9))
                  objnam += 9;
#endif
            Fprintf(ofp,"#define\tART_%s\t%d\n", limit(objnam, 1), i);
      }

      Fprintf(ofp, "#define\tNROFARTIFACTS\t%d\n", i-1);
      Fprintf(ofp,"\n#endif /* ONAMES_H */\n");
      Fclose(ofp);
      if (sumerr) exit(EXIT_FAILURE);
      return;
}

static char *
tmpdup(const char *str)
{
      static char buf[128];

      if (!str) return (char *)0;
      (void)strncpy(buf, str, 127);
      return buf;
}

static char *
eos(str)
char *str;
{
    while (*str) str++;
    return str;
}

/*
 * macro used to control vision algorithms:
 *      VISION_TABLES => generate tables
 */

void
do_vision(void)
{
#ifdef VISION_TABLES
    int i, j;

    /* Everything is clear.  xclear may be malloc'ed.
     * Block the upper left corner (BLOCK_HEIGHTxBLOCK_WIDTH)
     */
    for (i = 0; i < MAX_ROW; i++)
      for (j = 0; j < MAX_COL; j++)
          if (i < BLOCK_HEIGHT && j < BLOCK_WIDTH)
            xclear[i][j] = '\000';
          else
            xclear[i][j] = '\001';
#endif /* VISION_TABLES */

    SpinCursor(3);

    /*
     * create the include file, "vis_tab.h"
     */
    filename[0]='\0';
#ifdef FILE_PREFIX
    Strcat(filename, file_prefix);
#endif
    Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
    if (!(ofp = fopen(filename, WRTMODE))) {
      perror(filename);
      exit(EXIT_FAILURE);
    }
    Fprintf(ofp,Dont_Edit_Code);
    Fprintf(ofp,"#ifdef VISION_TABLES\n");
#ifdef VISION_TABLES
    H_close_gen();
    H_far_gen();
#endif /* VISION_TABLES */
    Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
    Fclose(ofp);

    SpinCursor(3);

    /*
     * create the source file, "vis_tab.c"
     */
    filename[0]='\0';
#ifdef FILE_PREFIX
    Strcat(filename, file_prefix);
#endif
    Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
    if (!(ofp = fopen(filename, WRTMODE))) {
      perror(filename);
      Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
      Unlink(filename);
      exit(EXIT_FAILURE);
    }
    Fprintf(ofp,Dont_Edit_Code);
    Fprintf(ofp,"#include \"config.h\"\n");
    Fprintf(ofp,"#ifdef VISION_TABLES\n");
    Fprintf(ofp,"#include \"vis_tab.h\"\n");

    SpinCursor(3);

#ifdef VISION_TABLES
    C_close_gen();
    C_far_gen();
    Fprintf(ofp,"\nvoid vis_tab_init() { return; }\n");
#endif /* VISION_TABLES */

    SpinCursor(3);

    Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
    Fprintf(ofp,"\n/*vis_tab.c*/\n");

    Fclose(ofp);
    return;
}

#ifdef VISION_TABLES

/*--------------  vision tables  --------------*\
 *
 *  Generate the close and far tables.  This is done by setting up a
 *  fake dungeon and moving our source to different positions relative
 *  to a block and finding the first/last visible position.  The fake
 *  dungeon is all clear execpt for the upper left corner (BLOCK_HEIGHT
 *  by BLOCK_WIDTH) is blocked.  Then we move the source around relative
 *  to the corner of the block.  For each new position of the source
 *  we check positions on rows "kittycorner" from the source.  We check
 *  positions until they are either in sight or out of sight (depends on
 *  which table we are generating).  The picture below shows the setup
 *  for the generation of the close table.  The generation of the far
 *  table would switch the quadrants of the '@' and the "Check rows
 *  here".
 *
 *
 *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
 *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
 *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,, Check rows here ,,,,,,,,,,,,
 *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
 *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXB,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
 *  ...............................
 *  ...............................
 *  .........@.....................
 *  ...............................
 *
 *      Table generation figure (close_table).  The 'X's are blocked points.
 *      The 'B' is a special blocked point.  The '@' is the source.  The ','s
 *      are the target area.  The '.' are just open areas.
 *
 *
 *  Example usage of close_table[][][].
 *
 *  The table is as follows:
 *
 *      dy = |row of '@' - row of 'B'|  - 1
 *      dx = |col of '@' - col of 'B'|
 *
 *  The first indices are the deltas from the source '@' and the block 'B'.
 *  You must check for the value inside the abs value bars being zero.  If
 *  so then the block is on the same row and you don't need to do a table
 *  lookup.  The last value:
 *
 *      dcy = |row of block - row to be checked|
 *
 *  Is the value of the first visible spot on the check row from the
 *  block column.  So
 *
 *  first visible col = close_table[dy][dx][dcy] + col of 'B'
 *
\*--------------  vision tables  --------------*/

static void
H_close_gen()
{
    Fprintf(ofp,"\n/* Close */\n");
    Fprintf(ofp,"#define CLOSE_MAX_SB_DY %2d\t/* |src row - block row| - 1\t*/\n",
          TEST_HEIGHT-1);
    Fprintf(ofp,"#define CLOSE_MAX_SB_DX %2d\t/* |src col - block col|\t*/\n",
          TEST_WIDTH);
    Fprintf(ofp,"#define CLOSE_MAX_BC_DY %2d\t/* |block row - check row|\t*/\n",
          TEST_HEIGHT);
    Fprintf(ofp,"typedef struct {\n");
    Fprintf(ofp,"    unsigned char close[CLOSE_MAX_SB_DX][CLOSE_MAX_BC_DY];\n");
    Fprintf(ofp,"} close2d;\n");
    Fprintf(ofp,"extern close2d close_table[CLOSE_MAX_SB_DY];\n");
    return;
}

static void
H_far_gen()
{
    Fprintf(ofp,"\n/* Far */\n");
    Fprintf(ofp,"#define FAR_MAX_SB_DY %2d\t/* |src row - block row|\t*/\n",
          TEST_HEIGHT);
    Fprintf(ofp,"#define FAR_MAX_SB_DX %2d\t/* |src col - block col| - 1\t*/\n",
          TEST_WIDTH-1);
    Fprintf(ofp,"#define FAR_MAX_BC_DY %2d\t/* |block row - check row| - 1\t*/\n",
          TEST_HEIGHT-1);
    Fprintf(ofp,"typedef struct {\n");
    Fprintf(ofp,"    unsigned char far_q[FAR_MAX_SB_DX][FAR_MAX_BC_DY];\n");
    Fprintf(ofp,"} far2d;\n");
    Fprintf(ofp,"extern far2d far_table[FAR_MAX_SB_DY];\n");
    return;
}

static void
C_close_gen()
{
    int i,dx,dy;
    int src_row, src_col;     /* source */
    int block_row, block_col; /* block */
    int this_row;
    int no_more;
    const char *delim;

    block_row = BLOCK_HEIGHT-1;
    block_col = BLOCK_WIDTH-1;

    Fprintf(ofp,"\n#ifndef FAR_TABLE_ONLY\n");
    Fprintf(ofp,"\nclose2d close_table[CLOSE_MAX_SB_DY] = {\n");
#ifndef no_vision_progress
    Fprintf(stderr,"\nclose:");
#endif

    for (dy = 1; dy < TEST_HEIGHT; dy++) {
      src_row = block_row + dy;
      Fprintf(ofp, "/* DY = %2d (- 1)*/\n  {{\n", dy);
#ifndef no_vision_progress
      Fprintf(stderr," %2d",dy),  (void)fflush(stderr);
#endif
      for (dx = 0; dx < TEST_WIDTH; dx++) {
          src_col = block_col - dx;
          Fprintf(ofp, "  /*%2d*/ {", dx);

          no_more = 0;
          for (this_row = 0; this_row < TEST_HEIGHT; this_row++) {
            delim = (this_row < TEST_HEIGHT - 1) ? "," : "";
            if (no_more) {
                Fprintf(ofp, "%s%s", CLOSE_OFF_TABLE_STRING, delim);
                continue;
            }
            SpinCursor(3);

            /* Find the first column that we can see. */
            for (i = block_col+1; i < MAX_COL; i++) {
                if (clear_path(src_row,src_col,block_row-this_row,i))
                  break;
            }

            if (i == MAX_COL) no_more = 1;
            Fprintf(ofp, "%2d%s", i - block_col, delim);
          }
          Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
      }
      Fprintf(ofp,"  }},\n");
    }

    Fprintf(ofp,"}; /* close_table[] */\n");          /* closing brace for table */
    Fprintf(ofp,"#endif /* !FAR_TABLE_ONLY */\n");
#ifndef no_vision_progress
    Fprintf(stderr,"\n");
#endif
    return;
}

static void
C_far_gen()
{
    int i,dx,dy;
    int src_row, src_col;     /* source */
    int block_row, block_col; /* block */
    int this_row;
    const char *delim;

    block_row = BLOCK_HEIGHT-1;
    block_col = BLOCK_WIDTH-1;

    Fprintf(ofp,"\n#ifndef CLOSE_TABLE_ONLY\n");
    Fprintf(ofp,"\nfar2d far_table[FAR_MAX_SB_DY] = {\n");
#ifndef no_vision_progress
    Fprintf(stderr,"\n_far_:");
#endif

    for (dy = 0; dy < TEST_HEIGHT; dy++) {
      src_row = block_row - dy;
      Fprintf(ofp, "/* DY = %2d */\n  {{\n", dy);
#ifndef no_vision_progress
      Fprintf(stderr," %2d",dy),  (void)fflush(stderr);
#endif
      for (dx = 1; dx < TEST_WIDTH; dx++) {
          src_col = block_col + dx;
          Fprintf(ofp, "  /*%2d(-1)*/ {", dx);

          for (this_row = block_row+1; this_row < block_row+TEST_HEIGHT;
                                                this_row++) {
            delim = (this_row < block_row + TEST_HEIGHT - 1) ? "," : "";

            SpinCursor(3);
            /* Find first col that we can see. */
            for (i = 0; i <= block_col; i++) {
                if (clear_path(src_row,src_col,this_row,i)) break;
            }

            if (block_col-i < 0)
                Fprintf(ofp, "%s%s", FAR_OFF_TABLE_STRING, delim);
            else
                Fprintf(ofp, "%2d%s", block_col - i, delim);
          }
          Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
      }
      Fprintf(ofp,"  }},\n");
    }

    Fprintf(ofp,"}; /* far_table[] */\n");      /* closing brace for table */
    Fprintf(ofp,"#endif /* !CLOSE_TABLE_ONLY */\n");
#ifndef no_vision_progress
    Fprintf(stderr,"\n");
#endif
    return;
}

/*
 *  "Draw" a line from the hero to the given location.  Stop if we hit a
 *  wall.
 *
 *  Generalized integer Bresenham's algorithm (fast line drawing) for
 *  all quadrants.  From _Procedural Elements for Computer Graphics_, by
 *  David F. Rogers.  McGraw-Hill, 1985.
 *
 *  I have tried a little bit of optimization by pulling compares out of
 *  the inner loops.
 *
 *  NOTE:  This had better *not* be called from a position on the
 *  same row as the hero.
 */
static int
clear_path(you_row,you_col,y2,x2)
    int you_row, you_col, y2, x2;
{
    int dx, dy, s1, s2;
    register int i, error, x, y, dxs, dys;

    x  = you_col;       y  = you_row;
    dx = abs(x2-you_col);     dy = abs(y2-you_row);
    s1 = sign(x2-you_col);    s2 = sign(y2-you_row);

    if (s1 == 0) {      /* same column */
      if (s2 == 1) {    /* below (larger y2 value) */
          for (i = you_row+1; i < y2; i++)
            if (!xclear[i][you_col]) return 0;
      } else {    /* above (smaller y2 value) */
          for (i = y2+1; i < you_row; i++)
            if (!xclear[i][you_col]) return 0;
      }
      return 1;
    }

    /*
     *  Lines at 0 and 90 degrees have been weeded out.
     */
    if (dy > dx) {
      error = dx; dx = dy; dy = error;    /* swap the values */
      dxs = dx << 1;          /* save the shifted values */
      dys = dy << 1;
      error = dys - dx; /* NOTE: error is used as a temporary above */

      for (i = 0; i < dx; i++) {
          if (!xclear[y][x]) return 0;    /* plot point */

          while (error >= 0) {
            x += s1;
            error -= dxs;
          }
          y += s2;
          error += dys;
      }
    } else {
      dxs = dx << 1;          /* save the shifted values */
      dys = dy << 1;
      error = dys - dx;

      for (i = 0; i < dx; i++) {
          if (!xclear[y][x]) return 0;    /* plot point */

          while (error >= 0) {
            y += s2;
            error -= dxs;
          }
          x += s1;
          error += dys;
      }
    }
    return 1;
}
#endif /* VISION_TABLES */

#define HASHSIZE 509 /* see japanese/jtrns.c */
static int hash_tab[HASHSIZE]; 
static int rhash_tab[HASHSIZE]; 
static int 
hash_val(key)
     unsigned char *key;
{
  int v = 0;
  ++key;/* skip first char */
  while(*key)
    v = (v*3 + *(key++))%HASHSIZE;
  return v;
}

/* JP
** 
*/
#define WRMODE "w+"
#define RDMODE "r"
void
do_japanese(void)
{
  FILE *fpr, *fpw;
  char fnamer[BUFSZ], fnamew[BUFSZ];
  unsigned char buf[BUFSZ], *p, *key, *val;
  int i, hval, rhval;

  for(i = 0 ; i < HASHSIZE; ++i){
    hash_tab[i] = -1;
    rhash_tab[i] = -1;
  }

  sprintf(fnamew,INCLUDE_TEMPLATE,JDATA);
  if((fpw = fopen(fnamew,WRMODE))==(void *)NULL){
    fprintf(stderr,"Error: Can't create %s\n",fnamew);
    return;
  }

  fprintf(fpw,Dont_Edit_Code);

  sprintf(fnamer,DATA_TEMPLATE,JMON_FILE);
  if((fpr = fopen(fnamer,RDMODE))==(void *)NULL)
    fprintf(stderr,"Warning: Can't open %s\n",fnamer);
  else{
    fprintf(fpw,"static struct _jtrns_tab {\n");
    fprintf(fpw,"  const int type;\n");
    fprintf(fpw,"  const int next;\n");
    fprintf(fpw,"  const int rev_next;\n");
/*    fprintf(fpw,"  const int type;\n");*/
    fprintf(fpw,"  const char *key;\n");
    fprintf(fpw,"  const char *val;\n");
    fprintf(fpw,"} jtrns_tab[] = {\n");

    i = 0;
    while(fgets((char *)buf, BUFSIZ, fpr)!=NULL){
      if(buf[0]=='#')
        goto Next1;
      buf[strlen((char *)buf)-1]='\0';
      p = buf;
      while(isspace(*p))
        if(!*p)
          goto Next1;
        else
          ++p;
      key = p;
      while(*p!=':')
        if(!*p)
          goto Next1;
        else if(*p<128)
          ++p;
        else
          p+=2;
      *p='\0';
      ++p;
      while(isspace(*p))
        if(!*p)
          goto Next1;
        else
          ++p;
      val = p;
      while(*p!=':')
        if(!*p)
          goto Next1;
        else if(*p<128)
          ++p;
        else
          p+=2;
      *p='\0';

      hval = hash_val(key);
      rhval = hash_val(val);

      fprintf(fpw,"  {'@', %d, %d, \"%s\", \"%s\"},\n", 
            hash_tab[hval], rhash_tab[rhval], key, val);

      hash_tab[hval] = i;
      rhash_tab[rhval] = i;
      ++i;
    Next1:
      ;
    }
    fclose(fpr);
    
    sprintf(fnamer,DATA_TEMPLATE,JOBJ_FILE);
    if((fpr = fopen(fnamer,RDMODE))==(void *)NULL)
      fprintf(stderr,"Warning: Can't open %s\n",fnamer);
    else{
      while(fgets((char *)buf,BUFSIZ,fpr)!=NULL){
      if(buf[0]=='#')
        goto Next2;
      buf[strlen((char *)buf)-1]='\0';
      p = buf;
      while(isspace(*p))
        if(!*p)
          goto Next2;
        else
          ++p;
      key = p;
      while(*p!=':')
        if(!*p)
          goto Next2;
        else
          ++p;
      *p='\0';
      ++p;
      while(isspace(*p))
        if(!*p)
          goto Next2;
        else
          ++p;
      val = p;
      while(*p!=':')
        if(!*p)
          goto Next2;
        else
          ++p;
      *p='\0';
      hval = hash_val(key + 1);
      rhval = hash_val(val);

      if(*key=='\'')
        fprintf(fpw, "  {'\\%c', %d, %d, \"%s\", \"%s\"},\n",
              *key, hash_tab[hval], rhash_tab[rhval],
              key + 1, val);
      else
        fprintf(fpw, "  {'%c', %d, %d, \"%s\", \"%s\"},\n",
              *key, hash_tab[hval], rhash_tab[rhval],
              key + 1, val);

      hash_tab[hval] = i;
      rhash_tab[rhval] = i;

      ++i;
      Next2:
      ;
      }
    }
    fclose(fpr);
    fprintf(fpw,"  {'\\0', -1, -1, (void *)0, (void *)0},\n");
    fprintf(fpw,"};\n");

    fprintf(fpw,"static int hash_tab[] = {\n");
    for ( i = 0 ; i < HASHSIZE ; i++ )
      fprintf(fpw, "%d, \n", hash_tab[i]);
    fprintf(fpw,"};\n");

    fprintf(fpw,"static int rhash_tab[] = {\n");
    for ( i = 0 ; i < HASHSIZE ; i++ )
      fprintf(fpw, "%d, \n", rhash_tab[i]);
    fprintf(fpw,"};\n");

    fclose(fpw);
  }
}
  
#ifdef STRICT_REF_DEF
NEARDATA struct flag flags;
# ifdef ATTRIB_H
struct attribs attrmax, attrmin;
# endif
#endif /* STRICT_REF_DEF */

/*makedefs.c*/

Generated by  Doxygen 1.6.0   Back to index