/***  dump.c  ***/

#include "al/constant.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <malloc.h>	/* <alloc.h> ?? */
#if sizeofint==2
#define INT16   1
#define INT32   0
#define inta    long
#else
#define INT16   0
#define INT32   1
#define  inta    int
#endif

/** standard prototypes:
	void *calloc(unsigned,unsigned);
	int fprintf(const FILE*,const char*,...);
	int printf(const char*,...);
	int sprintf(char*,const char*,...);
	int fread(void*,int,int,const FILE*);
	int fclose(FILE*);
	void exit(int);
	int fscanf(const FILE*,const char*,...);
	int _filbuf(const FILE*);
**/

/*-----------------------------------------------------------------------*/
/* standard operators */

#define pi_tag_link     3       /* REAL mode value */
#define	PLUSTO		57
#define PLUSAB		58
#define MINAB		59
#define	TIMEAB		60
#define	OVERAB		61
#define	MODAB		62
#define	DIVAB		63

#define	OR		64
#define AND		65

#define EQ_ST		66
#define NE		67
#define LESS		68
#define GREATER		69
#define LE		70
#define GE		71

#define PLUS		72
#define MINUS		73
#define TIMES		74
#define DIV		75
#define OVER		76
#define MOD		77
#define ELEM		78

#define UP		80
#define DOWN		81

#define LWB		82
#define UPB		83
#define PLIT		79

/* unary operators */

#define	NOT		84
#define ABS		85
#define ODD		86
#define	SIGN		87
#define	ENTIER		88
#define ROUND		89
#define	RE		90
#define	IM		91
#define	CONJ		92
#define	ARG		93
#define	REPR		94
#define BIN		95

/*----------------------------------------------------------------------*/
/* identifiers */

#define SQRT		96
#define EXP		97
#define LOG		98
#define COS		99
#define ARCCOS		100
#define SIN		101
#define ARCSIN		102
#define TAN		103
#define ARCTAN		104

#define PRINT		105
#define READ		106
#define WRITE		107

#define NEWLINE		108
#define SPACE		109
#define NEWPAGE		110

#define RANDOM		111
#define BITSPACK	112

#define dummy_tag	017777

/*----------------------------------------------------------------------*/
/* representations */
#if INT32
#define sOPEN	"(     "
#define sCLOSE 	")     "
#define sCOLON	":     "
#define sCOMMA	",     "
#define sVERT	"|     "
#define sAGAIN	"|:    "
#define sGOON	";     "
#define sEXIT	"_\be_\bx_\bi_\bt  "
#define sEQ	"=     "
#define sBECOMES ":=    "
#define sAT	"@     "
#define sGOTO	"_\bg_\bo_\bt_\bo  "
#define sWHILE	"_\bw_\bh_\bi_\bl_\be "
#define sDO	"_\bd_\bo    "
#define sFOR	"_\bf_\bo_\br   "
#define sFROM	"_\bf_\br_\bo_\bm  "
#define sBY	"_\bb_\by    "
#define sTO	"_\bt_\bo    "
#define sOD	"~     "
#define sIS	":=:   "
#define sISNT	":/=:  "
#define sDTRUE	"_\bt_\br_\bu_\be  "
#define sDFALSE	"_\bf_\ba_\bl_\bs_\be "
#define sEMPTY	"_\be_\bm_\bp_\bt_\by "
#define sOF	"_\bo_\bf    "
#define sNIL	"_\bn_\bi_\bl   "
#define sSKIP	"_\bs_\bk_\bi_\bp  "
#else
#define sOPEN   "(     "
#define sCLOSE 	")     "
#define sCOLON	":     "
#define sCOMMA	",     "
#define sVERT	"|     "
#define sAGAIN	"|:    "
#define sGOON	";     "
#define sEXIT   "exit  "
#define sEQ	"=     "
#define sBECOMES ":=    "
#define sAT	"@     "
#define sGOTO   "goto  "
#define sWHILE  "while "
#define sDO     "do    "
#define sFOR    "for   "
#define sFROM   "from  "
#define sBY     "by    "
#define sTO     "to    "
#define sOD	"~     "
#define sIS	":=:   "
#define sISNT	":/=:  "
#define sDTRUE  "true  "
#define sDFALSE "false "
#define sEMPTY  "empty "
#define sOF     "of    "
#define sNIL    "nil   "
#define sSKIP   "skip  "
#endif

/*----------------------------------------------------------------------*/
/* declarative symbols */

