Appendix B.1 contains a demonstration program, DEMOPGM, which uses the functions in the variable and parameter manipulation package.
Appendix B.2 contains a demonstration program to show use of dynamic q_ functions.
Appendix B.3 contains a demonstration program for an ASYNC-PROCESS.
/* * demopgm - this program will demonstrate the use of the * functions in the variable and parameter manipulation package. * * * The PDF for this program is: * * process * * parm DATE type=INTEGER count=1:3 default=(1, 11, 18) + * valid=(1:31) * parm COST type=REAL count=1:3 default=(12.5, 4.3, 36.9) * parm NAME type=(STRING, 24) count=1:3 + * default=(GASOLINE, FRAME, GROCERY) * * end-proc * */ #include "taeconf.inp" #include "parblk.inc" #include <stdio> FUNCTION main() { struct PARBLK vblock; CODE status; TEXT file [FSPECSIZ+1]; FILE *fp, *z_init(); /* structs for UNIX file output */ struct VARIABLE *p_find(); struct VARIABLE *date, *cost, *name; TAEINT vdate[] = 5; TAEFLOAT vcost[] = 16.75; TEXT *vname[] = "MAGTAPE"; /* initialize for write to standard output and receive V-block from TM */ fp = z_init(&vblock, P_ABORT); /* get variables from V-block: */ date = p_find (&vblock, "DATE"); cost = p_find (&vblock, "COST"); name = p_find (&vblock, "NAME"); /* Check counts of each parameter: */ fprintf (fp, "\nC demo is running.\n"); if ((*date).v_count != 1) fprintf (fp, "DATE may have only one value.\n"); if ((*cost).v count != 1) fprintf (fp, "COST may have only one value.\n"); if ((*name).v_count != 1) fprintf (fp, "NAME may have only one value.\n"); /* display the values: fprintf (fp, "\n\t%s\tpurchased on : March %u\tfor: $%6.2f", SVAL(*name,O), IVAL(*date,O), RVAL(*cost,O)); /* do some dynamic parameters */ q_init (&vblock, P_BYTES, P ABORT); q_dynp (&vblock, "", M_FULLPDF); /* tutor on original PDF */ p_inim (&vblock, sizeof(vblock), P_ABORT); /* receive the V-block from TM */ /* get variables from V-block */ date = p_find (&vblock, "DATE"); cost = p_find (&vblock, "COST"); name = p_find (&vblock, "NAME"); /* Check counts of each parameter: */ if ((*date).v count != 1) fprintf (fp, "DATE may have only one value.\n"); if ((*cost).v count != 1) fprintf (fp, "COST may have only one value.\n"); if ((*name).v_count != 1) fprintf (fp, "NAME may have only one value.\n"); /* display the values: */ fprintf(fp, "\n\t%s\tpurchased on : March %u\tfor : $%6.2f SVAL(*name,O), IVAL(*date,0), RVAL(*cost,O)); /* reconstruct the V-block: */ q_intg(&vblock, "DATE", 1, vdate, P_UPDATE); q_real(&vblock, "COST", 1, vcost, P_UPDATE); q_string(&vblock, "NAME", 1, vname, P UPDATE); /* write V-block out on disk: */ q_wrtb("demoblk.sav", 1, &vblock); /* read V-block from disk */ /* set mode to continue after failure*/ p_rdb("demoblk.sav", 1, &vblock, sizeof(vblock), P_CONT); /* get variables from V-block */ date = p_find (&vblock, "DATE"); cost = p_find (&vblock, "COST"); name = p_find (&vblock, "NAME"); /* Check counts of each parameter */ if ((*date).v_count != 1) fprintf (fp, "DATE may have only one value.\n"); if ((*cost).v_count != 1) fprintf (fp, "COST may have only one value.\n"); if ((*name).v count != 1) fprintf (fp, "NAME may have only one value.\n"); /* display the values */ fprintf(fp, "\n\t%s\tpurchased on : March %u\tfor : $%6.2f", SVAL(*name,0), IVAL(*date,O), RVAL(*cost,O)); /* set mode in V-block to abort */ vblock.mode = P_ABORT; /* exit with success */ z_exit(1, "demo-success"); return; }
/* Example program to show use of dynamic q functions. * This program initializes a PARBLK structure, then * adds variables to it. Using the new functions, it * sets valids and minimum and maximum counts for * those variables. The PARELK is then saved to disk * in a PAR file. * The result of running this program is the file * EXAMQ.PAR. * */ #include <stdio.h>: #include "taeconf.inp" #include "parblk.inc" #include "terminc.inc" FUNCTION main( ) { struct PARELK parblk; FILE *taeout, *z_init(); struct PARBLK p; FUNINT dummy; /* Initialize TAE and get parblk (not used here) */ taeout = z_init( &parblk, P_ABORT ); /* Initialize PARBLK structure. */ q_init( &p, P_BYTES, P_ABORT ); /* Add the variables A, B and S to the PARBLK. */ /* Use the new q_ functions to set valids and count. */ /* Define arrays for declaring integer variable */ /* with characteristics: */ /* NAME=A TYPE=INTEGER COUNT=O: 4 + /* INITIAL(2,4,13) VALID=(1:l0, 20:30) */ TEXT *iname = "A"; FUNINT imincount = 0, imaxcount = 4; TAEINT ivalues[] = { 2, 4, 13 }; FUNINT nivalues = 3; TAEINT ilow[] = { 1, 20 }; TAEINT ihigh[] = ( 10, 30 ); FUNINT nivalid = 2; /* Add variable A to the PARBLK. */ q_intg( &p, iname, nivalues, ivalues, P_ADD ); q_validintg (&p, iname, nivalid, ilow, ihigh ); q_min( &p, iname, imincount ); q_max( &p, iname, imaxcount ); /* Define arrays for declaring real variable */ /* with characteristics: */ /* NAME=B TYPE=REAL COUNT=1 + */ INITIAL=2.71 VALID=(0.1:1O.1, 20.5:30.0) */ TEXT *rname = "B"; FUNINT rmincount = 1, rmaxcount = 1; TAEFLOAT rvalues[] = { 2.71 }; FUNINT nrvalues = 1; TAEINT rlow[] = { 0.1, 20.5 }; TAEINT rhigh[] = { 10.1, 30.0 }; FUNINT nrvalid = 2; /* Add variable B to the PARBLK. q_real( &p, rname, nrvalues, rvalues, P_ADD ); q_validreal( &p, rname, nrvalid, rlow, rhigh ); q_min( &p, rname, rmincount ); q_max &p, rname, rmaxcount ); /* Define arrays for declaring string variable */ /* with characteristics: */ /* NAME=S TYPE=(STRING,5) COUNT=1:4 + */ /* INITIAL=("F", "T") VALID=("F", "T", "Y", "N") */ TEXT *sname = "S" FUNINT smincount = 1, smaxcount = 4; TEXT *svalues[] = { "F", "T" }; FUNINT nsvalues = 2; TEXT *svalids[] = { "F", "T", "Y", "N" }; FUNINT nsvalid = 4; /* Add variable S to the PARBLK. */ q_string( &p sname, nsvalues, svalues, P_ADD ); q_validstr( &p sname, nsvalid, svalids ); q_min( &p sname, smincount); q_max( &p sname, smaxcount); /* Write the PARBLK structure to disk (PAR file). */ qwrtb( "EXAMQ.PAR", dummy, &p ); /* Terminate the program. */ z_exit( 1, "Normal termination." ); }B.3 SIMPLE C SERVER
/* Demonstration program for ASYNC-PROCESS * * This is a simple server that receives an integer TCL variable * named "I", adds 1 to the value, and returns the value to * the requesting job. */ #include "TAECONF" /* TAE standard defs */ #include "PARELK" /* VBLOCK definitions */ #include "COMMINC" /* PATH struct definition*/ #include <stdio> /* UNIX-like standard I/O*/ static FILE *sysout = NULL; static COUNT get_string(); static TAEINT get_integer(); static CODE send_parblk(); struct VARIABLE *p_find(); VOID terminate(); CODE emit(); #define TERM 0xl000 #define STATUS 0xl00l main () { struct PATH in_path; /* input path control block */ struct VARIABLE *v; struct PARBLK in_parblk, out_parblk; /* VBLOCKs */ CODE code; COUNT i, l, parblk_size; TEXT *s; TEXT sender_job[STRINGSIZ+1], This_job [STRINGSIZ+1], Parent_job [STRINGSIZ+1]; TEXT errmsg[STRINGSIZ+1]; COUNT mb_size; /* size of mailbox to create*/ FILE *z_init (); COUNT messages = 0; /* number processed */ TAEINT ivalue, ivv[1]; /* integer value vector */ sysout = z_init (&in_parblk, P_CONT); /* get initial parameters */ if (sysout == NULL) terminate (in_parblk.hostcode, "z_init failure"); emit (0, "alive"); get_string (&in_parblk, "CHILD", this job); get_string (&in_parblk, "PARENT", parent job); fprintf (sysout, "Job '%s' under parent '%s'.\n", this_job, parent_job); mb_size = get integer (&in_parblk, "MB_SIZE"); code = c_crepath (&in_path, mb_size, this_job, TMPMBX); if (code != SUCCESS) { fprintf (sysout, "Cannot create input mailbox. %s\n", in_path.errmsg); terminate (in_path.host_code, "c_crepath error"); } q_init (&out_parblk, sizeof(out_parblk), P_CONT); send_parblk (&out_parblk, this_job, parent_job); /* announce ready */ messages = 0; while (FOREVER) { parblk size = mb_size; code = c_getmsg (&in_path, (GENPTR)&in_parblk, &parblk size); makeabs (&in_parblk.symtab, in_parblk.pool); /* make ptrs absolute */ in_parblk.mode = P_CONT; /* continue on errors */ get_string(&in_parblk, " JOB", sender job); q_init (&out_parblk, P_BYTES, P_CONT); ivalue = get_integer (&in_parblk, "I"); /* get TCL variable */ ivalue++; ivv[0] = ivalue; q_intg (&out_parblk, "I", I, ivv, P_ADD); /* put I in parblk */ send_parblk (&out_parblk, this_job, sender_job); messages++; emit (messages, "running"); /* announce new status */ } } FUNCTION static TAEINT get_integer (parblk, name) struct PARBLK *parblk; /* in: VBLOCK */ TEXT name []; /* in: name of variable */ { struct VARIABLE *v; v = p_find (parblk, name); if (v == NULL) { fprintf (sysout, "Cannot find variable '%s'.", name); terminate (-1, "No variable."); } return (IVAL(*v,0)); } FUNCTION static COUNT get_string (parblk, name, output) struct PARBLK *parblk; /* in: VBLOCK */ TEXT name[]; /* in: name of variable */ TEXT output[]; /* out: string value */ { struct VARIABLE *v; v = p_find (parblk, name); if (v == NULL) { fprintf (sysout, "Cannot find variable '%s'.", name); terminate (-1, "No variable."); } return (s_copy (SVAL(*v,O), output)); /* return string length */ } FUNCTION static CODE send_parblk (parblk, this_job, target_job) struct PARBLK *parblk; /* in: parblk to send */ TEXT this_job[]; /* in: name of current job */ TEXT target job[]; /* in: name of job to send it to */ { IMPORT GENPTR r_top(); /* current top of allocated area */ TEXT *valvec [1]; /* string value vector for _JOB */ TEXT errmsg[STRINGSIZ+1]; CODE code; valvec[O] = this_job; q_string (parblk, "JOB", 1, valvec, P_ADD); /* tell target who we are */ (*parblk).blksiz = r_top ((*parblk).pool) - (GENPTR)parblk; makerel (&(*parblk).symtab, (*parblk).pool);. /* make ptrs relative */ code = c_pmwcd (target_job, (GENPTR)parblk, (*parblk).blksiz, errmsg); if (code != SUCCESS) fprintf (sysout, "Cannot send to '%s'. %s.\n", target job, errmsg); return (code); . } /* emit. Emit status to parent. This is process analogy of * the TCL EMIT command. * * Currently, under UNIX, there * appears to be a bug whereby back-to-back emits * causes one or both of the emits to be lost. */ #include "ASYNCINC" FUNCTION CODE emit (sfi, skey) FUNINT sfi; /* in: $SFI to report */ TEXT skey[]; /* in: SSKEY to report */ { struct MON_MSG msg; CODE code; msg.type = MO_STATUS; msg.m_sfi = sfi; s_bcopy (skey, msg.m_skey, sizeof(msg.m_skey) - 1); code = c_snpa ((GENPTR)&msg, sizeof (msg)); return (code); } FUNCTION VOID terminate (sfi, skey) FUNINT sfi; /* in: final $SFI status */ TEXT skey[]; /* in: final $SKEY string */ { struct MON_MSG msg; #ifndef UNIX /* avoid back-to-back messages */ emit (sfi, skey); /* emit final status */ #endif msg.type = MO_TERM; /* tell parent we're terminating */ c_snpa ((GENPTR)&msg, sizeof(msg)); exit (1); }