/* This file includes all the routines to handle all operations
 * that will differ from machine to machine and which will
 * differ depending on the operating mode of the machine. Thus,
 * if the parser, etc are operating as a front end on a distant
 * network machine, these routines would involve network interface
 * work.
 */

/* This file is for ddt on 4.2 BSD Unix.
 *
 * Written by David A. Bridgham 1985
 */

#ifndef	DDTCAT	/* Don't reget hdrs if catting when all routines internal */
#include	<pdefs.h>
#include	<ptypes.h>
#include	"mdep.h"
#include	"ddt.h"

ext int proc_id;
ext int errno;
ext char d_crlf[];
#endif

#include <signal.h>
#include <sys/wait.h>

/* Machine dependant mode commands */

intern	retcd	md_mdepmd(dsp)
reg	ddtst	*dsp;
{
	if (d_numval(dsp) != 2)
		return(ERR);

	printf("\tUnimplemented %o %o", d_getval(dsp), d_getval(dsp));
}


/* Checks to see if current memory op is legal in this mode.
 */

intern	retcd	md_okfetch(dsp, mode)

{	return(OK);
}


intern	retcd	md_okstore(dsp, mode)

{	return(OK);
}


/* Does fetch or store, doing machine dependant mapping if necessary.
 * For remote debugger, would access memory over network.
 */

intern	retcd	md_fetch(dsp, mode, sz, src, dst)
ddtst	*dsp;
twrd	mode;
unsw	sz;
word	src;
word	dst;

{
    int data;

    data = ptrace(1, proc_id, src, 0);
    if (data == -1 && errno) {
	perror("Error reading from child");
	return(0);
    }

    if (sz == sizeof(byte)) {
	*((byte *) dst) = (byte) data;
	return(sz);
    };

    if (sz == sizeof(swrd)) {
	*((swrd *) dst) = (swrd) data;
	return(sz);
    };

    if (sz == sizeof(lwrd)) {
	*((lwrd *) dst) = (lwrd) data;
	return(sz);
    };

    ddtbug("bad sz in mov");
    return(0);
}


intern	retcd	md_store(dsp, mode, sz, src, dst)
ddtst	*dsp;
twrd	mode;
unsw	sz;
word	src;
word	dst;

{
    int data;

    if (sz == sizeof(lwrd)) {
	data = *(lwrd *)src;
    }
    else {
	data = ptrace(1, proc_id, dst, 0);
	if (data == -1 && errno) {
	    perror("Error reading from child");
	    return (0);
	}
	if (sz == sizeof(swrd)) {
	    data &= ~(int)((swrd)-1);
	    data |= *(swrd *)src;
	}
	else if (sz == sizeof(byte)) {
	    data &= ~(int)((byte)-1);
	    data |= *(byte *)src;
	}
	else
	  return (0);
    }
    if (ptrace(4, proc_id, dst, data) == -1) {
	perror("Error writing to child");
	return (0);
    }
    return (sz);
}


/* Stop or start processor from running normal code. On machine where
 * debugger running locally, just ups PS. For remote machine, would
 * cause it to drop into command listen mode. Note returns PS machine
 * stopped with; reset when restarted. This is used by the ^B command
 * of the run-time debugger, which causes a trace trap as the simplest
 * way of getting into the hard-core debugger.
 */

intern	PSTYP	md_stop()

{	reg	PSTYP	tmp;
/*
	tmp = ddtgps();
	ddtpps(PSNOINT);
	return(tmp);	only needed for run time ddt */
}


intern	md_start(ops)
PSTYP	ops;

{ /*	ddtpps(ops);	only needed for run time ddt */
}

ddtbug(msg)
char	*msg;
{
	puts("FATAL ERR! ");
	puts(msg);
	done();
}

ddterr()
{
	puts("Internal DDT error, restarting\n");
	DDT();
}

ddtexec()
{
/*	ddtbug("called 'ddtexec'"); */
}

#define SSIZ 128
#define ASIZ 128
/* Read a command line and execute the program. */
md_run_cmd(dsp)
ddtst *dsp;
{
    reg	int	p;
    char	c;
    char	buf[SSIZ];
    reg char	*bufp;
    char	*sbufp;
    char	*argv[ASIZ];
    reg char	**argp;
    struct wait status;

    buf[0] = ':';
    p = 1;
    for (;;) {
	c = d_getc(dsp);
	if (c == '\177') {
	    if (p <= 0) {
		d_ungetc(dsp, '');
		return;
	    }
	    (*dsp->d_puts)(" ");
	    p--;
	    continue;
	}
	else if (c == '\n' || c == '\r') {
	    dsp->d_puts(d_crlf);
	    break;
	}
	else if (c == '')
	  while (p > 1) {
	      (*dsp->d_puts)(" ");
	      p--;
	  }
	else if (c == '') {
	    d_err(dsp);
	    return;
	}
	else {
	    if (p < SSIZ) {
		d_prc(dsp, c);
		buf[p++] = c;
	    }
	    continue;
	}
    }
    buf[p] = '\0';

    sbufp = bufp = &buf[1];
    argp = argv;
    while (*bufp != '\0') {
	while (*bufp != ' ' && *bufp != '\0')
	  bufp++;
	if (*bufp != '\0')
	  *bufp++ = '\0';
	*argp++ = sbufp;
	while (*bufp == ' ') bufp++;
	sbufp = bufp;
    }
    *argp = 0;

    run_child(argv, &status, 0);
    dsp->d_putc('*');
}