#if INT32
#define sVOID   "_\bv_\bo_\bi_\bd  "
#define sREF	"_\br_\be_\bf   "
#define sFLEX	"_\bf_\bl_\be_\bx  "
#define sPROC	"_\bp_\br_\bo_\bc  "
#define sMODE	"_\bm_\bo_\bd_\be  "
#define sSTRUCT	"_\bs_\bt_\br_\bu_\bc_\bt"
#define sUNION	"_\bu_\bn_\bi_\bo_\bn "
#define sOP	"_\bo_\bp    "
#define sPRIO	"_\bp_\br_\bi_\bo  "
#define sINT	"_\bi_\bn_\bt   "
#define sREAL	"_\br_\be_\ba_\bl  "
#define sBOOL	"_\bb_\bo_\bo_\bl  "
#define sCHAR	"_\bc_\bh_\ba_\br  "
#define sSTRING	"_\bs_\bt_\br_\bi_\bn_\bg"
#define sCOMPL	"_\bc_\bo_\bm_\bp_\bl "
#define sBITS	"_\bb_\bi_\bt_\bs  "
#define sLOC	"_\bl_\bo_\bc   "
#define sHEAP	"_\bh_\be_\ba_\bp  "
#else
#define sVOID   "void  "
#define sREF    "ref   "
#define sFLEX   "flex  "
#define sPROC   "proc  "
#define sMODE   "mode  "
#define sSTRUCT "struct"
#define sUNION  "union "
#define sOP     "op    "
#define sPRIO   "prio  "
#define sINT    "int   "
#define sREAL   "real  "
#define sBOOL   "bool  "
#define sCHAR   "char  "
#define sSTRING "string"
#define sCOMPL  "compl "
#define sBITS   "bits  "
#define sLOC    "loc   "
#define sHEAP   "heap  "
#endif
/*----------------------------------------------------------------------*/
/* constants not in program text */
#if INT32
#define sOPROUT	"   -->"
#define sCOLL	"_\bc_\bo_\bl_\bl  "
#define sROW	"_\br_\bo_\bw   "
#define sBOOK	"_\bf_\bi_\bl_\be  "
#define sENDPROG "_\bE_\bO_\bP   "
#else
#define sOPROUT "   -->"
#define sCOLL   "coll  "
#define sROW    "row   "
#define sBOOK   "file  "
#define sENDPROG "EOP   "
#endif
/*----------------------------------------------------------------------*/
/* standard operators */

#if INT32
#define splusto_ST      "=:+   "
#define splusab_ST	"+:=   "
#define sminab_ST	"-:=   "
#define	stimeab_ST	"*:=   "
#define	soverab_ST	"%:=   "
#define	smodab_ST	"_\bm_\bo_\bd_\ba_\bb "
#define	sdivab_ST	"/:=   "

#define	sor_ST		"_\bo_\br    "
#define sand_ST		"_\ba_\bn_\bd   "

#define seq_ST		"=     "   /* has internal form 66, see in repr.c */
#define sne_ST		"/=    "
#define sless_ST	"<     "
#define sgreater_ST	">     "
#define sle_ST		"<=    "
#define sge_ST		">=    "

#define splus_ST	"+     "
#define smin_ST		"-     "
#define stimes_ST	"*     "
#define sdiv_ST		"/     "
#define sover_ST	"_\bo_\bv_\be_\br  "
#define smod_ST		"_\bm_\bo_\bd   "
#define selem_ST	"_\be_\bl_\be_\bm  "

#define sup_ST		"_\bu_\bp    "
#define sdown_ST	"_\bd_\bo_\bw_\bn  "

#define supb_ST		"_\bu_\bp_\bb   "
#define slwb_ST		"_\bl_\bw_\bb   "
#define split_ST	"_\bi     "

/* unary operators */

#define	snot_ST		"_\bn_\bo_\bt   "
#define sabs_ST		"_\ba_\bb_\bs   "
#define sodd_ST		"_\bo_\bd_\bd   "
#define	ssign_ST	"_\bs_\bi_\bg_\bn  "
#define	sentier_ST	"_\be_\bn_\bt   "
#define sround_ST	"_\br_\bo_\bu_\bn_\bd "
#define	sre_ST		"_\br_\be    "
#define	sim_ST		"_\bi_\bm    "
#define	sconj_ST	"_\bc_\bo_\bn_\bj  "
#define	sarg_ST		"_\ba_\br_\bg   "
#define	srepr_ST	"_\br_\be_\bp_\br  "
#define sbin_ST		"_\bb_\bi_\bn   "
#else
#define splusto_ST      "=:+   "
#define splusab_ST	"+:=   "
#define sminab_ST	"-:=   "
#define	stimeab_ST	"*:=   "
#define	soverab_ST	"%:=   "
#define smodab_ST       "modab "
#define	sdivab_ST	"/:=   "

#define sor_ST          "or    "
#define sand_ST         "and   "

#define seq_ST		"=     "   /* has internal form 66, see in repr.c */
#define sne_ST		"/=    "
#define sless_ST	"<     "
#define sgreater_ST	">     "
#define sle_ST		"<=    "
#define sge_ST		">=    "

