/* ------------------------------------------------------------------------- */
/*   "infact" :  A small utility to print out an Infix-style debugging info  */
/*               file.  Includes no non-system files.                        */
/*                                                                           */
/*   (C) Copyright Graham Nelson, 1994                                       */
/*                                                                           */
/*   See the format description file                                         */
/*                                                                           */
/*   For use with Inform release 5.4 or later                                */
/* ------------------------------------------------------------------------- */

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#define ARCHIMEDES

#ifdef ARCHIMEDES
#define Debugging_Name  "Game_Debug"
#endif
#ifdef UNIX
#define Debugging_Name  "game.dbg"
#endif
#ifdef LINUX
#define Debugging_Name  "game.dbg"
#endif
#ifdef PC
#define Debugging_Name  "game.dbg"
#endif
#ifdef VAX
#define Debugging_Name  "game.dbg"
#endif
#ifdef AMIGA
#define Debugging_Name  "game.dbg"
#endif
#ifdef ATARIST
#define Debugging_Name  "game.dbg"
#endif
#ifdef OS2
#define Debugging_Name  "game.dbg"
#endif
#ifdef MACINTOSH
#define Debugging_Name  "game.debug"
#endif
#ifndef Debugging_Name
#define Debugging_Name  "debuginf"
#endif

extern void fatalerror(char *s)
{   printf("Fatal error: %s\n",s);
   exit(1);
}

static void couldntopen(char *m, char *fn)
{   char err_buffer[128];
   sprintf(err_buffer, "%s \"%s\"", m, fn);
   fatalerror(err_buffer);
}

static FILE *Debug_fp;
extern void open_debug_file(void)
{
   Debug_fp=fopen(Debugging_Name,"rb");
   if (Debug_fp==NULL) couldntopen("Couldn't open debugging info file",
       Debugging_Name);
}

extern int read_debug_byte(void)
{   if (ferror(Debug_fp))
       fatalerror("I/O failure: can't write to debugging info file");
   return fgetc(Debug_fp);
}

extern void read_debug_string(char *s)
{   int i=0;
   while ((s[i]=read_debug_byte())!=0) i++;
}

typedef struct linestr_s
{   int file_no;
   int line_no;
} linestr;

extern linestr read_debug_linenum(void)
{   linestr l; int i;
   l.file_no = read_debug_byte();
   i = read_debug_byte();
   l.line_no = i*256 + read_debug_byte();
   return l;
}

extern void close_debug_file(void)
{   if (ferror(Debug_fp))
       fatalerror("I/O failure: can't close debugging info file");
   fclose(Debug_fp);
}

extern void p_debug_string(void)
{   char buffer[256];
   read_debug_string(buffer);
   printf("\"%s\"",buffer);
}

extern void p_line(linestr l)
{   printf("%d:%d",l.file_no,l.line_no);
}

extern void p_address(void)
{   long int l;
   l=read_debug_byte(); l=l*256+read_debug_byte();
   l=l*256+read_debug_byte();
   printf("%05lx (%ld)", l, l);
}

int type_flags[64];

