File:  [Coherent Logic Development] / freem / src / gfix.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Mar 9 19:14:25 2025 UTC (3 weeks, 2 days ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, v0-62-1, v0-62-0, HEAD
First phase of REUSE compliance and header reformat

/*
 *   $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>