#define splus_ST	"+     "
#define smin_ST		"-     "
#define stimes_ST	"*     "
#define sdiv_ST		"/     "
#define sover_ST        "over  "
#define smod_ST         "mod   "
#define selem_ST        "elem  "

#define sup_ST          "up    "
#define sdown_ST        "down  "

#define supb_ST         "upb   "
#define slwb_ST         "lwb   "
#define split_ST        "i     "

/* unary operators */

#define snot_ST         "not   "
#define sabs_ST         "abs   "
#define sodd_ST         "odd   "
#define ssign_ST        "sign  "
#define sentier_ST      "ent   "
#define sround_ST       "round "
#define sre_ST          "re    "
#define sim_ST          "im    "
#define sconj_ST        "conj  "
#define sarg_ST         "arg   "
#define srepr_ST        "repr  "
#define sbin_ST         "bin   "
#endif
/*----------------------------------------------------------------------*/
/* identifiers */

#define sSQRT		"sqrt  "
#define sEXP		"exp   "
#define sLOG		"log   "
#define sCOS		"cos   "
#define sARCCOS		"arccos"
#define sSIN		"sin   "
#define sARCSIN		"arcsin"
#define sTAN		"tan   "
#define sARCTAN		"arctan"

#define sPRINT		"print "
#define sREAD		"read  "
#define sWRITE		"write "

#define sNEWLINE	"nwline"
#define sSPACE		"space "
#define sNEWPAGE	"nwpage"

#define sRANDOM		"random"
#define sBITSPACK	"bitpck"

#define spi_tag		"pi    "
#define sre_tag		"%re   "
#define sim_tag		"%im   "
#define sstand_in	"stdin "
#define sstand_out	"stdout"
#define sbitswidth	"bitswd"
#define sblank_tag	"blank "
#define sdummy		"dummy "

/*----------------------------------------------------------------------*/
/* prototypes */

void create_arrays(void);	int  straighten(void);
void inp(char*);		void possibilities(void);
void welcome(void);		void single_A(int);
void X_simple(int);		void single_ABC(int);
void X_ident(int);		void out_ABCD(void);
int  X_indicator(int,int);	void int_DN(int);
void X_integer(int);		void real_DN(int);
void X_real(int);		void bits_DN(int);
void X_char(int);		void char_DN(int);
void X_string(int);		int  string_DN(int,int);
void X_bits(int);		void single_DN(int*,int*);
void X_denotation(int);		int  count_DN(int);
void out_X(void);		void out_DN(void);
void single_IND(int);		void goodby(void);
void deal_row(int);		void full_out(void);
void single_BC(int);		void out_IND(void);
/*----------------------------------------------------------------------*/

FILE *df;

short int *X, *A, *D, *D1, *LIND, *VIND, *DN_descr; int *DN, *B, *C; 
int Errnum,P,PX,Z,J,JGLOB,MORF,PLAB,FS,
	init_A,max_A,max_X,max_PX,max_IND,max_DN;

void create_arrays()
{	LIND = (short int *)calloc(J+1,sizeof(short int));
	VIND = (short int *)calloc(J+1,sizeof(short int));
	A    = (short int *)calloc(max_A+1,sizeof(short int));
	B    = (int *)calloc(max_A+1,sizeof(int));
	C    = (int *)calloc(max_A+1,sizeof(int));
	D    = (short int *)calloc(max_A+1,sizeof(short int));
	D1   = (short int *)calloc(max_A+1,sizeof(short int));
	X    = (short int *)calloc(PX+1,   sizeof(short int));
	DN   = (int *)calloc(max_DN+1,sizeof(int));
	DN_descr=(short int *)calloc(max_DN+1,sizeof(short int));
}

void inp(dump_file) char *dump_file;
{int i;
	df=fopen(dump_file,"rb");
	if(df==NULL){
	    fprintf(stderr,"cannot open %s, aborted\n",dump_file);exit(1);
	}
	if(fscanf(df,"%d%d%d%d%d%d%d%d%d",
		   &Errnum,&P,&PX,&Z,&J,&JGLOB,&MORF,&PLAB,&FS) != 9 ||
	   fscanf(df,"%d%d%d%d%d%d",
		   &init_A,&max_A,&max_X,&max_PX,&max_IND,&max_DN) != 6){
		fprintf(stderr,"file %s is ruined\n",dump_file);exit(1);
	}
	i=0; while(++i<10 && getc(df)>0);
	if(i>9){fprintf(stderr,"file %s is ruined\n",dump_file);exit(1);}
	create_arrays(); /* asks memory for the arrays */
	if(fread(&X[1],sizeof(short int),PX,df)!=PX ||
	   fread(&A[1],sizeof(short int),max_A,df)!=max_A ||
	   fread(&B[1],sizeof(      int),max_A,df)!=max_A ||
	   fread(&C[1],sizeof(      int),max_A,df)!=max_A ||
	   fread(&D[1],sizeof(short int),max_A,df)!=max_A ||
	   fread(&LIND[1],sizeof(short int),J,df)!=J ||
	   fread(&VIND[1],sizeof(short int),J,df)!=J ||
	   fread(&DN[1],sizeof(int),max_DN+1,df)!=max_DN+1){
	       fprintf(stderr,"file %s is ruined\n",dump_file);exit(1);
	 }
	 fclose(df);
}

