/* begincopyright
  Copyright (c) 1988 Xerox Corporation. All rights reserved.
  Use and copying of this software and preparation of derivative works based
  upon this software are permitted. Any distribution of this software or
  derivative works must comply with all applicable United States export
  control laws. This software is made available AS IS, and Xerox Corporation
  makes no warranty about the software, its performance or its conformity to
  any specification. Any person obtaining a copy of this software is requested
  to send their name and post office or electronic mail address to:
    PCR Coordinator
    Xerox PARC
    3333 Coyote Hill Rd.
    Palo Alto, CA 94304
  endcopyright */

/*
 * CedarCirioNubProcs.c
 *
 * A collection of procs to examine Cedar Typecodes
 *
 * Demers, March 3, 1992 5:09:57 pm PST
 * Horton, March 5, 1992 4:50:30 pm PST
 * Horton, March 9, 1992 1:02:13 pm PST
 */

#define CCNP←DEBUG 0
#define DYNAMIC←C←LOOKUP 0


/* #include "xr/CirioNubProtocol.h" */
#include "xr/CirioNubMarshall.h"
#include "CedarCirioNubProcs.h"
/* #include "xr/CirioNubEnvironment.h" */
#include "xr/CirioNubInstall.h"

#if DYNAMIC←C←LOOKUP
#   include "xr/IncrementalLoad.h"
#endif

#if CCNP←DEBUG
#   include "xr/ThreadsMsg.h" /* for XR←ConsoleMsg debug msgs */
#endif

/*
 * The following two utilities are stolen directly from Interp.c ...
 *   call from thread only.
 */

#if DYNAMIC←C←LOOKUP
int
CedarCirioNubLookupCProc(name, valp)
    char *name;
    unsigned *valp;
{
    XR←ILSymEntry ilse;
    char *altText;

    ilse = XR←ILGetMatchingSymEntryByName(
            NIL, name, TRUE, WANT←ALL←TYPES, IGNORE←INTERNAL, 0 );
    if( ilse == NIL ) {
        ilse = XR←ILGetMatchingSymEntryByName(
                NIL, name, TRUE, WANT←ALL←TYPES, IGNORE←NONE, 0 );
    }
    if( (ilse == NIL) && (name[0] != '←') ) {
        altText = (char *)XR←malloc(2+strlen(name));
        altText[0] = '←'; (void)strcpy(&(altText[1]), name);
        ilse = XR←ILGetMatchingSymEntryByName(
                NIL, altText, TRUE, WANT←ALL←TYPES, IGNORE←INTERNAL, 0 );
        if( ilse == NIL ) {
            ilse = XR←ILGetMatchingSymEntryByName(
                NIL, altText, TRUE, WANT←ALL←TYPES, IGNORE←NONE, 0 );
        }
    }
    if( ilse == NIL ) {
        return (-1);
    }
    *valp = ((unsigned)(ilse->ilse←value));
    return 0;
}
#endif


int
CedarCirioNubLookupCedarProc(interfaceName, procName, procp)
    char *interfaceName;
    char *procName;
    XR←MesaProc *procp;
{
    static XR←MesaProc ((*procFromNamedInterface)()) = NIL;
    int ans;
    char *tailP, *dotP;
    XR←MesaProc cedarProcValue;

#   if CCNP←DEBUG
        XR←ConsoleMsg("CirioNubBinding to %s %s ... ", interfaceName, procName);
#   endif
    if( (interfaceName == NIL) || (procName == NIL) ) return (-1);
#   if DYNAMIC←C←LOOKUP
        if( procFromNamedInterface == NIL ) {
            ans = CedarCirioNubLookupCProc( "XR←ProcFromNamedInterface",
                    &procFromNamedInterface );
            if( ans < 0 ) return ans;
        }
#   else
        {
            extern XR←MesaProc XR←ProcFromNamedInterface();
            procFromNamedInterface = XR←ProcFromNamedInterface;
        }
#   endif
    cedarProcValue = (*procFromNamedInterface)(interfaceName, procName, NIL, 0);
#   if CCNP←DEBUG
        XR←ConsoleMsg("result 0x%x ", cedarProcValue);
        if( cedarProcValue ) XR←ConsoleMsg( "(0x%x 0x%x)",
                cedarProcValue->mp←proc, cedarProcValue->mp←x );
        XR←ConsoleMsg("\n");
#   endif
    if( cedarProcValue == NIL ) {
        return(-1);
    }
    (*procp) = cedarProcValue;
    return 0;
}

/*
 * Binding to MesaLoadState ...
 *
 *   This initialization must be called from a thread before the debug nub
 *     starts running in its slave IOP.
 */

static XR←MesaProc mpGetTypestring = NIL;
static XR←MesaProc mpGetTypecode = NIL;
static XR←MesaProc mpGetConcreteTypecode = NIL;

static void
CedarCirioNubBindToLoadStateProcs()
{
    (void)CedarCirioNubLookupCedarProc(
                "MesaLoadStateBackdoor", "UnmonitoredTypeStringFromType",
                &mpGetTypestring );
    (void)CedarCirioNubLookupCedarProc(
                "MesaLoadStateBackdoor", "UnmonitoredFindTypeFromTypeString",
                &mpGetTypecode );
    (void)CedarCirioNubLookupCedarProc(
                "MesaLoadState", "ConcreteTypeFromAbstractType",
                &mpGetConcreteTypecode );
}



/*
 * Exported Cirio Nub Procs ...
 */

#define MESA←STRING←MAXLEN	4000

typedef struct MesaStringRep {
    unsigned short ms←len;
    unsigned short ms←maxLen;
    char ms←data[MESA←STRING←MAXLEN];
} * MesaString;


