From: federico@heinz.in-berlin.de (Federico Heinz)
Subject: Structured output to from the WS to an App --- does it work outside a wrap?
Organization: Federico Heinz Consulting
Date: Sat, 25 Jul 1992 00:47:08 GMT

This one's for DPS Client Libary hackers:

I'm trying to asynchronously get results back from the WS using the  
printobject operator. To do so, I arrange my data in an array on the top of  
the stack and invoke, say '0 printobject'. Unfortunately, the Client Library  
seems to think it has monopolic access to printobject, and raises the error  
dps_err_resultTagCheck. No problem, says me, since there's still arg1 and  
arg2 there, which are supposed to contain a pointer to the rejected binary  
object sequence and its length, respectively, so all I have to do is call my  
code from within the error handler, ignore the error-that-is-not, and I'm  
set.

Even more unfortunately, the binary object sequence arrives at the error  
handler in a rather crippled form. It seems the Client Library wipes away  
everything but the top-level object from the sequence. I'm enclosing a very  
short program that sends its standard input to the WS.  If you compile and  
invoke it to send the (enclosed) file test.ps, it should print the ASCII  
representation of an array of two strings, followed by the binary object  
sequence representation of the same array (in hex). The result, however, is  
disappointing:

federico@louis 41> BinObjTest < test.ps
====
WS says:
[(hi there) (how's business)]
====
====
WS complains:
Got 50-byte binary object sequence:
80 01 00 32 09 00 00 02 
00 00 00 08 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 
====

The binary sequence is wrong. Its length is OK (4 bytes header, 8 bytes root  
object, 2*8 bytes for the string objects + 22 chars for the strings = 50  
bytes), but the contents are correct only up to byte #12. I would have  
expected the following:

80 01 00 32 09 00 00 02 
00 00 00 08 05 00 00 08 
00 00 00 18 05 00 00 0e 
00 00 00 20 68 69 20 74 
68 65 72 65 68 6f 77 27
73 20 62 75 73 69 6e 65
73 73

What happened to the rest of my data? Is there no way to send structured data  
to the app besides through the use of wraps? Please take into account that I  
can't use wraps to get this data, because it is produced asynchronously.

Wondering again

	Federico


----- Here it comes ----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#       BinObjTest
# This archive created: Sat Jul 25 02:44:45 1992
export PATH; PATH=/bin:$PATH
if test ! -d 'BinObjTest'
then
        mkdir 'BinObjTest'
fi
cd 'BinObjTest'
if test -f 'test.ps'
then
        echo shar: will not over-write existing file "'test.ps'"
else
cat << \SHAR_EOF > 'test.ps'
%!

% Put two strings in an array
(hi there) (how's business) 2 array astore

% Now the array is at the top of the stack. Show it, so we can be sure
pstack flush

% Now send the array as a binary object sequence to the app
15 printobject flush
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
        echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
CFLAGS        = -O -g -Wall

DESTDIR           = .

HDRS          = 

LIBS          = -lNeXT_s

LINKER            = cc

OBJS      = BinObjTest.o 

SRCS          = BinObjTest.c

all:            BinObjTest

BinObjTest:             $(OBJS)
                                $(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o  
BinObjTest

clean:;                 rm *.o 

BinObjTest.o:           BinObjTest.c

SHAR_EOF
fi # end of overwriting check
if test -f 'BinObjTest.c'
then
        echo shar: will not over-write existing file "'BinObjTest.c'"
else
cat << \SHAR_EOF > 'BinObjTest.c'
#import <sys/types.h>
#import <sys/stat.h>
#import <dpsclient/dpsclient.h>
#import <libc.h>
#import <mach.h>
#import <mach_error.h>
#import <objc/error.h>
#import <cthreads.h>
#import <stdio.h>


DPSContext context;


/*
  Write text from the WS to stdout
*/

static mutex_t libc_mutex;              /* just so we won't bother the C  
library */

static void textCallBack(DPSContext pctx, char *text,
                                                          unsigned long  
length)
{
        mutex_lock(libc_mutex);
        fprintf(stderr, "====\nWS says:\n");
        write(fileno(stderr), text, length);
        write(fileno(stderr), "====\n", 5L);
        mutex_unlock(libc_mutex);
}


static void errorCallBack(DPSContext ctxt,
                                                  DPSErrorCode errorCode,
                                                  long unsigned int arg1, 
                                                  long unsigned int arg2)
{
        int i;
        unsigned char *p;

        mutex_lock(libc_mutex);
        fprintf(stderr, "====\nWS complains:\n");
        switch (errorCode)
        {
          case dps_err_ps:
                fprintf(stderr, "PostScript error in file to print:\n");
                DPSPrintError(stderr, (DPSBinObjSeq)(arg1));;
                break;
          case dps_err_nameTooLong:
                fprintf(stderr, "Name too long: %s.\n", (char *)arg1);
                break;
          case dps_err_resultTagCheck:
                fprintf(stderr, "Got %d-byte binary object sequence:",
                                (int)arg2);
                for (i = 0, p = (unsigned char *)arg1;
                         i < (int)arg2;
                         i++, p++)
                {
                        if (i % 8 == 0)
                                putc('\n', stderr);
                        fprintf(stderr, "%0.2x ", *p);
                }
                putc('\n', stderr);
                break;
          case dps_err_resultTypeCheck:
                fprintf(stderr, "Wrong type of result.\n");
                break;
          case dps_err_invalidContext:
                fprintf(stderr, "Context doesn't exist any longer.\n");
                break;
          case dps_err_select:
          case dps_err_read:
          case dps_err_write:
                fprintf(stderr, "Communications error: %d.\n", arg1);
                break;
          case dps_err_connectionClosed:
                fprintf(stderr, "Lost connection to window server.\n");
                break;
          case dps_err_invalidFD:
                fprintf(stderr, "Invalid file descriptor: %d.\n", arg1);
                break;
          case dps_err_invalidTE:
                fprintf(stderr, "Invalid timed entry: %d.\n", arg1);
                break;
          case dps_err_invalidPort:
                fprintf(stderr, "Invalid mach port: %d.\n", arg1);
                break;
          case dps_err_outOfMemory:
                fprintf(stderr, "Out of memory.\n");
                break;
          case dps_err_cantConnect:
                fprintf(stderr, "Cannot connect to window server.\n");
                break;
          default:
                fprintf(stderr, "Unknown DPS error.\n");
        }
        write(fileno(stderr), "====\n", 5L);
        exit(4);
        mutex_unlock(libc_mutex);
}


void main(int argc, char *argv[])
{
        kern_return_t retc;
        struct stat statbuf;
        char *memfile = NULL;

        NX_DURING
        {
                context = DPSCreateContext((void *)NULL, (void *)NULL,
                                                                   textCallBa 
ck, DPSDefaultErrorProc);
        } NX_HANDLER
        {
                if (NXLocalHandler.code != dps_err_cantConnect)
                        NX_RERAISE();
                else
                {
                        fprintf(stderr, "Could not connect to DPS, host  
%s.\n",
                                        (char *)NXLocalHandler.data2);
                        exit(1);
                }
        } NX_ENDHANDLER;
        DPSSetErrorProc(context, errorCallBack);
        DPSSetTextProc(context, textCallBack);
        libc_mutex = mutex_alloc();
        DPSSetContext(context);
        if (   (fstat(fileno(stdin), &statbuf) == 0)
                && (statbuf.st_size != 0)
                && ((retc = map_fd(fileno(stdin), (vm_offset_t)0,
                                                   &(vm_offset_t)memfile,  
TRUE,
                                                   (vm_size_t)statbuf.st_size 
) == KERN_SUCCESS)))
                DPSWriteData(context, memfile, statbuf.st_size);
        DPSFlushContext(context);
        DPSWaitContext(context);
        exit(0);
}
SHAR_EOF
fi # end of overwriting check
cd ..
#       End of shell archive
exit 0



Newsgroups: comp.sys.next.programmer