void welcome() /* prints the header and other useful information */
{int i;
	printf("\n%40s\n\n","D U M P");
	if(Errnum)printf("\nError number:         %4.1f",Errnum/10.0);
	printf("\nprogram address:      %d\n",P);
	while(FS){i=D[FS]; D[FS]= -1; FS=i;}
	max_A++; while(D[--max_A]<0);
	if(D[Z]>0){D[Z]++; printf("last value:           %d\n",Z);}
	if(PLAB)   printf("address of last jump: %d\n",PLAB);
	printf("the statement is %sMORF\n\n",MORF?"":"CO");
}

#if INT32
union { double e; struct { int i1, i2;} ii ;} eii;
#define real_part(x,v)  {eii.ii.i1=B[v]; eii.ii.i2=C[v]; x=eii.e;}
#define real_den(x,v)   {eii.ii.i1=DN[v]; eii.ii.i2=DN[v+1]; x=eii.e;}
#else
union {double e; struct{ int i1,i2,i3,i4;}ii;} eii; int _vv;
#define real_part(x,v)  \
    {eii.ii.i1=C[v]; _vv=B[v]; eii.ii.i2=A[_vv]; \
     eii.ii.i3=B[_vv]; eii.ii.i4=C[_vv]; x=eii.e;}
#define real_den(x,v)   \
    {eii.ii.i1=DN[v]; eii.ii.i2=DN[v+1]; \
     eii.ii.i3=DN[v+2]; eii.ii.i4=DN[v+3]; x=eii.e;}
#endif

int was_OPROUT = 0;
void X_simple(p) int p;
{char *c;
	if(was_OPROUT){was_OPROUT=0; printf(" %-6d",p); return;}
	switch(p){
	case OPEN:	c=sOPEN; break;
	case CLOSE:	c=sCLOSE; break;
	case COLON:	c=sCOLON; break;
	case COMMA:	c=sCOMMA; break;
	case VERT:	c=sVERT; break;
	case AGAIN:	c=sAGAIN; break;
	case GOON:	c=sGOON; break;
	case EXIT:	c=sEXIT; break;
	case EQ:	c=sEQ; break;
	case BECOMES:	c=sBECOMES; break;
	case AT:	c=sAT; break;
	case GOTO:	c=sGOTO; break;
	case WHILE:	c=sWHILE; break;
	case DO:	c=sDO;	break;
	case FOR:	c=sFOR; break;
	case FROM:	c=sFROM; break;
	case BY:	c=sBY; break;
	case TO:	c=sTO; break;
	case OD:	c=sDO; break;
	case IS:	c=sIS; break;
	case ISNT:	c=sISNT; break;
	case DTRUE:	c=sDTRUE; break;
	case DFALSE:	c=sDFALSE; break;
	case EMPTY:	c=sEMPTY; break;
	case OF:	c=sOF; break;
	case NIL:	c=sNIL; break;
	case SKIP:	c=sSKIP; break;

	case VOID:	c=sVOID; break;
	case REF:	c=sREF; break;
	case FLEX:	c=sFLEX; break;
	case PROC:	c=sPROC; break;
	case MODE:	c=sMODE; break;
	case STRUCT:	c=sSTRUCT; break;
	case UNION:	c=sUNION; break;
	case OP:	c=sOP; break;
	case PRIO:	c=sPRIO; break;
	case INT:	c=sINT; break;
	case REAL:	c=sREAL; break;
	case BOOL:	c=sBOOL; break;
	case CHAR:	c=sCHAR; break;
	case STRING:	c=sSTRING; break;
	case COMPL:	c=sCOMPL; break;
	case BITS:	c=sBITS; break;
	case LOC:	c=sLOC; break;
	case HEAP:	c=sHEAP; break;
	case OPROUT:	c=sOPROUT; was_OPROUT=1; break;
	case COLL:	c=sCOLL; break;
	case ROW:	c=sROW; break;
	case BOOK:	c=sBOOK; break;
	case ENDPROG:	c=sENDPROG; break;
	default:	printf(" \\%-5d",p); return;
	}
	printf(" %6s",c);
}

