
#include "debug.h"

#define KBSTAT 0177560
#define KBDATA 0177562
#define PRSTAT 0177564
#define PRDATA 0177566

char line[MAXLEN];
int indx;
int error;
int run;
int oldkbstat;
unsigned lcend,lc=0;
int symbtab_len=0;
FILE *fp;

main(argc,argv)
int argc;
char *argv[];
{
    extern unsigned regs[];

    char *s,c;
    int start,len,oldkbdata,oldprstat;
    register i;

    initmem();
    if (argc != 2)
    {
        printf("usage: debug filename\n");
        exit(1);
    }
    s=rindex(argv[1],'.');
    if (s != NULL)
    {
        while (*s && *s!='\\')
            s++;
        if (!*s)
        {
            printf("debug: suffix is added by program\n");
            exit(1);
        }
    }
    strcat(argv[1],".pdp");
    fp=fopen(argv[1],"r");
    if (fp == NULL)
    {
        printf("debug: can't open %s\n",argv[1]);
        exit(1);
    }    
    len=fgetoct();
    start=fgetoct();
    lc=0;
    while (lc < len)
        if ((c=getc(fp)) == '#')
            lc+=fgetoct();
        else
        {
            ungetc(c,fp);
            putword(lc,fgetoct());
            lc+=2;
        }
    regs[7]=start;
    lc=0;
    while (1)
    {
        error=FALSE;
        run=FALSE;
        Cconout('>');
        getstr(line);
        convline();
        indx=0;
        if (line[indx]=='q')
            exit(1);
        if (line[indx]=='r')
        {
            if (line[++indx]==':')
            {
                ++indx;
                i=0;
                while (1)
                {
                    skip();
                    if (!line[indx])
                        break;
                    if (line[indx]=='~')
                    {
                        indx++;
                        i++;
                    }
                    else if (!isoct())
                        break;
                    else
                        regs[i++]=getoct();
                    if (i>=8)
                        break;
                }
            }
            else
                showregs();
            goto loopend;
        }
        else if (line[indx]=='p')
            if (line[++indx]==':')
            {
                indx++;
                skip();
                if (!isoct())
                    goto loopend;
                else
                    regs[7]=getoct();
            }
            else
                regs[7]=start;                    
        else if (line[indx]=='s')
            while (1)
            {
                if (regs[7] & 1)
                {
                    printf("odd pc: %06o\n",regs[7]);
                    goto loopend;
                }
                showregs();
                lc=lcend=regs[7];
                disasm();
                c=Crawcin();
                if (c == '\033')
                    goto loopend;
                switch (exec())
                {
                    case 1:
                        printf("unknown instruction\n");
                        goto loopend;
                    case 2:
                        printf("program halt\n");
                        goto loopend;
                    case 3:
                        printf("trying to jump into a register\n");
                        goto loopend;
                    case 4:
                        printf("odd adress error\n");
                        goto loopend;
                    case 6:
                        printf("odd register in 'div'-instruction\n");
                        goto loopend;
                }
            }
        else if (line[indx]=='g')
        {
            putword(PRSTAT,0x80);
            putword(KBSTAT,0);
            putword(PRDATA,0);
            putword(KBDATA,0);
            printf("\033E\n");
            while (1)
            {
                if (regs[7] & 1)
                {
                    printf("odd pc: %06o\n",regs[7]);
                    goto loopend;
                }
                if (Cconis())
                {
                    c=Crawcin();
                    if (c=='\033')
                    {
                        printf("\nprogram stopped by user\n");
                        goto loopend;
                    }
                    if (!(word(KBSTAT) & 0x80))
                    {
                        putword(KBDATA,c & 0x00ff);
                        putword(KBSTAT,0x80);
                    }
                }
                oldkbdata=word(KBDATA);
                oldkbstat=word(KBSTAT);
                if (word(PRDATA) && (word(PRSTAT) & 0x80))
                {
                    Cconout((char) word(PRDATA));
                    putword(PRSTAT,0);
                    putword(PRDATA,0);
                }
                else
                    putword(PRSTAT,0x80);
                oldprstat=word(PRSTAT);
                run=TRUE;
                switch (exec())
                {
                    case 1:
                        printf("\nunknown instruction\n");
                        goto loopend;
                    case 2:
                        printf("\nprogram halt\n");
                        goto loopend;
                    case 3:
                        printf("\ntrying to jump into a register\n");
                        goto loopend;
                    case 4:
                        printf("\nodd adress error\n");
                        goto loopend;
                    case 6:
                        printf("\nodd register in 'div'-instruction\n");
                        goto loopend;
                }    
                run=FALSE;
                putword(KBDATA,oldkbdata);
                putword(KBSTAT,oldkbstat);
                putword(PRSTAT,oldprstat);                        
            }
        }
        else
        {
            if (isoct())
                lc=getoct();
            if (line[indx]=='.')
            {
                indx++;
                if (!isoct())
                {
                    printf("number after '.' expected\n");
                    goto loopend;
                }
                else
                    lcend=getoct();
            }
            else
                lcend=lc;
            switch (line[indx])
            {
                case '\0':
                    dump();
                    break;
                case 'c':
                    chrdmp();
                    break;
                case 'l':
                    disasm();
                    break;
                case ':':
                    if (lc != lcend)
                    {
                        printf("don't use '.' together with ':'!!!\n");
                        goto loopend;
                    }
                    if (lc & 1)
                    {
                        printf("odd address: %06o\n",lc);
                        goto loopend;
                    }
                    indx++;
                    while (1)
                    {
                        skip();
                        if (!line[indx])
                            break;
                        if (!isoct())
                        {
                            printf("number expected\n");
                            goto loopend;
                        }
                        putword(lc,getoct());
                        lc+=2;
                    }
                    break;
                default:
                    printf("unrecognizable syntax\n");
                    goto loopend;
            }
        }
    loopend:
        run=FALSE;
    }
}

fgetstr(s)
register char *s;
{
    fgets(s,10,fp);
    while (*s != '\n')
        s++;
    *s='\0';
}

getoct()
{
    register unsigned val=0;
    
    while (line[indx]>='0' && line[indx]<='7')
        val=val*8+line[indx++]-'0';
    return val;
}

fgetoct()
{
    fgetstr(line);
    indx=0;
    return getoct();    
}

convline()
{
    register i=0;
    
    while (line[i])
        line[i++]=tolower(line[i]);
}

isoct()
{
    return (line[indx]>='0' && line[indx]<='7');
}

skip()
{
    while (line[indx]==' ')
        indx++;
}