int main(int argc, char **argv)
{   int type; linestr l1; linestr l2; int i, j, k; char *p;
   char junk[256];

   printf("Infact 1 (try \"infact -help\" for instructions)\n");

   for (i=0; i<64; i++) type_flags[i]=1;
   type_flags[10]=0; type_flags[12]=0; type_flags[15]=0;

   if (argc>1)
   {   for (i=0; i<64; i++) type_flags[i]=0;
       for (i=1; i<argc; i++)
       {   p=argv[i];
           if (p[0]!='-') printf("Switches must begin with a -\n"); else p++;
           if (strcmp(p,"help")==0)
           {   printf(
"\"Infact\" is an utility to print out the information in an Infix format \n\
debugging data file, produced by Inform v 5.4 or later.  By default it \n\
prints everything except line references.  Otherwise the following switches \n\
may be used:\n\n\
 -files  -classes  -objects  -globals  -attributes  -fakes  -actions  -map\n\
 -properties  -header  -lines  -code  -codeless  -routines  -source\n\
 -help  -all\n");
           }
           else
           if (strcmp(p,"files")==0) { type_flags[1]=1; type_flags[16]=1; }
           else
           if (strcmp(p,"classes")==0) type_flags[2]=1;
           else
           if (strcmp(p,"objects")==0) type_flags[3]=1;
           else
           if (strcmp(p,"globals")==0) type_flags[4]=1;
           else
           if (strcmp(p,"attributes")==0) type_flags[5]=1;
           else
           if (strcmp(p,"properties")==0) type_flags[6]=1;
           else
           if (strcmp(p,"fakes")==0) type_flags[7]=1;
           else
           if (strcmp(p,"actions")==0) type_flags[8]=1;
           else
           if (strcmp(p,"header")==0) type_flags[9]=1;
           else
           if (strcmp(p,"lines")==0) { type_flags[10]=1; type_flags[12]=1; }
           else
           if (strcmp(p,"code")==0) type_flags[10]=1;
           else
           if (strcmp(p,"routines")==0) { type_flags[11]=1; type_flags[14]=1; }
           else
           if (strcmp(p,"codeless")==0) type_flags[12]=1;
           else
           if (strcmp(p,"map")==0) type_flags[13]=1;
           else
           if (strcmp(p,"source")==0) type_flags[15]=1;
           else
           if (strcmp(p,"all")==0)
               for (i=0; i<64; i++) type_flags[i]=1;
           else printf("Switch -%s unknown\n",p);
       }
   }

   open_debug_file();

   i=read_debug_byte(); j=read_debug_byte();
   k=read_debug_byte(); k=k*256+read_debug_byte();
   printf("Debugging file from Inform %d.%d (v %d)\n",i,j,k);

   do
   {   type=read_debug_byte();
       if (type>16) printf("Unknown type %d\n",type);
       if (type_flags[type]==1)
       switch(type)
       {   case 1: printf("File %d ",read_debug_byte()); p_debug_string();
                   printf(" expanding to "); p_debug_string(); printf("\n");
                   break;
           case 2: l1=read_debug_linenum();
                   printf("Class "); p_debug_string();
                   l2=read_debug_linenum();
                   printf(" from "); p_line(l1);
                   printf(" to "); p_line(l2); printf("\n"); break;
           case 3: k=read_debug_byte(); k=k*256+read_debug_byte();
                   l1=read_debug_linenum();
                   printf("Object %d ", k); p_debug_string();
                   l2=read_debug_linenum();
                   printf(" from "); p_line(l1);
                   printf(" to "); p_line(l2); printf("\n"); break;
           case 4: printf("Global %d ",read_debug_byte());
                   p_debug_string(); printf("\n"); break;
           case 5: printf("Attribute %d ",read_debug_byte());
                   p_debug_string(); printf("\n"); break;
           case 6: printf("Property %d ",read_debug_byte());
                   p_debug_string(); printf("\n"); break;
           case 7: printf("Action %d ",read_debug_byte());
                   p_debug_string(); printf(" (fake)\n"); break;
           case 8: printf("Action %d ",read_debug_byte());
                   p_debug_string(); printf(" (real)\n"); break;
           case 9: printf("Header of game file is:\n");
                   for (i=0; i<64; i++)
                       printf("%02x ",read_debug_byte());
                   printf("\n"); break;
           case 10: printf("Code line "); p_line(read_debug_linenum());
                    printf(" at (byte address) ");
                    p_address(); printf("\n"); break;
           case 11: k=read_debug_byte(); k=k*256+read_debug_byte();
                    printf("Routine %d (line ",k);
                    l1=read_debug_linenum(); p_line(l1); printf(") ");
                    p_debug_string();
                    while (read_debug_string(junk), junk[0]!=0)
                        printf(" %s",junk);
                    printf("\n"); break;
           case 12: printf("Codeless line "); p_line(read_debug_linenum());
                    printf("\n"); break;
           case 13: printf("Memory map:\n");
                    printf("  array area "); p_address(); printf(" to ");
                    p_address();
                    printf("\n  dictionary "); p_address();
                    printf("\n  code area  "); p_address();
                    printf("\n  strings    "); p_address();
                    printf("\n");
                    break;
           case 14: k=read_debug_byte(); k=k*256+read_debug_byte();
                    printf("Routine %d ends on line ",k);
                    p_line(read_debug_linenum()); printf("\n"); break;
           case 15: printf("Line "); p_line(read_debug_linenum());
                    printf(" is at byte "); p_address();
                    printf(" in its file\n"); break;
           case 16: printf("Size of file %d is ",read_debug_byte());
                    p_address();
                    k=read_debug_byte(); k=k*256+read_debug_byte();
                    printf(" chars, %d lines\n",k); break;
       }
       else
       switch(type)
       {   case 1: read_debug_byte(); read_debug_string(junk);
                   read_debug_string(junk); break;
           case 2: read_debug_linenum();
                   read_debug_string(junk);
                   read_debug_linenum();
                   break;
           case 3: read_debug_byte(); read_debug_byte(); read_debug_linenum();
                   read_debug_string(junk);
                   read_debug_linenum();
                   break;
           case 4: case 5: case 6: case 7: case 8: read_debug_byte();
                   read_debug_string(junk); break;
           case 9: for (i=0; i<64; i++) read_debug_byte(); break;
           case 10: read_debug_linenum();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    break;
           case 11: read_debug_byte(); read_debug_byte();
                    read_debug_linenum(); read_debug_string(junk);
                    while (read_debug_string(junk), junk[0]!=0);
                    break;
           case 12: read_debug_linenum(); break;
           case 13:
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    break;
           case 14: read_debug_byte(); read_debug_byte();
                    read_debug_linenum(); break;
           case 15: read_debug_linenum();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    break;
           case 16: read_debug_byte(); read_debug_byte(); read_debug_byte();
                    read_debug_byte(); read_debug_byte(); read_debug_byte();
                    break;
       }

   } while (type!=0);
   close_debug_file();
}

Files without descriptions:
4MPW_Infoclues.sit.bin  /if-archive/infocom/compilers/inform5/utilities/MPW_Infoclues.sit.bin
0infact.notes   /if-archive/infocom/compilers/inform5/utilities/infact.notes
9infoclue.zip   /if-archive/infocom/compilers/inform5/utilities/infoclue.zip
0infoclues.c    /if-archive/infocom/compilers/inform5/utilities/infoclues.c
0infoclues.notes        /if-archive/infocom/compilers/inform5/utilities/infoclues.notes