void X_ident(p) int p;
{char *c;
	switch(p){
	case SQRT:	c=sSQRT; break;
	case EXP:	c=sEXP; break;
	case LOG:	c=sLOG; break;
	case COS:	c=sCOS; break;
	case ARCCOS:	c=sARCCOS; break;
	case SIN:	c=sSIN; break;
	case ARCSIN:	c=sARCSIN; break;
	case TAN:	c=sTAN; break;
	case ARCTAN:	c=sARCTAN; break;

	case PRINT:	c=sPRINT; break;
	case READ:	c=sREAD; break;
	case WRITE:	c=sWRITE; break;

	case NEWLINE:	c=sNEWLINE; break;
	case SPACE:	c=sSPACE; break;
	case NEWPAGE:	c=sNEWPAGE; break;

	case RANDOM:	c=sRANDOM; break;
	case BITSPACK:	c=sBITSPACK; break;

	case pi_tag:	c=spi_tag; break;
	case re_tag:	c=sre_tag; break;
	case im_tag:	c=sim_tag; break;
	case stand_in:	c=sstand_in; break;
	case stand_out:	c=sstand_out; break;
	case bitswidth:	c=sbitswidth; break;
	case blank_tag:	c=sblank_tag; break;
	case dummy_tag:	c=sdummy; break;

	default:	printf(" %%%d%s",p,&"     "[p<10?1:p<100?2:3]);
			return;
	}
	printf(" %6s",c);
}

int start_indi=0;
int X_indicator(p,how) int p,how;
{char *c; int i;
	switch(p){
	case PLUSTO:	c=splusto_ST; break;
	case PLUSAB:	c=splusab_ST; break;
	case MINAB:	c=sminab_ST; break;
	case TIMEAB:	c=soverab_ST; break;
	case OVERAB:	c=soverab_ST; break;
	case MODAB:	c=smodab_ST; break;
	case DIVAB:	c=sdivab_ST; break;

	case OR:	c=sor_ST; break;
	case AND:	c=sand_ST; break;

	case EQ_ST:	c=seq_ST; break;
	case NE:	c=sne_ST; break;
	case LESS:	c=sless_ST; break;
	case GREATER:	c=sgreater_ST; break;
	case LE:	c=sle_ST; break;
	case GE:	c=sge_ST; break;

	case PLUS:	c=splus_ST; break;
	case MINUS:	c=smin_ST; break;
	case TIMES:	c=stimes_ST; break;
	case DIV:	c=sdiv_ST; break;
	case OVER:	c=sover_ST; break;
	case MOD:	c=smod_ST; break;
	case ELEM:	c=selem_ST; break;

	case UP:	c=sup_ST; break;
	case DOWN:	c=sdown_ST; break;

	case LWB:	c=slwb_ST; break;
	case UPB:	c=supb_ST; break;
	case PLIT:	c=split_ST; break;

/* unary operators */

	case NOT:	c=snot_ST; break;
	case ABS:	c=sabs_ST; break;
	case ODD:	c=sodd_ST; break;
	case SIGN:	c=ssign_ST; break;
	case ENTIER:	c=sentier_ST; break;
	case ROUND:	c=sround_ST; break;
	case RE:	c=sre_ST; break;
	case IM:	c=sim_ST; break;
	case CONJ:	c=sconj_ST; break;
	case ARG:	c=sarg_ST; break;
	case REPR:	c=srepr_ST; break;
	case BIN:	c=sbin_ST; break;

/* none of these */

	default:	i=0; while(i<start_indi && X[i]!=p)i++;
			if(i==start_indi){
			    if(how) return(1);
			    X[start_indi++]=p;
			}
			i=0; while(p){
#if INT32
			    printf(i==0?" _\b%%_\b%c":"_\b%c",'A'+p%26);
#else
                            printf(i==0?" %%%c":"%c",'A'+p%26);
#endif
			    i++; p /= 26;
			} printf("%s",&"     "[i]); return(0);
	}
	printf(" %6s",c); return(0);
}

char temp[50];
void X_integer(p) int p;
{inta i;
#if INT32
	i=DN[p];
	if(i>=0){printf(" %-6d",i); return;}
#else
        i=(long)(((((unsigned long)(unsigned)DN[p])<<16)|
            ((unsigned long)(unsigned)DN[p+1])));
        if(i>=0){printf(" %-6ld",i); return;}
#endif
	printf(" i|%-4d",p); DN_descr[p] |= 1;
}

void X_real(p) int p;
{float e;
	real_den(e,p); sprintf(temp," %-6g",e);
	if(temp[7]==0){printf("%s",temp); return;}
	printf(" r|%-4d",p); DN_descr[p] |=2;
}

void X_char(p) int p;
{int i;
	if((i=DN[p])<128 && i>=32){printf(" \"%c\"   ",i); return;}
	printf(" c|%-4d",p); DN_descr[p] |= 4;
}

