/*
* $Id: gfix.c,v 1.3 2025/03/09 19:14:25 snw Exp $
* display freem database blocks on-screen
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2020, 2025 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
* $Log: gfix.c,v $
* Revision 1.3 2025/03/09 19:14:25 snw
* First phase of REUSE compliance and header reformat
*
*
* SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
* SPDX-License-Identifier: AGPL-3.0-or-later
**/
#include <stdlib.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include "mpsdef0.h"
#include "errmsg.h"
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
/* needed if byte data are to be interpreted as unsigned integer */
#define UNSIGN(A) ((A)&0377)
#define g_EOL 30
#define POINT 28
#define MINUS 26
#define ROOT 0L
/* length of blocks. status bytes defined as offset to blocklength */
#define BLOCKLEN 1024
#define DATALIM (BLOCKLEN-11)
#define LLPTR (BLOCKLEN-10)
#define NRBLK LLPTR
#define RLPTR (BLOCKLEN- 6)
#define FREE RLPTR
#define BTYP (BLOCKLEN- 3)
#define OFFS (BLOCKLEN- 2)
#define PLEN 3
#define EMPTY 0
#define FBLK 1
#define POINTER 2
#define BOTTOM 6
#define DATA 8
#define LF 10
#define CR 13
#define SPC ' '
#define NUL 0
#define DEL 127
#ifndef SYSFIVE
#define FreeM_timezone -3600
#else
#ifdef __CYGWIN__
#define FreeM_timezone _timezone
#else
extern long FreeM_timezone;
#endif /* __CYGWIN__ */
#endif /* SYSFIVE */
/* mumps commands */
#define BREAK 'b'
#define CLOSE 'c'
#define DO 'd'
#define DO_BLOCK 2
#define ELSE 'e'
#define FOR 'f'
#define GOTO 'g'
#define HA 'h'
#define HALT '0'
#define HANG '1'
#define IF 'i'
#define JOB 'j'
#define KILL 'k'
#define LOCK 'l'
#define NEW 'n'
#define OPEN 'o'
#define QUIT 'q'
#define READ 'r'
#define SET 's'
#define USE 'u'
#define VIEW 'v'
#define WRITE 'w'
#define XECUTE 'x'
#define ZALLOCATE 'A'
#define ZBREAK 'B'
#define ZDEALLOCATE 'D'
#define ZGO 'G'
#define ZHALT 'H'
#define ZINSERT 'I'
#define ZJOB 'J'
#define ZLOAD 'L'
#define ZNEW 'N'
#define ZPRINT 'P'
#define ZQUIT 'Q'
#define ZREMOVE 'R'
#define ZSAVE 'S'
#define ZTRAP 'T'
#define ZWRITE 'W'
#define PRIVATE SP
int
main (argc, argv)
int argc; /* arguments count */
char *argv[]; /* arguments string */
{
static char ASCII[] = "NULSOHSTXETXEOTENQACKBELBS TABLF VT FF CR SO SI DLEDC1DC2DC3DC4NAKSYNETBCANEM SUBESCFS GS RS US ";
char filnam[40];
short filedes;
char block[BLOCKLEN];
char key[512];
char data[1024];
long blknbr;
short offset;
short type;
unsigned long pointer;
short length;
short koffs;
register int i,
j,
k,
ch;
filnam[0] = '^';
filnam[1] = 0;
if (argc > 1) {
j = 0;
while (--argc > 0) {
j++; /* accept it with or without '^' sign */
if (**(argv + j) == '-') {
fprintf (stderr, "usage is: %s [^]global\012\015", *argv);
exit (0);
}
if (**(argv + j) == '^')
strcpy (filnam, *(argv + j));
else
strcpy (&filnam[1], *(argv + j));
}
} else {
printf ("\012\015display global ^");
scanf ("%s", &filnam[1]);
}
if ((filedes = open (filnam, 0)) == -1) {
printf ("cannot open file %s\007\012\015", filnam);
exit (0);
}
again:;
printf ("\012\015display block #");
scanf ("%ld", &blknbr);
if (blknbr < 0) {
printf ("\012\015*** done ***\012\015\033[r\033[24H");
exit (0);
}
lseek (filedes, blknbr * 1024L, 0);
if (read (filedes, block, BLOCKLEN) == 0) {
printf ("block #%ld does not exist\007\012\015-1 will terminate", blknbr);
goto again;
}
printf ("\033[r\033[2Jglobal\033[;20H%s\033[;40Hblock\033[;60H%ld",
filnam,
blknbr);
printf ("\033[2Hblock type\033[2;20H");
type = block[BTYP];
switch (type) {
case DATA:
printf ("DATA");
break;
case POINTER:
printf ("POINTER");
break;
case BOTTOM:
printf ("BOTTOM POINTER");
break;
case EMPTY:
printf ("EMPTY");
break;
case FBLK:
printf ("FBLK");
break;
default:
printf ("ILLEGAL TYPE");
type = DATA;
}
if (blknbr == ROOT)
printf (", ROOT");
offset = UNSIGN (block[OFFS]) * 256 +
UNSIGN (block[OFFS + 1]);
printf ("\033[2;40Hoffset\033[2;60H%d", offset);
if (offset > DATALIM || (type == FBLK && offset % PLEN)) {
printf (" ???");
offset = DATALIM;
}
pointer = UNSIGN (block[LLPTR]) * 65536 +
UNSIGN (block[LLPTR + 1]) * 256 +
UNSIGN (block[LLPTR + 2]);
printf ("\033[3H%s\033[3;20H%ld",
blknbr != ROOT ? "LEFT LINK POINTER" : "NR_OF_BLKS",
pointer);
pointer = UNSIGN (block[RLPTR]) * 65536 +
UNSIGN (block[RLPTR + 1]) * 256 +
UNSIGN (block[RLPTR + 2]);
printf ("\033[3;40H%s\033[3;60H%ld",
blknbr != ROOT ? "RIGHT LINK POINTER" : "FREE",
pointer);
printf ("\033[4;24r\033[4H"); /* define scrolling area */
if (type == FBLK) {
i = 0;
while (i < offset) {
k = UNSIGN (block[i]) * 65536 +
UNSIGN (block[i + 1]) * 256 +
UNSIGN (block[i + 2]);
i += PLEN;
printf ("%8d", k);
}
goto again;
}
i = 0;
while (i < offset) {
printf ("\012\015%3d", i);
length = UNSIGN (block[i++]);
k = koffs = UNSIGN (block[i++]);
if ((i + length) > offset)
break;
for (j = 0; j < length; j++)
key[k++] = block[i++];
key[k] = g_EOL;
/*----------------------*/
{
short ch0,
i,
j,
k,
typ;
j = 0;
i = 0;
data[j++] = '(';
k = 1;
while ((ch = UNSIGN (key[i++])) != g_EOL) {
if (k) {
k = 0;
if ((typ = (ch > SPC)))
data[j++] = '"';
}
ch0 = (ch >= SPC ? (ch >> 1) : /* 'string' chars */
(ch < 20 ? (ch >> 1) + '0' : /* 0...9 */
(ch >> 1) + SPC)); /* '.' or '-' */
if (ch0 == DEL) {
if (((ch = UNSIGN (key[i++])) >> 1) == DEL) {
ch0 += DEL;
ch = UNSIGN (key[i++]);
}
ch0 += (ch >> 1);
data[j] = '<';
data[++j] = '0' + ch0 / 100;
data[++j] = '0' + (ch0 % 100) / 10;
data[++j] = '0' + ch0 % 10;
data[++j] = '>';
} else
data[j] = ch0;
if (data[j++] == '"')
data[j++] = '"';
if (ch & 01) {
if (typ)
data[j++] = '"';
data[j++] = ',';
k = 1;
}
}
data[j--] = 0;
data[j] = ')';
if (j == 0)
data[0] = 0;
while (j >= 0) {
if ((ch = data[--j]) < SPC || ch >= DEL)
break;
}
if (j < 0)
printf ("[%d][%d] %s ", length, koffs, data);
else
printf ("[%d][%d] <illegal subscipt>", length, koffs);
/*----------------------*/
}
if (type == DATA) {
length = UNSIGN (block[i++]);
k = 0;
if ((i + length) > offset)
break;
while (length-- > 0) {
ch = UNSIGN (block[i++]);
if ((ch >= SPC) && (ch < DEL))
data[k++] = ch;
else {
data[k++] = '<';
if ((ch >= NUL) && (ch < SPC)) {
ch = ch * 3;
data[k++] = ASCII[ch++];
data[k++] = ASCII[ch++];
if ((data[k++] = ASCII[ch++]) == SPC)
k--;
} else if (ch == DEL) {
data[k++] = 'D';
data[k++] = 'E';
data[k++] = 'L';
} else {
if (ch > 99) {
data[k++] = '0' + (ch / 100);
ch = ch % 100;
}
if (ch > 9) {
data[k++] = '0' + (ch / 10);
ch = ch % 10;
}
data[k++] = '0' + ch;
}
data[k++] = '>';
}
}
data[k] = 0;
printf ("= %s", data);
} else {
pointer = UNSIGN (block[i]) * 65536 +
UNSIGN (block[i + 1]) * 256 +
UNSIGN (block[i + 2]);
i += PLEN;
printf ("-> %ld", pointer);
}
}
if (i != offset)
printf ("\012\015wrong offset %d vs. %d\012\015", offset, i);
goto again;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>