/*****************************************************************************
 * FILE: sysdep.c							     *
 *									     *
 * DESC:								     *
 *	- system functions for 16bit compilers				     *
 *									     *
 * Copyright (C) 1993,1994						     *
 *	Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld		     *
 *	email: rainer@mathematik.uni-bielefeld.de			     *
 *									     *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DPMI.H"
#include "RMLIB.H"
#include "PROCESS.H"
#include "LOADPRG.H"
#include "RSX.H"
#include "FPU.H"
#include "COPY32.H"
#include "SYSDEP.H"

DWORD copro_struct;		/* address of soft-387 struct */
UINT emu_sel = 0;		/* emu data-sel */
DWORD emu_esp;			/* emu esp entry */
POINTER16_32 emu_entry; 	/* entry address emu (for init) */

static char cline[260];
static char *argvec[50];

void save_emu_state(NEWPROCESS * proc)
{
    cpy32_16(emu_sel, copro_struct, &(proc->npx), sizeof(union i387_union));
}

void load_emu_state(NEWPROCESS * proc)
{
    cpy16_32(emu_sel, copro_struct, &(proc->npx), sizeof(union i387_union));
}

/* load emu & init */
static int init_emu387(char *filename)
{
    if (load_protected_program(filename, npz))
	return -1;

    puts("load rsx387");

    /* init some emu vars for long-jmp, emu data selector access */
    emu_sel = npz->data32sel;
    emu_esp = npz->stackp32;
    emu_entry.off = npz->entry;
    emu_entry.sel = npz->code32sel;

    LockLinRegion(npz->memaddress, npz->membytes);

    /* emu_init call emulator to install exception handler */
    copro_struct = emu_init();
    /* return the 387-register struct, need for switching prgs */

    return 0;
}

int install_rsx387()
{
    static char rsx387_default[] = "\\RSX\\FPU-EMU\\RSX387";
    char *emu_name;

    emu_name = getenv("RSX387");
    if (emu_name == NULL) {
	if (rm_access(rsx387_default, 0)) {
	    puts("Can't find RSX387");
	    return -1;
	} else
	    emu_name = rsx387_default;
    }
    if (init_emu387(emu_name) == -1) {
	printf("Can't load emu: %s\n", emu_name);
	return -1;
    }
    return 0;
}

/* convert PSP to command line */
void get_emxl_psp(unsigned emxl_psp)
{
    int z, env_seg;
    char far *cmdl;

    /* get envoronment segment from PSP */
    env_seg = *(int far *) ((DWORD) emxl_psp << 16 | 0x2c);

    /* build far pointer to environment */
    cmdl = (char far *) ((DWORD) env_seg << 16);

    /* skip env-strings ; last has two 0-bytes */
    for (; cmdl++;)
	if (*cmdl == '\0' && *(cmdl + 1) == '\0')
	    break;

    cmdl += 4;
    /* copy arg0 */
    for (z = 0; *cmdl != '\0'; cmdl++, z++)
	cline[z] = *cmdl;
    cline[z++] = ' ';

    /* build cmdline far pointer from PSP */
    cmdl = (char far *) ((DWORD) emxl_psp << 16 | 0x81);

    /* copy arg1,arg2,... */
    for ( ; z < sizeof(cline) ; z++) {
	cline[z] = *cmdl;
	if (cline[z] == 13)
	    break;
	cmdl++;
    }
    cline[z] = '\0';
}

/* make command string to argv */
void build_emx_args(int *argn, char ***argvp)
{
    int argc, src, dst, bs, quote;
    char *q;

    argc = 0;
    dst = src = 0;
    while (cline[src] == ' ' || cline[src] == '\t' || cline[src] == '\n')
	++src;
    do {
	if (cline[src] == 0)
	    q = NULL;
	else {
	    q = cline + dst;
	    bs = 0;
	    quote = 0;
	    for (;;) {
		if (cline[src] == '"') {
		    while (bs >= 2) {
			cline[dst++] = '\\';
			bs -= 2;
		    }
		    if (bs & 1)
			cline[dst++] = '"';
		    else
			quote = !quote;
		    bs = 0;
		} else if (cline[src] == '\\')
		    ++bs;
		else {
		    while (bs != 0) {
			cline[dst++] = '\\';
			--bs;
		    }
		    if (cline[src] == 0 ||
		    ((cline[src] == ' ' || cline[src] == '\t') && !quote))
			break;
		    cline[dst++] = cline[src];
		}
		++src;
	    }
	    while (cline[src] == ' ' || cline[src] == '\t'
		   || cline[src] == '\n')
		++src;
	    cline[dst++] = 0;
	}
	argvec[argc++] = q;
    } while (q != NULL);

    *argvp = (char **) &(argvec[0]);
    *argn = argc - 1;
}

#define MK_LP(seg,o) (void far *) (DWORD) ((((DWORD)(seg)) << 16) | (WORD)(o))

void build_dj_args(int *argc, char ***argv)
{
    int narg, i;
    char **args = *argv;
    int segm, off;
    int far *old_argv;
    char far *old_argi;

    sscanf(args[2], "%x", &narg);
    sscanf(args[3], "%x", &segm);
    sscanf(args[4], "%x", &off);
    old_argv = (int far *) MK_LP(segm, off);
    argvec[0] = cline;
    for (i = 0; i < narg; i++) {
	old_argi = (char far *) MK_LP(segm, (old_argv[i]));
	_fstrcpy((char far *) (argvec[i]), old_argi);
	argvec[i + 1] = argvec[i] + (strlen(argvec[i]) + 1);
    }
    argvec[narg] = 0;

    *argv = (char **) &(argvec[0]);
    *argc = narg;
}

void set_stdout(void)
{
    setbuf(stdout,NULL);
    setbuf(stderr,NULL);
}

void flush_all_buffers(void)
{
    fflush(stdin);
    fflush(stdout);
    fflush(stderr);
}