void X_string(p) int p;
{int i,j;
	if((i=DN[p])<5 && i>=0){
	    if(i==0){printf(" %s","\"\"    "); return;}
	    j=p; while(++j<=p+i && 31<DN[j] && DN[j]<128);
	    if(j>p+i){
		j=p; while(++j<=p+i)printf(j==p+1?" \"%c":"%c",DN[j]);
		printf("\"%s",&"    "[i]); return;
	    }
	}
	printf(" s|%-4d",p); DN_descr[p] |= 16;
}

void X_bits(p) int p;
{
#if INT32
        sprintf(temp," %#-6o",DN[p]);
#else
        sprintf(temp," %#-6lo", (((((unsigned long)(unsigned)DN[p])<<16)|
            ((unsigned long)(unsigned)DN[p+1]))));
#endif
	if(temp[7]==0){printf("%s",temp); return;}
	printf(" b|%-4d",p); DN_descr[p] |= 8;
}

void X_denotation(p) int p;
{	switch(p & 016000){
	case 000000:	X_integer(p); break;
	case 002000:	X_real(p&01777); break;
	case 004000:	X_char(p&01777); break;
	case 006000:	X_string(p&01777); break;
	case 010000:	X_bits(p&01777); break;
	default:	printf("!%-6d",p); return;
	}
}

void out_X()
{int i,j,p;
	printf("\n\n%50s\n\n","P r o g r a m    t e x t");
	for(i=1;i<=PX;i += 10){
	    printf("\n%4d",i);
	    for(j=i;j<=PX && j<i+10;j++){
		switch((p=X[j])&060000){
		    case 000000: X_simple(p); break;
		    case 020000: X_ident(p&017777); break;
		    case 040000: X_indicator(p&017777,0); break;
		    case 060000: X_denotation(p&017777); break;
		}
	    }
	}
	printf("%s\n","\n\n");
}

#define PART	077777

void single_IND(p) int p;
{int L,V;
	if(p>J)return;
	L=LIND[p]; V=VIND[p]; printf("%4d",p);
	if(L==PART){printf(" ------- %4d     ",p-V); return;}
	if(X_indicator(L&017777,1))X_ident(L&017777);
	printf("  %4d%s    ",V,L&020000?"*":" ");
	if(D[V]>0)D[V]++;
}

void out_IND()
{int i,p,k;
	printf("\n\n%47s\n\n","L i n k a g e   a r e a");
	p=0; while(++p<=J && LIND[p]!=PART);
	k=J+1-p; k=k>14?(k+2)/3:k>6?(k+1)/2:k;
	for(i=0;i<3;i++)printf("  i%15s    ","object value");
	printf("%s","\n"); was_OPROUT = 0;
	for(i=p;i<p+k;i++){
	    printf("%s","\n");
	    single_IND(i); single_IND(i+k); single_IND(i+k+k);
	}
	printf("%s\n","\n\n");
}

#define deal(v)	{if(D1[v]==1)D1[v]++;}

void deal_row(v) int v;
{int i,offst,n,vv,index,j,k;
	if((n=C[v])==0){deal(B[v]); return;}
	vv=v+A[v];
	for(index=0;index<n;index++){
	    offst=B[v]; j=index;
	    for(i=vv;i>v;i--){offst+=(j%(k=B[i]-A[i]+1))*C[i];j/=k;}
	    deal(offst);
	}
}

int straighten()
{int i,v,bn,bv,done;
	done=0;
	for(v=init_A;v<=max_A;v++)if(D1[v]==2){
	    D1[v]=8; done=1; bv=B[v]; switch(A[v]){
		case REF:
		case MODE:	if(bv>0)deal(bv); break;
		case STRUCT:
		case COLL:	bn=C[v]+bv;
				for(i=bv;i<bn;i++){deal(B[i]);D1[i]=7;}
				break;
		case PROC:	bn=C[v]+bv+1;
				for(i=bv;i<bn;i++){deal(B[i]);D1[i]=7;}
				break;
		case OP:	bn=bv+(C[v]<10?3:2);
				for(i=bv;i<bn;i++){deal(B[i]);D1[i]=7;}
				break;
		case UNION:	bn=bv+C[bv]; deal(C[v]);
				for(i=bv;i<bn;i++){deal(B[i]);D1[i]=7;}
				break;
		case ROW:	bn=bv+A[bv]; deal_row(bv);
				for(i=bv;i<=bn;i++)D1[i]=7;
				break;
#if INT16
                case REAL:      D1[bv]=0; break;
#endif
	    }
	}
	return(done);
}