CirioNubRetCode
CedarCirioNubServeGetTypestring(argc, args)
    int argc;
    unsigned *args;
{
    XR←MesaProc mp = mpGetTypestring;
    int ans;
    CirioNubRetCode rc;
    struct CirioNubCedarTypeCodeRep tc;
    MesaString ms;

#   if CCNP←DEBUG
        XR←ConsoleMsg("CirioNub GetTypestring argc %d\n", argc);
#   endif
    if( argc != 1 ) return( cnrc←badArgs );
    tc.typeCode = (unsigned long)(args[0]);
    
    if( mp == NIL ) return cnrc←noProc;
    ms = (MesaString) ((*(mp->mp←proc))(tc.typeCode, mp));
    if( ms == NIL ) {
#       if CCNP←DEBUG
            XR←ConsoleMsg("GetTypestring fails ms == NIL\n");
#       endif
        return cnrc←badArgs; /* ??? */
    }
#   if CCNP←DEBUG
        XR←ConsoleMsg("GetTypestring res len %d\n", ms->ms←len);
#   endif
    if( (rc = CirioNubPutBlock8(ms->ms←data, ms->ms←len)) != cnrc←ok )
        return rc;
    return cnrc←ok;
}


CirioNubRetCode
CedarCirioNubServeGetTypecode(argc, args)
    int argc;
    unsigned *args;
{
    int ans, len;
    CirioNubRetCode rc;
    XR←MesaProc mp = mpGetTypecode;
    struct {
        long fnd; 
        struct CirioNubCedarTypeCodeRep tc;
    } resultRec;
    struct MesaStringRep ms;

#   if CCNP←DEBUG
        XR←ConsoleMsg("CirioNub GetTypecode argc %d ", argc);
        if( argc >= 1 ) XR←ConsoleMsg("len %d", (int)(args[0]));
        XR←ConsoleMsg("\n");
#   endif

    if( argc != 2 ) return cnrc←badArgs;
    len = (int)(args[0]);
    if( len > MESA←STRING←MAXLEN ) return cnrc←badArgs;
    ms.ms←len = len;
    ms.ms←maxLen = MESA←STRING←MAXLEN;
    bcopy( (char *)(args[1]), ms.ms←data, len);

    if( mp == NIL ) return cnrc←noProc;
    (*(mp->mp←proc))(&resultRec, &ms, mp);
#   if CCNP←DEBUG
        XR←ConsoleMsg("CirioNub GetTypecode res %d 0x%x\n",
                resultRec.fnd, resultRec.tc.typeCode );
#   endif
    if( (rc = CirioNubPutCard32(resultRec.fnd)) != cnrc←ok ) return rc;
    if( (rc = CirioNubPutCard32(resultRec.tc.typeCode)) != cnrc←ok ) return rc;
    return cnrc←ok;
}



CirioNubRetCode
CedarCirioNubServeGetConcreteTypecode(argc, args)
    int argc;
    unsigned *args;
{
    XR←MesaProc mp = mpGetConcreteTypecode;
    int ans;
    CirioNubRetCode rc;
    struct CirioNubCedarTypeCodeRep abs;
    struct CirioNubCedarTypeCodeRep conc;

#   if CCNP←DEBUG
        XR←ConsoleMsg("CirioNub GetConcrete argc %d ", argc);
        if( argc >= 1 ) XR←ConsoleMsg("arg 0x%x", args[0]);
        XR←ConsoleMsg("\n");
#   endif
    if( argc != 1 ) return cnrc←badArgs;
    abs.typeCode = (unsigned long)(args[0]);

    if( mp == NIL ) return cnrc←noProc;
    conc.typeCode = (*(mp->mp←proc))(abs.typeCode, mp);
#   if CCNP←DEBUG
        XR←ConsoleMsg("GetConcrete res 0x%x\n", conc.typeCode);
#   endif

    if( (rc = CirioNubPutCard32(conc.typeCode)) != cnrc←ok ) return rc;
    return cnrc←ok;
}


static CirioNubRetCode
CedarCirioNubServeNull(argc, args)
    int argc;
    unsigned *args;
{
    unsigned v;
    CirioNubRetCode rc;

    v = ((argc >= 1) ? args[0] : CEDAR←CIRIO←NUB←PROCS←VERSION); 
    if( v < CEDAR←CIRIO←NUB←PROCS←LOW←VERSION ) {
        v = CEDAR←CIRIO←NUB←PROCS←LOW←VERSION;
    } else if( v > CEDAR←CIRIO←NUB←PROCS←VERSION ) {
        v = CEDAR←CIRIO←NUB←PROCS←VERSION;
    }
    if( (rc = CirioNubPutCard32(v)) != cnrc←ok ) return rc;
    return cnrc←ok;
}


int
XR←run←CedarCirioNub()
{
    CirioNubHandle h;

    if( (h = CirioNubGetDefaultHandle(0, 0)) == NIL ) return (-1);

    CedarCirioNubBindToLoadStateProcs();

    (void)CirioNubRegisterCProc(h,
        CedarCirioNubProcID←Null,
        CedarCirioNubServeNull);
    (void)CirioNubRegisterCProc(h,
        CedarCirioNubProcID←GetTypestring,
        CedarCirioNubServeGetTypestring);
    (void)CirioNubRegisterCProc(h,
        CedarCirioNubProcID←GetTypecode,
        CedarCirioNubServeGetTypecode);
    (void)CirioNubRegisterCProc(h,
        CedarCirioNubProcID←GetConcreteTypecode,
        CedarCirioNubServeGetConcreteTypecode);

    return 0;
}