home *** CD-ROM | disk | FTP | other *** search
- /************************************************************
- * *
- * Minimal Print server Client Demo for IPC *
- * *
- * Pete Goodeve 88:7:25 *
- * *
- * [This module has only been compiled under Lattice; *
- * it will need some modification for Manx/Aztec] *
- * *
- * *
- * This is a simple test module for the "Print Format" *
- * server. When you type the return key, it generates *
- * a message with a set of items in various formats, *
- * and sends it to the print server. (For test purposes *
- * the items are fixed.) If you simply type a return, *
- * the formatted string generated from the message is *
- * displayed in the print server's own window; if you *
- * type an 'F' before the return, a file handle to this *
- * Client program's console window is passed in the *
- * message and the string will be output to this instead; *
- * if you type an 'M' before the return, the string will *
- * be passed back in the reply message and again shown *
- * in the Client's console window. *
- * *
- * Typing 'Q' will send a 'QUIT' message to the server *
- * instead of a print request. To exit the client *
- * program type an 'end-of-file' (cntrl-'\'); the *
- * print server is currently programmed to exit also *
- * when there are no running clients left. *
- * *
- * It is a simple "synchronous" client: when it sends a *
- * message it waits for the reply before continuing *
- * (unlike others that may continue with other activities *
- * while the server is processing a message). The main *
- * loop is simple: *
- * *
- * Wait for keyboard command *
- * Send message *
- * Wait for reply *
- * Display string from reply if supplied *
- * Loop to wait for keyboard again. *
- * *
- * *
- ************************************************************/
-
- #include "IPC.h"
- #include "exec/memory.h"
-
- #define LINESZ 120
- #define SHOWREAL 1
-
- /*
- * Define the ID codes recognized by the print format server
- *
- * (MAKE_ID is defined in IPC.h)
- */
-
- /* Message IDs: */
- #define CNVA MAKE_ID('C','N','V','A')
- /* CoNVert to Ascii */
- #define QUIT MAKE_ID('Q','U','I','T')
-
- /* Item IDs: */
- #define RETS MAKE_ID('R','E','T','S')
- /* RETurn String */
-
- #define FILH MAKE_ID('F','I','L','H')
- /* FILe Handle */
-
-
- #define PATS MAKE_ID('P','A','T','S')
- /* PATtern String */
-
- #define PAT1 MAKE_ID('P','A','T','1')
- /* PATtern -- 1 item */
-
- #define LINE MAKE_ID('L','I','N','E')
- /* indicates a complete line of text -- omitting newline */
-
- #define TEXT MAKE_ID('T','E','X','T')
- /* Text block -- may include newlines */
-
- #define STRG MAKE_ID('S','T','R','G')
- /* general non-specific ASCII STRinG */
-
- /* The above three categories are treated identically by Pserver
- -- they may have distinct meanings to other servers */
-
- #define CHAR MAKE_ID('C','H','A','R')
- /* A single character in L.S byte of ii_Ptr */
-
- #define INTG MAKE_ID('I','N','T','G')
- /* A 32-bit INTeGer in ii_Ptr */
-
- #define REAL MAKE_ID('R','E','A','L')
- /* A 32-bit floating point value in ii_Ptr (care in conversion!) */
-
-
- /*******************
- rather than the above if you prefer, with Lattice 4.0 you can simply
- use 4-character constants as in the following (compile with the -cm option):
-
- #define CNVA 'CNVA'
- #define QUIT 'QUIT'
-
- #define RETS 'RETS'
- #define FILH 'FILH'
-
- #define PATS 'PATS'
- #define PAT1 'PAT1'
- #define LINE 'LINE'
- #define TEXT 'TEXT'
- #define STRG 'STRG'
- #define CHAR 'CHAR'
- #define INTG 'INTG'
- #define REAL 'REAL'
- *********************/
-
-
- struct IPCPort *port=NULL; /* will point to server port */
- struct MsgPort *rport=NULL; /* where we get our replies */
- struct IPCMessage *imsg=NULL; /* this one message is used repeatedly */
-
- struct MsgPort * CreatePort(char *, int);
- ULONG Output();
-
- void Cleanup();
- void outputstr(char *);
-
-
- /***************************
- *
- * Main program entry point:
- *
- * -- Note that to save overhead we use '_main'; you should also compile
- * (under Lattice) using the -v switch, to suppress stack checking and
- * the associated baggage.
- *
- * We avoid using any C level I/O also -- just AmigaDOS calls, so we
- * dont need <stdio.h>.
- */
-
- void _main()
- {
- struct IPCItem *item, *item0; /* pointers to access message items */
-
- int count=0; /* dummy value used to stuff into message */
- float realcount=0.0; /* -- ditto */
-
- char tbuf[22]; /* keyboard input dumped in here */
-
-
- /* First we set up our ports: */
-
- port = GetIPCPort("Print_Format");
- if (!port) _exit(20);
-
- rport = CreatePort(NULL,0);
- if (!rport) {Cleanup(); _exit(21);}
-
- /* ... then make a message block */
- imsg = CreateIPCMsg(20,0,rport); /* large enough for playing with... */
- if (!imsg) {Cleanup(); _exit(22);}
-
- item0 = &imsg->ipc_Items[0]; /* a convenient permanent reference */
-
-
- /* The main program loop:
- * -- continues until told to quit by end-of-file (ctrl-\)
- */
- while (1) {
- item = item0; /* reset item pointer */
- imsg->ipc_Id = CNVA; /* only message ID needed (except QUIT) */
- /*
- * Initially we assume that the first item will be a slot
- * in which the server will return the formatted string.
- * This will be overwritten if another option is chosen
- */
- item->ii_Id = RETS;
- item->ii_Ptr = NULL; /* The server will provide the data block */
- item->ii_Size = 0;
- item->ii_Flags = imsg->ipc_Flags = 0;
-
- /* get keyboard input (terminated by return): */
- /* E-O-F returns a length of zero, causing break from loop */
- if (Read(Input(), tbuf, 21) <= 0) break;
-
- /*
- * decode first character of input to decide action
- * (sorry about the crudity... but it suffices)
- */
- switch(*tbuf) {
- case 'Q': /* Send a QUIT message */
- case 'q':
- case '.': imsg->ipc_Id = QUIT; /* all items are ignored */
- break;
-
- case 'm': /* Request string in reply Message */
- case 'M':
- case '?': item++; /* leave default RETS in place */
- item->ii_Id = STRG; /* Add in a string item to
- distinguish displayed line */
- item->ii_Ptr = (void *)("Returned: ");
- item++;
- break;
-
- case 'F': /* Pass File handle to this console */
- case 'f':
- case '^': item->ii_Id = FILH; /* overwrites RETS */
- item++->ii_Ptr = (void *)Output(); /* the file handle */
- break;
-
- default: /* anything else just overwrites RETS with output
- items, so string appears on Pserver window */
- break;
- }
-
- /*
- * The rest of the setup code simply stuffs a few values of
- * different types into successive items -- rearrange to your
- * own satisfaction...
- * NOTE that we haven't bothered to put the strings into public
- * memory, contrary to the suggestions of the IPC standard
- * [For shame, Peter!] but this is really only a restriction
- * that needs to be observed for general messages that may have
- * a destination outside the ken of the sender (or for a future
- * machine that has process-private memory). This isn't relevant
- * to such a simple test program, so we've simplified things.
- * At the same time, the ii_Size field for the string items is
- * set to ZERO, indicating that the "data block" is Read-Only
- * as far as the server is concerned.
- */
- item->ii_Id = STRG; /* A short string to start out with */
- item->ii_Ptr = (void *)("Test line...");
- item++;
- item->ii_Id = PAT1; /* then a format specifier for a value */
- item->ii_Ptr = (void *)(" #%3d");
- item++;
- item->ii_Id = INTG; /* the integer value to be formatted */
- item->ii_Ptr = (void *)(count++); /* (just a sequential count...) */
- item++;
- item->ii_Id = STRG; /* another string... */
- item->ii_Ptr = (void *)("... value=");
- item++;
- item->ii_Id = REAL; /* A float value in default format */
- /* note the messy conversion to get it into the ii_Ptr field */
- *(float *) &item->ii_Ptr = (realcount += 1.234);
- item++;
- item->ii_Id = CHAR; /* and a newline character to end the section */
- item->ii_Ptr = (void *)('\n');
- item++;
- item->ii_Id = PATS; /* Multi item format specifier */
- item->ii_Ptr = (void *)("formatted line #%2d %s\n");
- item++;
- item->ii_Id = INTG;
- item->ii_Ptr = (void *)(count++);
- item++;
- item->ii_Id = STRG;
- item->ii_Ptr = (void *)((count & 3) ? "..." : "tick...");
- /* no more items allowed after PATS is satisfied */
-
- /* set actual ItemCount into message: */
- imsg->ipc_ItemCount = item - item0 + 1;
-
- /* Send the message (if possible) */
- if (!PutIPCMsg(port, imsg)) {
- outputstr("No server!\n");
- continue; /* don't wait for a reply that won't come! */
- }
- /* Wait at the reply port: */
- WaitPort(rport);
- GetMsg(rport); /* we assume we know what's there! */
- if (imsg->ipc_Flags & IPC_NOTKNOWN)
- outputstr("Server barfed\n");
- /*
- * If we asked for a return string, display it in our
- * window, then dispose of the block of memory passed to us
- * by the server:
- */
- if (item0->ii_Id == RETS) {
- Write(Output(), item0->ii_Ptr, strlen(item0->ii_Ptr));
- /* note that we DON'T use the ii_Size value above!
- There is no guarantee that it is exactly the size of
- the string. */
- FreeMem(item0->ii_Ptr, item0->ii_Size);
- }
- }
- /*** end of main loop ***/
-
- Cleanup();
- }
-
-
- void Cleanup()
- {
- if (port) DropIPCPort(port);
- if (rport) DeletePort(rport);
- if (imsg) DeleteIPCMsg(imsg);
- }
-
-
- void outputstr(str) char *str;
- {
- Write(Output(), str, strlen(str));
- }
-
-