void possibilities()
{int i,v,bv,bn,dbv,done;
	for(v=init_A;v<=max_A;v++) if(D1[v]==1||D1[v]==5){
	    bv=bn=B[v]; done=1; switch(A[v]){
		case STRUCT:
		case COLL:	bn=bv+C[v]; break;
		case ROW:	bn=bv+A[bv]+1; break;
		case PROC:	bn=bv+C[v]+1; break;
		case OP:	bn=bv+(C[v]<10?2:3); break;
		case UNION:	bn=bv+C[bv]; break;
#if INT16
                case REAL:      done=0;
                                if(init_A<=bv && bv<=max_A && (3&D1[bv])!=0)
                                    D1[bv]=0;
                                break;
#endif
		default:	done=0; break;
	    }
	    if(done && init_A<=bv && bv<bn && bn<=max_A && (dbv=(3&D1[bv]))!=0){
		i=bv; while(++i<bn && (3&D1[i])==dbv);
		if(i==bn){
		    for(i=bv;i<bn;i++)D1[i]=5;
		}
	    }
	}
}

void single_A(x) int x;
{	printf(" (%2d)",x); X_simple(x); 
}

void single_BC(x) int x;
{	printf(" %6d",x);
}

#if INT16
#define int_value(v)  (long)(((((unsigned long)(unsigned)B[v])<<16)|((unsigned long)(unsigned)C[v])))
#endif

void single_ABC(v) int v;
{int j,a,b; float e;
	if(v>=max_A)return;
	if((j=D1[v])<0)j= -j; printf("%4d%c",j,D[j]&040000?'*':' ');
	if(D1[v]>0){switch(a=A[j]){
	    case VOID: case PRIO: case BOOL: case REF: case MODE: case BOOK:
	    case STRUCT: case COLL: case ROW: case PROC: case UNION:
	    case OP:
		single_A(a); single_BC(B[j]); single_BC(C[j]); return;
	    case CHAR:
		single_A(a); if((b=B[j])<32 || b>126){
		    single_BC(b); printf("%7s","");
		}else{
		    printf("    \"%c\"%7s",b,""); 
		} return;
	    case INT:
#if INT32
                single_A(a); printf(" %6d%7s",B[j],"");
#else
                single_A(a); printf(" %6ld%7s",int_value(j),"");
#endif
		return;
	    case BITS:
#if INT32
		single_A(a);if((b=B[j])&037777700000){
		    printf(" %#-13o",b);
		}else{
		    printf(" %#6o%7s",b,"");
		} return;
#else
		single_A(a);if((int_value(j))&037777700000L){
                    printf(" %#-13lo",int_value(j));
		}else{
                    printf(" %#6lo%7s",int_value(j),"");
                } return;
#endif
            case REAL:
		single_A(a); real_part(e,j); printf(" %-13g",e); return;
	}}
	printf("      %-6d",A[j]);
	single_BC(B[j]); single_BC(C[j]);
	return;
}

void out_ABCD()
{int i,k,di;
	for(i=init_A;i<=max_A;i++)D1[i]=D[i]<0?0:D[i]>1?2:1;
#if INT16
        D1[B[pi_tag_link]]=0;
#endif
	while(straighten()); possibilities();
	/* a descriptor if D1[.] is 7 or 5; otherwise it is 1 or 8 */
	k=0; /* for(i=1;i<20;i++)D1[k++]=i; */
	for(i=init_A;i<=max_A;i++){
	    if((di=D1[i])!=0)D1[k++]=di&4?-i:i;
	} 
	max_A=k; k=(max_A+1)/2; /* number of items */
	printf("\n\n%49s\n\n","W o r k i n g   a r e a");
	for(i=0;i<2;i++)printf("  i%10s%10s%7s        ","A","B","C");
	printf("%s","\n");
	for(i=0;i<k;i++){
	    printf("%s","\n");
	    single_ABC(i); printf("%7s",""); single_ABC(i+k);
	}
	printf("%s\n","\n\n");
}

void int_DN(p) int p;
#if INT32
{       printf("i|%-4d  %-28d",p,DN[p]);}
#else
{       printf("i|%-4d  %-28ld",p,(((unsigned long)(unsigned)DN[p])<<16)|
            ((unsigned long)(unsigned)DN[p+1]));}
#endif

void real_DN(p) int p;
#if INT32
{double e; real_den(e,p);  printf("r|%-4d  %-28g",p,e);}
#else
{double e; real_den(e,p);  printf("r|%-4d  %-28lg",p,e);}
#endif

void bits_DN(p) int p;
#if INT32
{	printf("b|%-4d  %#-28o",p,DN[p]);}
#else
{       printf("i|%-4d  %#-28lo",p,(((unsigned long)(unsigned)DN[p])<<16)|
            ((unsigned long)(unsigned)DN[p+1]));}
#endif

void char_DN(p) int p;
{	printf("c|%-4d  \\%-27o",p,DN[p]);}

int string_DN(p,typ) int p,typ; /*returns 0 if the string ends,otherwise 16 */
{int len,q0,q1,res,i,b;
	if(typ<5)printf("s|%-4d \"",p);else printf("s|cont%2s","");
	len=DN[p]; q0=p+1+25*(typ-4); res=0;
	if((q1=p+1+len)>q0+25){q1=q0+25; res=16;}
	for(i=q0;i<q1;i++){
	    b=DN[i]; if(b<32||b>126)printf("%s","-\b?");else printf("%c",b);
	}
	if(i>p+len){i++; printf("%c",'\"');}
	while(i<q0+28){i++; printf("%c",' ');}
	return(res);
}

