/*
 * OpenComal -- a free Comal implementation
 *
 * This file is part of the OpenComal package.
 * (c) Copyright 1992-2024 Jos Visser <josvisser66@gmail.com>
 *
 * The OpenComal package is covered by the GNU General Public
 * License. See doc/LICENSE for more information.
 */

/* PDCOMAL SYS routines for any OS (default C) */

#include "pdcglob.h"
#include "pdcmisc.h"
#include "pdcext.h"
#include "pdcdef.h"
#include "pdcexec.h"

#ifdef MSDOS
#include "alloc.h"
#endif


PUBLIC void sys_init() {
    ext_init();

    puts("+----------+");
    puts("| WARNING! |");
    puts("+----------+\n");
    puts("This OpenComal binary has not been tailored for any OS, and thus contains");
    puts("a very limited system interface only.\n");
}


PUBLIC void sys_tini() {
    ext_tini();
}


PUBLIC int sys_escape() {
    return 0;
}


PUBLIC void sys_put(int stream, char *buf, long len) {
    ext_put(stream, buf, len);
    fputs(buf, stdout);
}


PUBLIC void sys_page(FILE *f) {
    if (!comal_testing)
        run_error(NIMP_ERR, "PAGE not implemented");
}


PUBLIC void sys_cursor(FILE *f, long x, long y) {
    if (!comal_testing)
        run_error(NIMP_ERR, "CURSOR not implemented");
}


PUBLIC void sys_nl(int stream) {
    ext_nl();
    putchar('\n');
}


PUBLIC void sys_screen_readjust() {
}

PUBLIC int sys_yn(int stream, char *s) {
    char buf[80];

    for (;;) {
        char *p;

        my_printf(stream, 0, s);
        fgets(buf, 79, stdin);

        for (p = buf; *p == ' '; p++);

        if (*p == 'n' || *p == 'N')
            return 0;
        else if (*p == 'y' || *p == 'Y')
            return 1;
    }
}

PRIVATE int do_get(int stream, char *line, int maxlen, char *prompt) {
    if (prompt)
        my_printf(stream, 0, prompt);

    if (!fgets(line, maxlen, stdin)) {
        *line = 0;

        if (ferror(stdin))
            perror("Error on input");
        else if (feof(stdin))
            perror("EOF on input");

        clearerr(stdin);
        return 1;
    }

    *(line + strlen(line) - 1) = '\0';
    return 0;
}


PUBLIC int sys_get(int stream, char *line, int maxlen, char *prompt) {
    if (ext_get(stream, line, maxlen, prompt))
        return 0;
    else
        return do_get(stream, line, maxlen, prompt);
}


PUBLIC int sys_edit(int stream, char *line, int maxlen, int cursor) {
    int i;

    for (i = 0; line[i]; i++) {
        if (i == cursor)
            putchar('!');

        putchar(line[i]);
    }

    putchar('\n');

    return do_get(stream, line, maxlen, "E ");
}

PUBLIC int sys_system(char *cmd) {
    return system(cmd);
}

PUBLIC void sys_dir(char *pattern) {
    system("ls -l");
}


PUBLIC void sys_setpaged(int n) {}

PUBLIC char *sys_key(long delay) {
    return strdup("");
}

PUBLIC int sys_quit_allowed() {
    return 1;
}

PUBLIC int sys_call_scan(struct id_rec *id, struct exp_list *exproot, char *errtext) {
    int rc = ext_call_scan(id, exproot, errtext);

    if (rc == -1) {
        sprintf(errtext, "PROCedure %s not found", id->id_name);
        return 0;
    }

    return rc;
}

PUBLIC int sys_call(struct id_rec *id, struct exp_list *exproot, int calltype, void **result, enum VAL_TYPE *type) {
    return ext_call(id, exproot, calltype, result, type);
}

PUBLIC void sys_sys_exp(struct exp_list *exproot, void **result, enum VAL_TYPE *type) {
    if (ext_sys_exp(exproot, result, type) == -1)
        run_error(SYS_ERR, "Unknown SYS() command");
}

PUBLIC void sys_syss_exp(struct exp_list *exproot, struct string **result, enum VAL_TYPE *type) {
    if (ext_syss_exp(exproot, result, type) == -1)
        run_error(SYS_ERR, "Unknown SYS$() command");
}

PUBLIC int sys_sys_stat(struct exp_list *exproot) {
    int rc = ext_sys_stat(exproot);

    if (rc == -1)
        run_error(SYS_ERR, "Unknown SYS statement command");

    return rc;
}
