/*
 * PCRCmdGlueImpl.c
 *
 * Exports to PCRCmdGlue.mesa
 *
 * Demers, July 26, 1990 9:05:26 am PDT
 */

#include <xr/BasicTypes.h>
#include <xr/ThreadsMsg.h>
#include <xr/CommandLine.h>
#include <xr/CommandLoop.h>


/*
 * Stuff for executing PCR commands from PCedar commander
 */

/* the following is the same type as clce←msgSink */

typedef XR←MesaProc PCRCmdGlue$PutProc
        /* (char *msg, int nBytes, XR←MesaProc self) */;

char *
PCRCmdGlue$Execute(cmd, putProc)
    char *cmd;
    PCRCmdGlue$PutProc putProc;
{
    char *cmdCopy;
    XR←CLHandle clh;
    struct XR←CLCallEnvRep clce;
    int verbosity = XR←VERBOSITY←NORMAL;
    int ans;

    if( putProc == NIL ) putProc = XR←stdOutCLMsgSink;
    cmdCopy = (char *) XR←malloc(1+strlen(cmd));
    (void) strcpy(cmdCopy, cmd);
    clh = XR←CLCreateHandleFromString(cmdCopy);
    (void) bzero( &clce, (sizeof clce) );
    clce.clce←h = clh;
    clce.clce←pH = XR←globalCLProcsHandle;
    clce.clce←msgSink = putProc;
    clce.clce←msgVerbosityP = &verbosity;
    if( ans = XR←setjmp(&clce.clce←jmpBuf) != 0 ) {
        char *errMsg = (char *) XR←malloc(64);
        XR←SPrintF(errMsg, "Command failed (unwound %d)\n", ans);
        return errMsg;
    }
    ans = XR←CLApply( &clce, NIL, NIL );
    if( ans < 0 ) {
        char *errMsg = (char *) XR←malloc(64);
        XR←SPrintF(errMsg, "Command failed (%d)\n", ans);
        return errMsg;
    }
    return NIL;  
}

/*
 * Stuff for registering PCedar Commander commands with PCR
 */
 
typedef XR←MesaProc
PCRCmdGlue$CommandLineProc /* (
    char * cmdline,
    PCRCmdGlue$PutProc putProc, 
    XR←Pointer data,
    XR←MesaProc self)
    RETURNS XR←Pointer result
*/;

typedef struct DataForProcRegisteredWithPCRRep {
    XR←MesaProc dfp←proc;
    XR←Pointer dfp←data;
    char *dfp←replacementName;
} *DataForProcRegisteredWithPCR;

/* FOLLOWING SHOULD BE EXPORTED IN COMMANDLINE.H */

static char *
ReconstructCmdLine(head, argc, argv)
    char *head;
    int argc;
    char **argv;
{
    int i, len, totalLen;
    char *result;

    if( head == NIL ) head = "";

    totalLen = 1+strlen(head);
    for( i = 0; i < argc; i++ ) totalLen += (1+strlen(argv[i]));
    if( totalLen == 0 ) return ("");
    result = (char *)XR←malloc(totalLen);

    totalLen = 0;
    i = 0;
    for(;;) {
        len = strlen(argv[i]);
        (void)bcopy(argv[i], &(result[totalLen]), len);
        totalLen += len;
        if( (++i) >= argc ) break;
        result[totalLen] = ' ';
        totalLen += 1;
    }
    result[totalLen] = 0;
    return result;
}


static
XR←CLPROC(PCedarCmdCLProc)
{
    XR←MesaProc innerProc, msgSink;
    DataForProcRegisteredWithPCR dfp;
    char *cmdLine;
    XR←Pointer result;

    if( argc <= 0 ) return (-1);
    dfp = (DataForProcRegisteredWithPCR)(self->mp←x);
    cmdLine = ReconstructCmdLine(dfp->dfp←replacementName, argc-1, argv+1);
    innerProc = dfp->dfp←proc;
    result = (*(innerProc->mp←proc))(
            cmdLine,
            clce->clce←msgSink,
            dfp->dfp←data,
            innerProc
    );
    return 1; /* success */
}


int
PCRCmdGlue$RegisterWithPCRCommandLoop(proc, data,
        pcrName, replacementName, helpMsg)
    XR←MesaProc proc; /* (cmdline, data, self) -> out */
    XR←Pointer data;
    char *pcrName;
    char *replacementName;
    char *helpMsg;
{
    DataForProcRegisteredWithPCR dfp;
    XR←MesaProc realRegisteredProc;

    dfp = (DataForProcRegisteredWithPCR) XR←malloc(sizeof *dfp);
    dfp->dfp←proc = proc;
    dfp->dfp←data = data;
    dfp->dfp←replacementName = (char *) XR←malloc(1+strlen(replacementName));
    strcpy(dfp->dfp←replacementName, replacementName);
    realRegisteredProc = XR←MakeMesaProc(PCedarCmdCLProc, dfp);
    (void) XR←CLRegisterProc(
        XR←globalCLProcsHandle,
        pcrName, FALSE,
        helpMsg,
        realRegisteredProc,
        TRUE
    );
    return 0;
}