void single_DN(p,typ) int *p,*typ;
{int d;
	while(*p<=max_DN && (d=DN_descr[*p])==0) ++*p;
	if(*p>max_DN) return;
	switch(*typ){
	case 0:	if(d&1){ int_DN(*p); *typ=1; d&=036; break;}
	case 1:	if(d&2){real_DN(*p); *typ=2; d&=034; break;}
	case 2: if(d&4){char_DN(*p); *typ=3; d&=030; break;}
	case 3: if(d&8){bits_DN(*p); *typ=4; d&=020; break;}
		*typ=4;
	default:d=string_DN(*p,*typ); ++*typ; break;
	}
	if(d==0){*typ=0; ++*p;}
	return;
}

int count_DN(i) int i;
{int k,d;
	d=DN_descr[i]; k=0;
	if(d&16)k+=(DN[i]+24)/25; d &= 15;
	while(d){k+=(d&1);d >>=1;}
	return(k);
}

void out_DN()
{int i,p,q,p0,q0,k;
	i=0;for(p=1;p<=max_DN;p++)i+=count_DN(p);
	if(i==0)return; k=(i+1)/2; p=q=1; p0=q0=0;
	i=0; while(i<k){i+=count_DN(q); q++;} k=q;
	printf("\n\n%49s\n\n","D e n o t a t i o n s");
	while(p<k){
	    printf("%s","\n"); single_DN(&p,&p0);
	    printf("%6s",""); single_DN(&q,&q0);
	}
	printf("%s\n\n","\n");
}

void goodby() /* the last line of the dump */
{	printf("\n%s\n","***** end of dump *****");
}

void LV_raw(int L,int V)
{
    if(L==PART){ printf("    ------%10d",V); return; }
    switch(L&060000){
      case 000000:      printf("%10d%10d",L,V); break;
      case 060000:      printf("%8d:%1d%10d",L&01777,3+((L&016000)>>10),V);
                        break;
      default:          printf("%8d:%1d%10d",L&017777,(L&060000)>>13,V);
                        break;
    }
}

void full_out()
{int i,j;
	printf("\n%40s\n\n","D U M P");
	printf("\nP=%d,PX=%d,Z=%d,J=%d,JGLOB=%d,MORF=%d,PLAB=%d,FS=%d\n",
		P,PX,Z,J,JGLOB,MORF,PLAB,FS);
	printf("init_A=%d,max_A=%d,max_X=%d,max_PX=%d,max_IND=%d,max_DN=%d\n",
		init_A,max_A,max_X,max_PX,max_IND,max_DN);
	printf("\n\nProgram text in X[1:%d]\n",PX);
	for(i=1;i<=PX;i+=10){
	    printf("\n%4d",i);
            for(j=i;j<i+10 && j<=PX; j++) switch(X[j]&060000){
                case 000000: printf("%5d  ",X[j]); break;
                case 060000: printf("%5d:%1d",X[j]&01777,3+((X[j]&016000)>>10));
                             break;
                default:     printf("%5d:%1d",X[j]&017777,(X[j]&060000)>>13);
                             break;
                }
	}
	printf("\n\n\nDenotations DN[1:%d]\n",max_DN+1);
	for(i=1;i<max_DN+2;i+=4){
	    printf("\n%5d",i);
	    for(j=i;j<i+4 && j<max_DN+2;j++)printf("%15d",DN[j]);
	}
	printf("\n\n\nWorking area in A,B,C,D[1:%d]\n\n",max_A);
	for(i=1;i<=max_A;i++)
	    printf("%6d%12d%12d%12d%12d\n",i,A[i],B[i],C[i],D[i]);
	printf("\n\nLinkage area LIND,VIND[1:%d]\n",J);
	for(i=1;i<=J;i+= 2){
            printf("\n%4d",i); LV_raw(LIND[i],VIND[i]);  
            if(i<J){printf("    |%4d",i+1); LV_raw(LIND[i+1],VIND[i+1]);}
	}
	printf("\n\n\n%s\n","***** end of dump *****");
}

int main(argc,argv) int argc; char *argv[];
{
	if(argc<2){fprintf(stderr,"%s\n","args: %dump [-]"); exit(1);}
	if(argc==3 && *argv[2]=='-' && argv[2][1]==0){
	    inp(argv[1]); full_out();
	}else{
            signal(SIGFPE,SIG_IGN); /* no floating pont error */
	    inp(argv[1]);
	    welcome();out_X(); out_DN(); out_IND(); out_ABCD();
	    goodby();
	}
	return 0;
}
