W~ DTLIB.BCKn DTLIB.BCKSBACKUP USER$0:[CHAREST.DTLIB.SRC]*.* SYS$KITS:[DECTALK_GUIDE]DTLIB.BCK/SAVE/LOG/VER SIMM x{ΑV5.1 _VOX:: G _$1$DJA4: V5.0 ~ *[CHAREST.DTLIB.SRC]DECTLK.H;69+,N .6/_x 4E65-M 0123KPWO75697 wL89ɊʑG_xHJj/*0 * D e f i n i t i o n s a n d G l o b a l s *< * This file contains symbolic definitions of the structures7 * and characters used by DECtalk application programs,4 * including all DECtalk escape sequence parameters. *? * Note: on RSX-11M, your program must first #include  *//*E * Select a Unix "flavor" (bizarre code as Decus C lacks "defined()") */ #ifdef unix#ifndef BSD_42#ifndef UNIX_V#define UNIX_V#endif#endif#endif#ifdef DOCUMENTATION*title dectlk.h DECtalk Library Header File#index DECtalk library header filesynopsis .s.nf #include "dectlk.h" .s.f description0 This file is included in the compilation of all3 modules that use the DECtalk applications library., It defines common ASCII characters, DECtalk- escape sequence parameters, library globals," and the DECTALK buffer structure. configuration/ You can edit dectlk.h to enable debugging code* by defining the DT_DEBUG flag as follows: #define DT_DEBUG 13 This changes the primary input and output routines6 so that they become capable of logging all characters, transmitted to and from the DECtalk device.globals5 The library provides two global flags which are used as follows: .lm +161 .s.i-16;dt__abort########This is set non-zero by/ an intercepted CTRL/C trap (if you have called5 dt_trap()). When set, no I/O will be performed, and6 library subroutines will exit as quickly as possible.2 .s.i-16;dt__debug########This may be set non-zero6 by an applications program to enable debug printouts.3 Note that the library must have been compiled with6 DT_DEBUG defined in order to compile in the necessary print calls. .s.lm -16 error codes2 The library may return the following error codes./ These are all less than zero, and consequently+ cannot be part of the ASCII character set: .s.lm +16.nj2 .i-16;DT__ERROR########An operating-system error.2 .i-16;DT__TIMEOUT######An input operation did not2 complete in the required (operating-system) time.. .i-16;IO__ERROR########An error exit code for3 the exit() library routine. The value is selected4 as appropriate for the particular operating system. .s.lm-16.j.tp 6Routines implemented as macros2 Certain frequently routines may be implemented as/ macros (if macro expansion is supported by the/ particular C compiler). These are as follows: .s.lm +20.nj5 .i-20;dt__iskey(dt)########TRUE if data is currently( stored in the keypad type-ahead buffer.4 .i-20;dt__isvalid(c)#######TRUE if the character is/ a valid keypad character. Note: evaluation of0 the argument must not have side-effects. I.e.,% you must not write dt_isvalid(*p++).3 .i-20;dt__ptest(dt,r3)#####Phone test, TRUE if the current reply is R2_PHONE, R3.3 .i-20;dt__offhook(dt)######Phone test, TRUE if the* current reply is R2_PHONE, R3_PH_OFFHOOK.3 .i-20;dt__onhook(dt)#######Phone test, TRUE if the) current reply is R2_PHONE, R3_PH_ONHOOK.3 .i-20;dt__istimeout(dt)####Phone test, TRUE if the* current reply is R2_PHONE, R3_PH_TIMEOUT.1 .i-20;dt__phone(dt,p3,p4)##Send a phone message.2 .i-20;dt__eol(dt)##########Send "end of line" and force output to DECtalk.: .i-20;dt__version(dt)######Return DECtalk version number. .s.lm -20;.j.tp 6general definitions% The following variables are defined: .s.lm +16.nj$ .i-16;EOS#############End of string- .i-16;FALSE###########For TRUE/FALSE testing- .i-16;TRUE############For TRUE/FALSE testing .s.lm-16.j.tp 6 ascii characters1 The following C0 control characters are defined: .s.nf. .br;##NUL###STX###ETX###BEL####BS####VT###LS1. .br;##LS0###XON##XOFF###CAN###SUB###ESC###DEL .s.f1 The following C1 control characters are defined: .s.nf. .br;##SS2###SS3###DCS#OLDID###CSI####ST###OSC .br;###PM###APC##RDEL .s.f. The following DECtalk-specific parameters are also defined. .s.lm +16.nj, .i-16;CSI__DA__PRODUCT##The DECtalk product. identification code for the DECtalk 1 (DTC01)) (Note: dt_version(dt) returns the actual/ product identification code for either a DTC01 or DTC03.5 .i-16;DT__LEVEL1#######Device ID for DTC03, level 1.5 .i-16;DT__LEVEL2#######Device ID for DTC03, level 2.4 .i-16;DCS__F__DECTALK###The DECtalk specific device( control sequence (DCS) final character./ .i-16;P1__DECTALK######All DCT01 DCS sequences. transmit this for their first (P1) parameter.6 .i-16;R1__DECTALK######All DCT01 DCS replies transmit' this for the first R1 reply parameter. .s.lm-16.j> The P2 and P3 parameters select the specific DECtalk command. .s.lm+16.nj, .i-16;P2__PHOTEXT######Speak phonemic text.& .i-16;P2__STOP#########Stop speaking.$ .i-16;P2__SYNC#########Synchronize.. .i-16;P2__SPEAK########Enable/disable speech.# .i-16;P2__INDEX########Index text.* .i-16;P2__IX__REPLY#####Index with reply.2 .i-16;P2__IX__QUERY#####Return last spoken index.- .i-16;P2__DICT#########Load user dictionary.* .i-16;P2__PHONE########Telephone control./ .i-16;P2__MODE#########Synthesis mode control.3 .i-16;P2__LOG##########Local terminal log control./ .i-16;P2__TERMINAL#####Local terminal control., .i-16;P2__MASK#########Keypad mask control. .s.lm-16.j2 The telephone control command takes an additional4 parameter to specify the specific telephone action. .s.lm+16.nj0 .i-16;P3__PH__STATUS####Return a status report., .i-16;P3__PH__ANSWER####Answer on P4 rings.* .i-16;P3__PH__HANGUP####Hangup the phone.2 .i-16;P3__PH__KEYPAD####Enable keypad data entry.3 .i-16;P3__PH__NOKEYPAD##Disable keypad data entry.@ .i-16;P3__PH__STOPPAD###Enable keypad data entry with autostop.1 .i-16;P3__PH__TIMEOUT###Send a timeout report if4 no data entered in P4 seconds if P4 is greater than& zero; disable timeouts if P4 is zero.. .i-16;P3__PH__TONE######Dial out using tones./ .i-16;P3__PH__PULSE#####Dial out using pulses./ .i-16;P3__PH__WINK######Enable wink detection.0 .i-16;P3__PH__NOWINK####Disable wink detection. .s.lm-16.j1 Several P2 commands return messages to the host: .s.lm+16.nj0 .i-16;R2__IX__REPLY#####Reply to P2__IX__REPLY.& R3 contains the last index processed.0 .i-16;R2__IX__QUERY#####Reply to P2__IX__QUERY.& R3 contains the last index processed.- .i-16;R2__DICT#########Reply to P2__DICT. R3+ contains the dictionary entry status code.+ .i-16;R2__PHONE########Reply to P2__PHONE." R3 contains the telephone status. .s.lm-16.j1 The following R3 parameters are returned after a P2_PHONE command. .s.lm+16.nj9 .i-16;R3__PH__ONHOOK####Telephone is hung up (inactive).8 .i-16;R3__PH__OFFHOOK###Telephone is answered (active).3 .i-16;R3__PH__TIMEOUT###No data was entered by the6 telephone user within the required number of seconds.6 .i-16;R3__PH__TOOLONG###A telephone number to dial is too long.< .i-16;R3__PH__WINK######A "wink" was returned (DTC03 only). .s.lm-16.j9 The following R3 parameters are returned after a P2_DICT command: .s.lm+16.nj5 .i-16;R3__DI__LOADED####Dictionary entry was loaded.5 .i-16;R3__DI__NOROOM####The user dictionary is full.: .i-16;R3__DI__TOOLONG###The dictionary entry is too long. .s.lm-16.j7 The following codes are used to control host-requested self test (DECTST): .s.lm+16.nj, .i-16;TEST__POWER######Rerun power up test.5 .i-16;TEST__HDATA######Host data link loopback test./ .i-16;TEST__HCONTROL###Host line control test.- .i-16;TEST__LDATA######Local line data test./ .i-16;TEST__SPEAK######Speak a canned message. .s.lm-16.j8 The following status codes are returned by the extended DSR sequence: .s.lm+16.nj+ .i-16;DSR__OK##########No errors detected.. .i-16;DSR__COMFAIL#####Communication failure.. .i-16;DSR__INBUFOVER###Input buffer overflow.6 .i-16;DSR__DECNVRFAIL##Last restore from non-volatile memory failed.2 .i-16;DSR__PHONEME#####Incorrect phoneme entered.4 .i-16;DSR__PRIVATE#####DECtalk DCS parameter error.5 .i-16;DSR__DECTSTFAIL##Last DECTST self-test failed. .s.lm-16.j2 The following flags configure the P2_LOG command: .s.lm+16.nj( .i-16;LOG__TEXT########Log spoken text./ .i-16;LOG__PHONEME#####Log generated phonemes.3 .i-16;LOG__RAWHOST#####Log all characters received from host without change.3 .i-16;LOG__INHOST######Log all characters received from host in "visible" format.1 .i-16;LOG__OUTHOST#####Log all output to host in visible format.+ .i-16;LOG__ERROR#######Log error messages.6 .i-16;LOG__TRACE#######Log commands in mnemonic form.D .i-16;LOG__HOSTPH######Log phonemes on host line (DECtalk III only) .s.lm-16.j5 The following flags are for the P2_TERMINAL command: .s.lm+16.nj2 .i-16;TERM__HOST#######Send text entered from the local terminal to the host.3 .i-16;TERM__SPEAK######Speak text entered from the local terminal.3 .i-16;TERM__EDITED#####Line-edit text entered from the local terminal.7 .i-16;TERM__HARD#######Use hard-copy edit conventions.+ .i-16;TERM__SETUSPEAK##Speak SETUP dialog.4 .i-16;TERM__FILTER#####Filter escape sequences sent to the local terminal. .s.lm-16.j1 The following flags are for the P2_MODE command: .s.lm+16.nj2 .i-16;MODE__SQUARE#####[ ] bracket phonemic text.2 .i-16;MODE__ASKY#######Use single-letter phonemic alphabet.1 .i-16;MODE__MINUS######Pronounce '-' as "minus".4 .i-16;MODE__EUROPE#####Use European conventions for8 ',' and '.' in numbers (123.456,78). (Only in DECtalks for certain countries.) .s.lm-16.j2 The P2_LOG, P2_TERMINAL, and P2_MODE commands can3 take a fourth parameter that specifies whether the1 bits specified in the P3 parameter are assigned,! set, or cleared in the firmware:e .s.lm+16.nj* .i -16;P4__ASSIGN######Bits are assigned., .i -16;P4__BITSET######Set only these bits.. .i -16;P4__BITCLEAR####Clear only these bits. .s.lm-16.j6 The following flags are for the dt_splice() function. .s.lm+16.nj3 .i -16;SPLICE__SPEAK###DECtalk speaks text if set.4 .i -16;SPLICE__LOG#####Text sent to DECtalk is sent' to the terminal (P2_LOG, LOG_RAWHOST).d2 .i -16;SPLICE__TERM####The terminal may send text! to DECtalk (P2_TERM, TERM_HOST).d .s.lm -16.jEscape sequence data bufferL- All information needed to generate and parser. escape sequences is contained in the SEQUENCE2 data structure. It is configured by the following size constants: .s.lm+16.nj6 .i-16;SEQ__INTMAX######Maximum number of intermediate characters.5 .i-16;SEQ__PARMAX######Maximum number of parameters.a .s.lm-16.j& It contains the following components: .s.lm+16.nj5 .i-16;short#state#####Processing state or introducer  character to send. 3 .i-16;char#final######Final character in sequence. 3 .i-16;char#private####Private introducer characterh or 'X' to indicate an error.n5 .i-16;short#param[]###Private parameters (unsigned);d, param[0] contains the number of parameters./ .i-16;char#inter[]####Intermediate characters;m/ inter[0] contains the number of intermediates.e .s.lm-16.jnDECTALK data buffer definition3 All information needed by the DECtalk applicationso3 library is contained in the DECTALK data structure 7 which is created by dt_open() and freed by dt_close().. It is configured by the following parameters: .s.lm+16.nj0 .i-16;PEND__SIZE#######Maximum number of keypad0 characters that may be typed-ahead. Additional characters are discarded.- .i-16;IN__BUFLEN#######Size of the operating system input buffer.- .i-16;OUT__BUFLEN######Size of the operating system output buffer. .s.lm-16.j4 The data buffer contains the following information: .s.lm+16.nj8 .i-16;DECTALK#*link###Chains together all active units.4 .i-16;short#unit######Operating system I/O channel., .i-16;short#timeout###Current timeout value2 .i-16;short#flag######Speech and dt_splice flags.. .i-15;short#version###DECtalk version number.0 .i-16;short#pend__fc###Bytes in pending buffer.5 .i-16;short#pend__fp###Index to free byte in pending buffer.4 .i-16;short#pend__ep###Index to next byte to return from pending buffer.- .i-16;char#*in__ptr####Input buffer pointer.) .i-16;char#*in__end####Input buffer end.3 .i-16;char#*out_ptr####Output buffer free pointer.. .i-16;SEQUENCE#send###Last DCS sequence sent.3 .i-16;SEQUENCE#reply##Last DECtalk reply received.7 .i-16;SEQUENCE#seq####Look-ahead for string terminator processing.5 .i-16;char#*device####Remember dt_open() device name for debug printouts.) .i-16;char#pend[]#####Type-ahead buffer.% .i-16;char#in_buff[]###Input buffer.& .i-16;char#out_buff[]##Output buffer.9 .i-16;struct#termio#stty__save#Terminal characteristics block (Unix System V).7 .i-16;struct#sgtty#stty__save#Terminal characteristics block (Unix 4.2 BSD).- .i-16;FILE#*fildes####File descriptor (RSX)./ .i-16;struct#iosb#iosb#I/O status block (RSX).2 .i-16;QIOPARM#parm#####QIO parameter block (RSX). (RSX only)./ .i-16;int#pos__xk#######TRUE if POS XK: driver (RSX only). .s.lm-16.j1 The flag entry controls library internal states. .s.lm +16.nj4 .i-16;__FLAG__SPEAK#####Set if DECtalk is speaking.3 .i-16;__FLAG__LOG#######Set if LOG RAWHOST is set.1 .i-16;__FLAG__TERM######Set if TERM HOST is set.= .i-16;__FLAG__EIGHTBIT##Set to read and write eight-bit data and control sequences. .s.lm-16.j: FLAG_SPEAK, FLAG_LOG, and FLAG_TERM should not be changed by application programs.8 FLAG_EIGHTBIT must be set by the application program if9 DECtalk sends and receives C1 control sequences in their8 eight-bit form. Note that the application program must7 ensure that the operating system passes eight-bit data; correctly and DECtalk setup must set HOST FORMAT to EIGHT. Unix Notes/ On Unix System V, the DECtalk terminal line is- forced to 9600 Baud. This may be changed to0 retain the current Baud rate. Also, you should5 be aware that there are numerious subtle differences) between different Unix implementations. Note< Unix and System V are trademarks of AT&T Bell Laboratories.#endif /*; * Define DT_DEBUG to enable debug printouts of transmitted * characters. */#define DT_DEBUG#define FALSE 0#define TRUE 1 #ifndef EOS#define EOS '\0'#endif #ifdef unix #ifdef BSD_42#include #else #ifdef UNIX_V#include #endif#endif#endif/*3 * These error codes may not be in the Ascii range. */#define DT_ERROR (-1)#define DT_TIMEOUT (-2)/* * C0 control characters */"#define NUL 0x00 /* NUL code */&#define STX 0x02 /* Start of text */%#define ETX 0x03 /* End of text */#define BEL 0x07 /* Bell */"#define BS 0x08 /* Backspace */,#define VT 0x0B /* Vertical tab ('\013') */"#define LS1 0x0E /* LS1 (SO) */"#define LS0 0x0F /* LS0 (SI) */#define XON 0x11 /* DC1 */#define XOFF 0x13 /* DC3 */(#define CAN 0x18 /* Cancel */$#define SUB 0x1A /* Substitute */##define NUL 0x00 /* Null code */ #define ESC 0x1B /* Escape */ #define DEL 0x7F /* Delete *//* * C1 control characters */'#define SS2 0x8E /* Single shift 2 */'#define SS3 0x8F /* Single shift 3 *//#define DCS 0x90 /* Device control sequence */!#define OLDID 0x9A /* ESC Z */3#define CSI 0x9B /* Control Sequence Introducer */)#define ST 0x9C /* String terminator */1#define OSC 0x9D /* Operating System sequence */'#define PM 0x9E /* Privacy Message */3#define APC 0x9F /* Application Program Control */.#define RDEL 0xFF /* Delete in right side */<#define CSI_DA_PRODUCT 19 /* DTC01 device id product code */6#define DT_LEVEL1 81 /* DTC03 Level 1 compatibility */)#define DT_LEVEL2 82 /* DTC03 Level 2 *//*/ * Basic definitions for DECtalk device control; * strings. All DECtalk sequences have a first parameter of= * P1_DECTALK. This provides an easy place for future DECtalk- * products to fit into the scheme of things. */.#define DCS_F_DECTALK 'z' /* DECtalk final */+#define P1_DECTALK 0 /* DECtalk param 1 */0#define R1_DECTALK 0 /* DECtalk reply param 1 *//*2 * The second parameter selects the basic command. *//#define P2_PHOTEXT 0 /* Speak phonemic text */(#define P2_STOP 10 /* Stop speaking */'#define P2_SYNC 11 /* Synchronize */4#define P2_SPEAK 12 /* Enable or disable speaking */!#define P2_INDEX 20 /* INDEX */*#define P2_IX_REPLY 21 /* INDEX_REPLY */*#define P2_IX_QUERY 22 /* INDEX_QUERY */-#define P2_DICT 40 /* Dictionary control */(#define P2_PHONE 60 /* Phone control */0#define P2_MODE 80 /* Synthesis mode control */5#define P2_LOG 81 /* LOG information on local tty */3#define P2_TERMINAL 82 /* Local terminal control */.#define P2_MASK 83 /* Keypad mask control *//*/ * Additional parameters for the phone command. */2#define P3_PH_STATUS 0 /* Send a status report */9#define P3_PH_ANSWER 10 /* Answer (P4 has ring number) */&#define P3_PH_HANGUP 11 /* Hangup */*#define P3_PH_KEYPAD 20 /* Raw keypad *//#define P3_PH_NOKEYPAD 21 /* Disable keypad */:#define P3_PH_STOPPAD 22 /* Enable keypad with autostop */7#define P3_PH_TIMEOUT 30 /* Status report on timeout */&#define P3_PH_TONE 40 /* Dial out */'#define P3_PH_PULSE 41 /* Dial out */)#define P3_PH_WINK 50 /* Enable wink */,#define P3_PH_NOWINK 51 /* Disable wink *//*> * The second parameter in a reply specifies the general class * of the reply sequence. */3#define R2_IX_REPLY 31 /* Sent after INDEX_REPLY */3#define R2_IX_QUERY 32 /* Sent after INDEX_QUERY */*#define R2_DICT 50 /* Sent after DICT */1#define R2_PHONE 70 /* Telephone status report *//*A * Additional reply information is passed in the third parameter. */&#define R3_PH_ONHOOK 0 /* Hung up */.#define R3_PH_OFFHOOK 1 /* Phone is lifted */3#define R3_PH_TIMEOUT 2 /* No reply in N seconds */s7#define R3_PH_TOOLONG 3 /* Telephone # text too long */ "#define R3_PH_WINK 4 /* Wink. */4#define R3_PH_NO_TONE 5 /* No dial tone detected. *//#define R3_PH_BUSY 6 /* Busy, also reorder. */s.#define R3_PH_NO_ANSWER 7 /* Call failed. */7#define R3_DI_LOADED 0 /* Dictionary entry loaded ok */E2#define R3_DI_NOROOM 1 /* No room in dictionary */.#define R3_DI_TOOLONG 2 /* String too long *//*5 * Test specification codes for the request self test# * (DECTST) sequence. */10#define TEST_POWER 1 /* Rerun power up tests */7#define TEST_HDATA 2 /* Host line data loopback test */l4#define TEST_HCONTROL 3 /* Host line control test */0#define TEST_LDATA 4 /* Local line data test */1#define TEST_SPEAK 5 /* Speak a canned message */C/*; * Error (and success) codes for the extended DSR sequence.I */E!#define DSR_OK 20 /* All OK */ 3#define DSR_COMMFAIL 22 /* Communication failure */s4#define DSR_INBUFOVER 23 /* Input buffer overflow */3#define DSR_DECNVRFAIL 24 /* Last DECNVR failed */h3#define DSR_PHONEME 25 /* Error in phonemic text */f9#define DSR_PRIVATE 26 /* Error in DECtalk private DCS */X3#define DSR_DECTSTFAIL 27 /* Last DECTST failed */./*. * Local logging flags for the P2_LOG command. */m5#define LOG_TEXT 0x0001 /* Log text that is spoken */.7#define LOG_PHONEME 0x0002 /* Log generated phonemes */ 4#define LOG_RAWHOST 0x0004 /* Log raw host input *//#define LOG_INHOST 0x0008 /* Log host input */i1#define LOG_OUTHOST 0x0010 /* Log host output */e+#define LOG_ERROR 0x0020 /* Log errors */t7#define LOG_TRACE 0x0040 /* Log sequence trace info. */t5#define LOG_HOSTPH 0x0100 /* Log phonemes to host *//*4 * Local terminal flags for the P2_TERMINAL command. */E1#define TERM_HOST 0x0001 /* Send text to host */e:#define TERM_SPEAK 0x0002 /* Speak local terminal input */)#define TERM_EDITED 0x0004 /* Edited */ 9#define TERM_HARD 0x0008 /* Local terminal is hardcopy */y6#define TERM_SETUSPEAK 0x0010 /* Spoken setup mode */=#define TERM_FILTER 0x0020 /* Filter logged esc. sequences */e/*& * Mode flags for the P2_MODE command. *: * Note that MODE_EUROPE is available only in DECtalks for< * certain countries. It is not present in firmware 2.0 for * the USA.b */.:#define MODE_SQUARE 0x0001 /* [ ] are phonemic brackets */1#define MODE_ASKY 0x0002 /* Use ASKY alphabet */ 9#define MODE_MINUS 0x0004 /* "-" is pronounced "minus" */g7#define MODE_EUROPE 0x0008 /* For 123.456,78 numbers */o/*4 * Definitions for P2_LOG, P2_TERMINAL, and P2_MODE: */-4#define P4_ASSIGN 0 /* Assign value to bits */3#define P4_BITSET 1 /* Set only these bits */p6#define P4_BITCLEAR 2 /* Clear only these bits *//*2 * Flags for dt_splice() and ((DECTALK *)dt)->flag */ 4#define SPLICE_SPEAK 0x0001 /* Speak text if set */3#define SPLICE_LOG 0x0002 /* Log rawhost if set */c3#define SPLICE_TERM 0x0004 /* Local host if set */S=#define _FLAG_SPEAK 0x0001 /* Speaking, set by dt_splice() */L;#define _FLAG_LOG 0x0002 /* Log rawhost from dt_splice() */a:#define _FLAG_TERM 0x0004 /* Term host from dt_splice() */>#define _FLAG_EIGHTBIT 0x0008 /* Read eight-bit C1 controls *//*@ * These macros and structure definitions are used by the escape * sequence parser.u */f2#define SEQ_INTMAX 2 /* Max. # of intermediates */1#define SEQ_PARMAX 16 /* Max. # of parameters *//*< * dt_gesc() (get escape sequence) and dt_pesc() (put escape3 * sequence) use this structure for all processing.( */typedef struct {1 short state; /* Processing state or intro */#. char final; /* Final character in seq. */+ char private; /* Private introducer */ #ifdef decus" unsigned param[SEQ_PARMAX+1];#elseb' unsigned short param[SEQ_PARMAX+1];.#endif$ /* Intermediate count, values */ char inter[SEQ_INTMAX+1];S } SEQUENCE;H /*< * The DECTALK structure is used to maintain all information: * needed to process a DECtalk device. It is allocated by: * dt_open(), freed by dt_close() and a required parameter * by essentially all routines.a */ #ifdef rsx/*= * The qio parameter block controls all RSX11-M I/O requests.a */2typedef struct qioparm { /* QIO parameter block */' char *buffer; /* Buffer location */p' int size; /* Bytes to transfer */o# char *p3; /* For ctrl/c ast */( char *table; /* Terminator table */' int unused[2]; /* Not used here */ } QIOPARM;/*@ * The I/O status block receives the status of all I/O requests. */t.typedef struct iosb { /* I/O status block */) char status; /* Operation status */b0 char terminator; /* Input terminator byte */- int count; /* Bytes read from device */a} IOSB;f#endif#ifndef PEND_SIZEf/#define PEND_SIZE 32 /* Pending buffer size */t#endif#ifndef IN_BUFLENa#define IN_BUFLEN 32#endif#ifndef OUT_BUFLEN#define OUT_BUFLEN 128#endif6#if (IN_BUFLEN < 1 || OUT_BUFLEN < 1 || PEND_SIZE < 1)1 << error, mandatory parameters aren't correct >>i#endiftypedef struct DECtalk {8 struct DECtalk *link; /* Chain all units together */$ short unit; /* I/O channel */* short timeout; /* For dt_timeout() */0 short flag; /* Speech and "splice" flags */5 short version; /* Version number set by dtinit */f0 short pend_fc; /* Bytes in pending buffer */2 short pend_fp; /* Pending buffer fill index */3 short pend_ep; /* Pending buffer empty index */f0 char *in_ptr; /* I/O input buffer pointer */. char *in_end; /* -> end of input buffer */5 char *out_ptr; /* -> free spot in output buff. */*- SEQUENCE send; /* Last sequence sent */t. SEQUENCE reply; /* Last sequence read */- SEQUENCE seq; /* Sequence look-ahead */ / char *device; /* DECtalk hardware device */e6 char pend[PEND_SIZE]; /* Type-ahead ring buffer */3 char in_buff[IN_BUFLEN]; /* I/O input buffer */06 char out_buff[OUT_BUFLEN]; /* I/O output buffer */ /*; * The following entries are operating-system specific. */T #ifdef unixi #ifdef BSD_42*2 struct sgttyb stty_save; /* Terminal flags */#elsef #ifdef UNIX_V ; struct termio stty_save; /* Terminal flags (Unix V7) */m#endif#endif#endif #ifdef rsx( FILE *fildes; /* File descriptor */' IOSB iosb; /* I/O status block */d- QIOPARM parm; /* QIO parameter block */p4 short pos_xk; /* Device characteristics word */#endif } DECTALK; o/*; * Certain short routines and common tests are expressed as > * macros. In all instances, 'dd' is a DECtalk I/O descriptor< * as returned by dt_open(). Note that the arguments should * not have "side-effects".  *9 * dt_iskey(dd) TRUE if something in type-ahead buffer. : * dt_isvalid(c) TRUE if argument is a valid keypad key. *< * The following are only useful after executing dt_phone(). *3 * dt_ptest(dd, r3) TRUE if specific phone reply.*: * dt_offhook(dd) TRUE if last DECtalk reply is OFFHOOK.8 * dt_onhook(dd) TRUE if last DECtalk reply is ONHOOK.< * dt_istimeout(dd) TRUE if last DECtalk reply is TIMEOUT. *: * The following simple commands may be written as macros: *- * dt_phone(dd,p3,p4) Send a phone message.n4 * dt_get(dd, sec) Read a character (with timeout). * dt_put(dd, c) Send a character to DECtalk; * dt_eol(dd, c) Send "end of line", flush output buffers *? * If DT_DEBUG is #defined, dt_get() and dt_put() are functionsS> * which may log all characters to the standard output stream. */t#ifndef DT_DEBUG#define dt_get dt_ioget#define dt_put dt_ioput#endif#ifndef nomacarg'#define dt_iskey(dd) (dd->pend_fc != 0)d2#define dt_isvalid(c) (( (c >= '0' && c <= '9') \ || c == '#' || c == '*' \d || (c >= 'A' && c <= 'D')))e3#define dt_ptest(dd,r3) (dt_test(dd, R2_PHONE, r3))a4#define dt_offhook(dd) (dt_ptest(dd, R3_PH_OFFHOOK))2#define dt_onhook(dd) (dt_ptest(dd, R3_PH_ONHOOK))6#define dt_istimeout(dd) (dt_ptest(dd, R3_PH_TIMEOUT))(#define dt_phone(dd,p3,p4) (dt_msg(dd, \" P2_PHONE, p3, p4, R2_PHONE, -1)) #ifdef unix*4#define dt_eol(dd) (dt_put(dd, '\n'), dt_put(dd, 0))#elsea'#define dt_eol(dd) (dt_put(dd, '\r'), \d" dt_put(dd, '\n'), dt_put(dd, 0))#endif#endif #ifdef decus#ifdef DT_DEBUGa/*, * This forces traceback on Decus C systems. */ #define exit errorP*#define IO_ERROR "fatal DECtalk I/O error"#endif#endif#ifndef IO_ERROR #ifdef vms#include #define IO_ERROR SS$_ABORT#elseu#define IO_ERROR 2#endif#endif/*7 * dt_abort may be set by a user program at any time ton9 * stop DECtalk. Typically, it would be set by dt_trap() : * when a (Unix INTERRUPT signal) is typed by the * terminal user.  */t,extern int dt_abort; /* Set TRUE to stop */4extern DECTALK *dt_root; /* Root of device chain */#ifdef DT_DEBUGd-extern int dt_debug; /* TRUE if debug log */ #endif*[CHAREST.DTLIB.SRC]DEMO.C;1+,P ./_x 48t-M 0123KPWO56I'P7'xL89ɊʑG_xHJ #include #include "dectlk.h"main(argc, argv) int argc;char *argv[];{/ register DECTALK *dt; /* Dectalk device *// register int retries; /* Initializations *// register int ncalls; /* Completed calls */ char *dev; extern DECTALK *dt_open(); dev = "TT2:"; if (argc > 1) dev = argv[1]; retries = 0; ncalls = 0; dt_debug = TRUE;# if ((dt = dt_open(dev)) == NULL) { perror(dev); return; }& dt_trap(); /* Catch CTRL/C abort */0 while (dt_init(dt)) { /* One-time setup */* dt_dcs(dt, P2_MODE, MODE_SQUARE, -1);* retries++; /* Count attempts */8 while (dt_answer(dt, 1)) { /* Answer the phone */- if (process(dt)) { /* Do user process */*) ncalls++; /* User ran ok, */)+ retries = 0; /* Clear retry count */v }g* dt_hangup(dt); /* Hangup the phone */) if (dt_abort) /* Check interrupt */U) goto finis; /* Error exit */} } if (dt_abort)% goto finis; /* Error exit */*. if (retries > 2) { /* Got lost? */ printf("Too many retries\n");+ break; } }2 fprintf(stderr, "Couldn't initialize DECtalk\n");2finis: dt_abort = FALSE; /* Restart output */) dt_reset(dt); /* Hangup DECtalk */ * dt_put(dt, 0); /* Force out buffer */) dt_close(dt); /* Close up DECtalk */u}h h process(dt)fregister DECTALK *dt;n{r+ register char c; /* Keypad character */ ) char work[30]; /* For echo message */o# dt_talk(dt, "Welcome to DECtalk");i3 if (!dt_keypad(dt, TRUE)) /* Enable keypad */o. return (FALSE); /* Error occurred */& for (;;) { /* Do forever... */3 c = dt_inkey(dt, 15); /* Key with timeout */ 2 if (!dt_isvalid(c)) /* Check for timeout */! break; /* Exit if so */ ( sprintf(work, "You pressed %c", c); dt_talk(dt, work);t. if (c == '*') { /* Make '*' special */- dt_timeout(dt, 0); /* No timeouts now *//! dt_talk(dt, "Long message...");k } } /*D) * Timeout is normal, others are errors.n */$ return ((c == 'T') ? TRUE : FALSE);}E*[CHAREST.DTLIB.SRC]DTANSW.C;1+,Q ./_x 43-M 0123KPWO56yƩ87 'xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION$title dt_answer Answer the Telephoneindex Answer the telephonesynopsis .s.nf #include  #include "dectlk.h" int dt_answer(dt, nrings)& DECTALK *dt; /* Device descriptor */# int nrings; /* Number of rings */ .s.f description. Hangup the phone (by calling dt_hangup()) and, answer the phone after the specified number of rings.. Return TRUE if successful, FALSE if in error. #endif#include #include "dectlk.h"intdt_answer(dt, nrings)register DECTALK *dt; int nrings;/*) * Hangup the phone and answer on nrings. */{ register int code;0again: if (!dt_hangup(dt)) /* Make sure it's */% return (FALSE); /* on-hook. */, dt_dcs(dt, P2_PHONE, P3_PH_ANSWER, nrings);( while (dt_read(dt, 0), dt_onhook(dt)) { if (dt_abort) return (FALSE); } if (dt_onhook(dt)) goto again;. if (!dt_offhook(dt)) /* Did it answer ok? */ return (FALSE); /*3 * OK, cl;>^~ DTLIB.BCKQ M [CHAREST.DTLIB.SRC]DTANSW.C;13oear timeout flag and type-ahead counters. */ dt->timeout = 0;- dt->pend_fc = dt->pend_fp = dt->pend_ep = 0; return (TRUE);}*[CHAREST.DTLIB.SRC]DTAUTO.C;1+,S ./_x 4C-M 0123KPWO56WI7`'xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATIONCtitle dt_autostop Enable/disable the Telephone Keypad with Autostop9index Enable/disable the Telephone Keypad with autostopsynopsis .s.nf #include  #include "dectlk.h" int dt_autostop(dt, flag)& DECTALK *dt; /* Device descriptor */ int flag; /* Enable code */ .s.f description) If the flag is zero, disable the keypad.) If non-zero, enable it in autostop mode.5 Returns TRUE if successful. If FALSE, the telephone may have been hung up.d1 When enabled in autostop mode, DECtalk will stop 5 speaking when a key is pressed, ignoring any pendinge1 text. Furthermore, it will act as if speech wash/ turned off (as if P2_STOP;0 were transmitted).f, The program must explicitly restart speech. For example:a dt_autostop(dt, TRUE);o for (;;) {g /*& * restart speech and print command. */- dt_dcs(dt, P2_SPEAK, 1, -1); dt_talk("Enter command");  c = dt_inkey(dt, 10);l dt_dcs(dt, P2_SPEAK, 1, -1); /*# * decide what to do and/or exit.e */ ...h }#endif#include #include "dectlk.h""inthdt_autostop(dt, enable) register DECTALK *dt;A int enable; /** * Enable or disable the telephone keypad. */a{ dt_phone(dt,c4 (enable) ? P3_PH_STOPPAD : P3_PH_NOKEYPAD, -1); if (dt_offhook(dt)) return (TRUE);  return (FALSE);}D*[CHAREST.DTLIB.SRC]DTCLOS.C;1+,T ./_x 4BT-M 0123KPWO568c7{'xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION*title dt_close Terminate DECtalk Operation#index Terminate DECtalk Operationsynopsis .s.nf #include  #include "dectlk.h" dt_close(dt)# DECTALK *dt; /* DECtalk device */ .s.f description0 Close the DECtalk channel and free all buffers. No error is returned.#endif#include #include "dectlk.h" #ifdef rsx#include #include #include #include #define QIO_EFN 1r2static QIOPARM noparm; /* QIO parm (all zero) */#endif E dt_close(dt)register DECTALK *dt;i/* * Close the DECtalk channel.i */{o register DECTALK **linkp; #ifdef unixi #ifdef BSD_42 9 stty(dt->unit, &dt->stty_save); /* Restore tty flags */n#else* #ifdef UNIX_V,B ioctl(dt->unit, TCSETA, &dt->stty_save); /* Restore tty flags */#endif#endif close(dt->unit);#endif #ifdef vms sys$dassgn(dt->unit);#endif #ifdef rt11L rs_close(dt->unit);#endif #ifdef rsx6 qiow(IO_DET, dt->unit, QIO_EFN, NULL, NULL, &noparm); fclose(dt->fildes);#endif /*r% * Unlink the device from the chain.G */' for (linkp = &dt_root; *linkp != NULL; linkp = &((*linkp)->link)) { if (*linkp == dt) { *linkp = dt->link; break; } } free(dt->device); free((char *)dt); return (NULL); }t*[CHAREST.DTLIB.SRC]DTCMD.C;1+,V ./_x 43"-M 0123KPWO56J@I7`(xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION,title dt_cmd Send DCS w/o String Terminator&index Send DCS w/o string terminatorsynopsis .s.nf #include  #include "dectlk.h" int dt_cmd(dt, p2, p3)& DECTALK *dt; /* Device descriptor */ int p2; /* P2_... parameter */ int p3; /* P3_... parameter */ .s.f description0 This routine sends a DCS command to the DECtalk. terminal. The string terminator is not sent.2 This is needed to send phonemic text or telephone dial commands.0 The p2 or p3 parameter may be -1 if it is to be ommitted.3 A phonemic text sequence would be sent as follows: .s.nf dt_cmd(dt, p2, p3); dt_talk(dt, "hh'ehlow."); dt_st(dt); .s.f#endif#include #include "dectlk.h"static SEQUENCE command = {2 DCS, DCS_F_DECTALK, 0, { 3, P1_DECTALK, 0, 0 }};dt_cmd(dt, p2, p3).register DECTALK *dt; /* Device descriptor */!int p2; /* P2_command or -1 */!int p3; /* P3_command or -1 *//*+ * Send a DCS command, no string terminator */{ if (p2 == -1) command.param[0] = 1; else { command.param[2] = p2; if (p3 == -1) command.param[0] = 2; else { command.param[0] = 3; command.param[3] = p3; } } dt_pesc(dt, &command);}*[CHAREST.DTLIB.SRC]DTDCHA.C;1+,W ./_x 43:-M 0123KPWO56K7w-(xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION)title dt_dchar Dump One Character Visibly"index Dump one character visiblysynopsis .s.nf #include  dt_dchar(c, iov) int c; /* Character to dump */# FILE *iov; /* File to write to */ .s.f description0 The character is formatted into a visible Ascii2 "Datascope" format and the resulting text written to the indicated file.1 Note that this routine is independent of DECtalk definitions.3 Output is via the C standard library. If the dump$ is to a terminal, it is unbuffered.#endif#include dt_dchar(c, iov)register int c;register FILE *iov;/* * Dump a character. */{ char work[12]; dt_visible(c, work); fprintf(iov, "%s", work); if (isatty(fileno(iov))) fflush(iov);}*[CHAREST.DTLIB.SRC]DTDCS.C;1+,Y ./_x 4Bx-M 0123KPWO56r"7 K(xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION(title dt_dcs Send a DECtalk DCS Command"index Send a DECtalk DCS commandsynopsis .s.nf #include  #include "dectlk.h" dt_dcs(dt, p2, p3, p4)& DECTALK *dt; /* Device descriptor */ int p2; /* P2_xxx parameter */$ int p3; /* P3_PH_xxxx parameter */ int p4; /* timeout or rings */ .s.f description2 This routine sends a DECtalk DCS control sequence% using the p2, p3, and p4 parameters.+ Note that the Pn parameters are -1 if they are not sent. No errors are possible.#endif #include #include "dectlk.h"(static SEQUENCE DT_string_terminator = {" ST /* String terminator */};dt_dcs(dt, p2, p3, p4)+register DECTALK *dt; /* Dectalk device */*int p2, p3, p4; /* Parameters to send *//*3 * Load the parameter buffer and send the sequence.B * dt->send.param[0] contains the number of additional parameters. */{ dt->send.state = DCS; dt->send.final = DCS_F_DECTALK; dt->send.private = 0; dt->send.inter[0] = 0; dt->send.param[0] = 1; if (p2 >= 0) { dt->send.param[0]++; dt->send.param[2] = p2; } if (p3 >= 0) { dt->send.param[0]++; dt->send.param[3] = p3; } if (p4 >= 0) { dt->send.param[0]++; dt->send.param[4] = p4; } dt_pesc(dt, &dt->send);$ dt_pesc(dt, &DT_string_terminator);}*[CHAREST.DTLIB.SRC]DTDEMO.C;1+,Z ./_x 4A-M 0123KPWO567j(xL89ɊʑG_xHJ(/*) * S A M P L E M A I N P R O G R A M *//*)BUILD $(INCLUDE) = { dtdemo.h } $(FILES) = { dtdemo sample }0 $(RTLIB) = { dtlib,c:rstslb,c:clib } # Get the2 $(RXLIB) = { dtlib/lb,c:cx/lb,c:c/lb } # special6 $(VXLIB) = { []vdtlib/lib,lb:crtlib/lib } # libraries*/#ifdef DOCUMENTATION!title dtdemo Sample Main Programindex Sample main programsynopsis .s.nf( dtdemo [-d] [-t terminal] [-m max_time] .s.f description2 This is a sample "answer the phone" main program.. It calls a user-written subroutine, process()- when the phone is answered. This subroutine/ should return TRUE when the call has completed/ successfully and FALSE when the call completes- in error. The main program will hang up the% phone before starting the next call.% The following options are supported: .s.lm+12.nj% .i-12;-d##########Enable debug logs.* .i-12;-t#device###The DECtalk terminal is! connected to this terminal line.) .i-12;-m#seconds##Hangup the phone after+ the specified number of seconds. (Default- is 180 seconds or 3 minutes.) -m#0 disables the hangup. .s.lm-12.j: On Unix and VMS, an environment variable, DECTALK, may be9 used to specify the DECtalk terminal line. On VMS, this3 would be set by the DCL ASSIGN command as follows: $ ASSIGN terminal DECTALK4 On P/OS, the DECtalk device must be attached to the9 PRO-350 printer port for the software to work correctly. P/OS V1.7 is required.. The user-written process subroutine should be defined as follows: int process(dt, max)& DECTALK *dt; /* DECtalk device */" int max; /* -m parameter */#endif #include #include "dectlk.h" #ifdef vms/*0 * This creates text files in vanilla RMS on VMS */extern FILE *fdopen();@#define CREATE(f, m) fdopen(creat(f, 0, "rat=cr", "rfm=var"), m)#else#define CREATE fopen#endif char *dev = NULL;int off_demo = 180;main(argc, argv) int argc;char *argv[];{/ register DECTALK *dt; /* Dectalk device *// register int retries; /* Initializations *// register int ncalls; /* Completed calls */ extern DECTALK *dt_open(); argc = setup(argc, argv); retries = 0; ncalls = 0; dt_debug = TRUE;# if ((dt = dt_open(dev)) == NULL) { perror(dev); exit(IO_ERROR); }& dt_trap(); /* Catch CTRL/C abort */0 while (dt_init(dt)) { /* One-time setup */* dt_dcs(dt, P2_MODE, MODE_SQUARE, -1);* retries++; /* Count attempts */8 while (dt_answer(dt, 1)) { /* Answer the phone */2 if (process(dt, off_demo)) { /* User process */) ncalls++; /* User ran ok, */+ retries = 0; /* Clear retry count */ }* dt_hangup(dt); /* Hangup the phone */) if (dt_abort) /* Check interrupt */) goto finis; /* Error exit */ } if (dt_abort)% goto finis; /* Error exit */. if (retries > 2) { /* Got lost? */ printf("Too many retries\n"); goto finis; } }+ printf("Cannot initialize \"%s\"\n", dev);2finis: dt_abort = FALSE; /* Restart output */) dt_reset(dt); /* Hangup DECtalk */* dt_put(dt, 0); /* Force out buffer */) dt_close(dt); /* Close up DECtalk */} static intsetup(argc, argv) int argc;char *argv[];{ #ifndef decus extern char *getenv();#endif argc = getoptions(argc, argv); if (dev == NULL && argc > 1) dev = argv[1]; #ifdef unix if (dev == NULL) dev = getenv("DECTALK");#endif #ifdef vms if (dev == NULL) dev = getenv("DECTALK");#endif #ifdef rsx if (dev == NULL) dev = "TT2:";#endif #ifdef rt11 if (dev == NULL) dev = "TT2:";#endif if (dev == NULL) {/ fprintf(stderr, "No device specified.\n"); exit(IO_ERROR); }} /* * G E T O P T I O N S *> * Generalized command line argument processor. The following! * types of arguments are parsed:3 * flags The associated int global is incremented: * -f f-flag set to 1+ * -f123 f-flag set to 123 (no separator)' * -fg f-flag and g-flag incremented.3 * values A value must be present. The associated# * int global receives the value: * -v123 value set to 123 * -v 123 value set to 1230 * arguments The associated global (a char *) is * set to the next argument:! * -f foo argument set to "foo" */#define FLAG 0#define VALUE 1 #define ARG 2#define ERROR 3typedef struct argstruct { char opt; /* Option byte */" char type; /* FLAG/VALUE/ARG *// char **name; /* What to set if option seen */, char *what; /* String for error message */ } ARGSTRUCT;static ARGSTRUCT arginfo[] = {/ { 'd', FLAG, (char **)&dt_debug, "debug" },9 { 'm', VALUE, (char **)&off_demo, "Max. demo time" },( { 't', ARG, &dev, "device name" },! { EOS, ERROR, NULL, NULL },};static char *argtype[] = {( "flag", "takes value", "takes argument"};#include  static intgetoptions(argc, argv) int argc; char **argv;/*< * Process arg's. The argument vector is compressed and the6 * number of arguments remaing (new argc) is returned. */{ register char *ap; register int c; register ARGSTRUCT *sp; int i; /* Input argv index */! int j; /* Output argv index */ int helpneeded;# argc = getredirection(argc, argv); helpneeded = FALSE;! for (j = i = 1; i < argc; i++) { if (*(ap = argv[i]) != '-') argv[j++] = ap; else {# for (ap++; (c = *ap++) != EOS;) { if (isupper(c)) c = tolower(c); sp = arginfo;, while (sp->opt != EOS && sp->opt != c) sp++; switch (sp->type) {% case FLAG: /* Set the flag */ if (!isdigit(*ap)) { (*((int *)sp->name))++; break; } case VALUE: /* -x123 */ if (isdigit(*ap)) {% *((int *)sp->name) = atoi(ap); *ap = EOS; }' else if (*ap == EOS && ++i < argc) {* *((int *)sp->name) = atoi(argv[i]); } else { fprintf(stderr, "Bad option '%c%s' (%s)", c, ap, sp->what);& fprintf(stderr, ", ignored\n"); helpneeded++; } break; case ARG: /* -x foo */ if (++i < argc) {' *((char **) sp->name) = argv[i]; } else { fprintf(stderr,$ "Argument needed for '%c' (%s)", c, sp->what);& fprintf(stderr, ", ignored\n"); helpneeded++; } break; case ERROR: fprintf(stderr,, "Unknown option '%c', ignored\n", c); helpneeded++; break; } } } } if (helpneeded > 0) {/ for (sp = arginfo; sp->opt != EOS; sp++) {& fprintf(stderr, "'%c' -- %s (%s)\n",, sp->opt, sp->what, argtype[sp->type]); } } argv[j] = NULL; return (j);} /*< * getredirection() is intended to aid in porting C programs7 * to VMS (Vax-11 C) which does not support '>' and '<'7 * I/O redirection. With suitable modification, it may1 * useful for other portability problems as well. */#include static intgetredirection(argc, argv) int argc; char **argv;/*= * Process vms redirection arg's. Exit if any error is seen.: * If getredirection() processes an argument, it is erased? * from the vector. getredirection() returns a new argc value. *> * Warning: do not try to simplify the code for vms. The codeA * presupposes that getredirection() is called before any data is( * read from stdin or written to stdout. * * Normal usage is as follows: * * main(argc, argv) * int argc; * char *argv[]; * {& * argc = getredirection(argc, argv); * } */{ #ifdef vms+ register char *ap; /* Argument pointer */ int i; /* argv[] index */ int j; /* Output index */# int file; /* File_descriptor */- extern int errno; /* Last vms i/o error */: for (j = i = 1; i < argc; i++) { /* Do all arguments */ switch (*(ap = argv[i])) { case '<': /* ': /* >file or >>file */# if (*++ap == '>') { /* >>file */ /*3 * If the file exists, and is writable by us,6 * call freopen to append to the file (using the7 * file's current attributes). Otherwise, create3 * a new file with "vanilla" attributes as if/ * the argument was given as ">filename".3 * access(name, 2) is TRUE if we can write on * the specified file. */! if (access(++ap, 2) == 0) {( if (freopen(ap, "a", stdout) != NULL)' break; /* Exit case statement */( perror(ap); /* Error, can't append */' exit(errno); /* After access test */" } /* If file accessable */ } /*8 * On vms, we want to create the file using "standard"5 * record attributes. create(...) creates the file3 * using the caller's default protection mask and/ * "variable length, implied carriage return"8 * attributes. dup2() associates the file with stdout. */6 if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1) || dup2(file, fileno(stdout)) == -1) {* perror(ap); /* Can't create file */) exit(errno); /* is a fatal error */ } /* If '>' creation */ break; /* Exit case test */ default:) argv[j++] = ap; /* Not a redirector */ break; /* Exit case test */ } } /* For all arguments */ return (j);#else /*2 * Note: argv[] is referenced to fool the Decus C3 * syntax analyser, supressing an unneeded warning * message. */3 return (argv[0], argc); /* Just return as seen */#endif}*[CHAREST.DTLIB.SRC]DTDIAL.C;1+,\ . /_x 4= *-M 0123KPWO 56T7 (xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION!title dt_dial Dial the Telephoneindex Dial the telephonesynopsis .s.nf #include  #include "dectlk.h" int! dt_dial(dt, p3, numb, wait, msg)& DECTALK *dt; /* Device descriptor */$ int p3; /* P3_PH_xxxx parameter */" char *numb; /* Number to dial */ int wait; /* See below */ char *msg; /* Announcement */ .s.f description2 This routine dials the DECtalk telephone. The P30 parameter must be either P3_PH_TONE (tone dial) or P3_PH_PULSE (pulse dial). .s2 For tone dialing, the number text may contain any1 valid touch-tone characters ("0123456789*#ABCD")/ or the characters '!' (for a one second delay)4 or the '^' for a 250 millisecond switch-hook flash." All other characters are ignored. .s7 If pulse dialing is selected, only the digits, '!' and '^' are interpreted.3 Note that the telephone will not be hung up before5 dialing if it is offhook when the command is issued.Call Progress Detection3 DECtalk cannot tell if or when someone answers the7 phone. The only way to do this is to speak a message,2 such as "This is DECtalk, please press any button3 on the keypad." and wait some limited time for the. person to press the button. The wait and msg$ parameters provide this capability.7 If wait is less than or equal to zero, DECtalk returns7 without attempting to verify that someone has answered4 the phone. The return will be TRUE if the phone is offhook.6 If wait is greater than zero, it specifies the number2 of seconds to wait for a response, and msg is the4 message to speak. (If msg is NULL, the sample text4 shown above will be used.) The message is repeated/ continuously until either the alloted time has9 elapsed or a button is received. dt_dial() then returns( TRUE if the phone is offhook, as above.5 To cause DECtalk to silently wait for a message, use3 a zero-length string (""). Note, however, that an5 audible message is required by some public telephone systems.4 When DECtalk returns after call progress detection,7 keypad data entry and keypad timeout will be disabled.#endif#include #include "dectlk.h"=#define ANNOUNCEMENT "This is DECtalk, please press any key."int&dt_dial(dt, p3, number, wait, message).register DECTALK *dt; /* Device descriptor */$int p3; /* P3_PH_PULSE or TONE */,register char *number; /* Number to dial */&int wait; /* Call progress delay */$char *message; /* Announcement *//* * Send a phone message. */{ register int code;( int dialtime; /* Time to dial phone */ long endtime; extern long time();& if (number == NULL) /* Paranoia, */& number = ""; /* Ahh, paranoia */ dt_cmd(dt, P2_PHONE, p3); dialtime = strlen(number); if (p3 == P3_PH_PULSE) dialtime *= 2;. while (*number != EOS) /* Send the number */ dt_put(dt, *number++); dt_st(dt); do {' code = dt_read(dt, dialtime + 30);+ } while (code == ST || dt_save(dt, code)); if (wait <= 0) return (dt_offhook(dt)); /* * Call progress detection. */- if (!dt_offhook(dt) || !dt_keypad(dt, TRUE)) return (FALSE);! endtime = time(NULL) + wait + 1; if (message == NULL) message = ANNOUNCEMENT; do {3 dt_talk(dt, message); /* Speak announcement */0 dt_put(dt, VT); /* Make sure it's heard */% } while ((code = dt_read(dt, 5)) < 0! && time(NULL) <= endtime);2 dt_dcs(dt, P2_STOP, -1, -1); /* Enough already */* if (dt_isvalid(code)) { /* User key? */4 dt_keypad(dt, FALSE); /* Turn off keypad and */+ dt_drain(dt); /* Drop pending text */( return (TRUE); /* Normal return */ }/ else if (dt_phone(dt, -1, -1), dt_offhook(dt)). dt_hangup(dt); /* No response, hangup */ return (FALSE);}*[CHAREST.DTLIB.SRC]DTDRAI.C;1+,] ./_x 49-M 0123KPWO56)a178(xL89ɊʑG_xHJ  /*)LIBRARY*/#ifdef DOCUMENTATION"title dt_drain Drain Pending Inputindex Drain pending inputsynopsis .s.nf #include  #include "dectlk.h" dt_drain(dt)& DECTALK *dt; /* Device descriptor */ .s.f description" Absorb any type-ahead characters. No errors are possible.note5 On Unix systems, dt_drain() will also cancel pending0 output. This may cause DECtalk to receive word' fragments or partial escape sequences.5 The code is conditionally compiled for two varieties3 of Unix: Ultrix-32 (or 4.2 bsd) and Unix system V.I2 Other varieties of Unix and Unix-like systems may need to edit this file.#endif#include #include "dectlk.h"; #ifdef unixr dt_drain(dt)register DECTALK *dt;r/*0 * dt_drain() tosses out any pending type-ahead. */o{- dt->pend_fc = dt->pend_fp = dt->pend_ep = 0; #ifdef BSD_42u" ioctl(dt->unit, TIOCFLUSH, NULL);#else #ifdef UNIX_Va- ioctl(dt->unit, TCFLSH, 0); /* Unix V7 */<#endif#endif' dt->in_ptr = dt->in_end = dt->in_buff;n} #endif #ifdef vms#include dt_drain(dt)register DECTALK *dt;*/*0 * dt_drain() tosses out any pending type-ahead. */d{B- dt->pend_fc = dt->pend_fp = dt->pend_ep = 0;s /*i8 * This is probably sub-optimal. It should be possible * to do "sys$qiow(...i* * IO$_READLBLK | IO$M_PURGE | IO$M_TIMED6 * with a zero-length timeout, but I sure don't know. */ while (dt_vmsread(dt,9 IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED,> IN_BUFLEN, 0) >= IN_BUFLEN)T ;' dt->in_ptr = dt->in_end = dt->in_buff;n} #endif #ifdef rt11d#include o dt_drain(dt)register DECTALK *dt;o/*0 * dt_drain() tosses out any pending type-ahead. */l{s- dt->pend_fc = dt->pend_fp = dt->pend_ep = 0;X clrxrb();) xrb.xrlen = 7; /* Cancel type-ahead */s xrb.xrci = dt->unit * 2;  xrb.xrblkm = TTYHND;g rstsys(_SPEC);l' dt->in_ptr = dt->in_end = dt->in_buff;e} #endif #ifdef rsx dt_drain(dt)register DECTALK *dt;r/*0 * dt_drain() tosses out any pending type-ahead. */f{r- dt->pend_fc = dt->pend_fp = dt->pend_ep = 0;p do {h+ dt->in_ptr = dt->in_end = dt->in_buff;p } while (dt_get(dt, 1) > 0);,' dt->in_ptr = dt->in_end = dt->in_buff;f} #endif*[CHAREST.DTLIB.SRC]DTDUMP.C;1+,_ ./_x 45-M 0123KPWO56J17(xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION*title dt_dump Dump Escape Sequence Buffer#index Dump escape sequence buffersynopsis .s.nf #include  #include "dectk.h" int dt_dump(what, seq) char *what; /* Explanation */$ SEQUENCE *seq; /* Buffer to dump */ .s.f description0 The requested escape sequence buffer is written' (visibly) to the standard output file.5 If what is not NULL, it is written as an identifier.& Output is via the C standard library. For example, #include  #include "dectlk.h" DECTALK *dt; extern DECTALK *dt_open(); ... /* * Open a DECtalk device, * request phone status and# * dump returned status sequence. */ dt = dt_open("kb2:");! dt_phone(dt, P2_PH_STATUS, -1); dt_dump("status", &dt->reply);#endif#include #include "dectlk.h"dt_dump(what, seq) char *what;register SEQUENCE *seq;{ register int i; register char *wp; char work[81]; extern char *dt_visible(); if (what != NULL) printf("%s: \"", what);# wp = dt_visible(seq->state, work); switch (seq->state) { case ESC: case CSI: case DCS: if (seq->private != 0)$ wp = dt_visible(seq->private, wp);+ for (i = 1; i <= seq->param[0]; i++) { if (i > 1) *wp++ = ';'; if (seq->param[i] != 0) {' sprintf(wp, "%u", seq->param[i]); wp += strlen(wp); } }) for (i = 1; i <= seq->inter[0]; i++)% wp = dt_visible(seq->inter[i], wp);n break;f default:o break;  } if (seq->final != 0)-% wp = dt_visible(seq->final, wp);8 *wp = EOS;4 printf("%s%s", work, (what == NULL) ? "" : "\"\n");}*[CHAREST.DTLIB.SRC]DTEOL.C;1+,` ./_x 43b-M 0123KPWO56;_7A(xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION*title dt_eol Write End of Line to DECtalk$index Write End of Line to DECtalksynopsis .s.nf #include c #include "dectlk.h" dt_eol(dt)u& DECTALK *dt; /* Device descriptor */ .s.f/ descriptions/ An "end of line" is written to DECtalk and theT0 operating system executive service is called to/ cause the local output buffer to be written tot the terminal. No value is returned.1 This routine is needed on operating systems thatr0 enforce "line wrap-around" on terminal devices.3 It also improves the appearance of debugging logs.T#endif#include #include "dectlk.h" #ifdef dt_eolq #undef dt_eolu#endif dt_eol(dt).register DECTALK *dt; /* Device descriptor */{: #ifndef unix dt_put(dt, '\r');#endif dt_put(dt, '\n'); dt_put(dt, 0);e}f*[CHAREST.DTLIB.SRC]DTGESC.C;1+,b ./_x 4AF-M 0123KPWO56|=Q7!)xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION0title dt_gesc Read Escape Sequence or Character)index Read escape sequence or charactersynopsis .s.nf #include  #include "dectlk.h" int dt_gesc(dt, sec)& DECTALK *dt; /* Device descriptor */$ char sec; /* O.S. timeout value */ .s.f description- Read an escape sequence or keypad character.8 dt_gesc() interprets a stream of 7- or 8-bit charactersA including escape sequences adhering to the coded representations> of ISO 646, ISO 2022, and ISO 6429 with extensions to the DCS, introducer as required by DEC Standard 138.5 The function dt_gesc() recognizes ESC, CSI, and DCS,= and processes characters following each of these introducers? until a complete sequence is encountered. In the case of DCS,; control returns to the caller after the final character of; the DEC Standard 138 introduction sequence, but before the3 first data character of the device control string.< When sandwiched between the applicati0~ DTLIB.BCKb M [CHAREST.DTLIB.SRC]DTGESC.C;1Aޥ&on and a get character4 function (dt_get()), dt_gesc() transforms the input@ stream from a character stream to a stream of tokens consisting< of characters, escape sequences, control sequences, and DCS= introduction sequences. When any of the recognized sequence= types is encountered, the function value returned is that of< ESC, CSI, or DCS, and the interpretted body of the sequence7 is returned in the seq structure. The caller may treat8 dt_gesc() similarly to getchar(), ignoring the returned? structure in all cases except when the returned function value is ESC, CSI, or DCS.: An additional function performed by dt_gesc() is that all? C1 control functions received in their 7-bit form are returned= to the caller in their 8-bit form, thus eliminating the need@ for the caller to process C1 control functions in their (7-bit)@ escape sequence form and enforcing the equivalence of the 7-bit; and 8-bit forms of the C1 control functions. The function> also enforces the sequence cancellation effect of the SUB and CAN control characters.8 The dt_gesc() function calls the user-supplied dt_get(); (read one character) function as many times as required to: complete an escape sequence, control sequence, or Digital8 standard DCS introduction sequence. In the passed data 8 structure, it returns the final character, intermediate" characters, and parameter values.6 Since 7-bit operation is a compatible subset of 8-bit9 operation, there is -- normally -- no distinction in the1 dt_gesc() function between the two environments.s7 The application program may set the _FLAG_EIGHTBIT bit 6 in dt->flag to receive C1 control characters in their2 eight-bit form. If _FLAG_EIGHTBIT is set on, the3 application program must also ensure that the host_3 operating system communication line receives eighti= data bits, and that DECtalk setup has set HOST FORMAT EIGHT.. Also, dt_get() may return two special values,; DT_ERR and DT_TIMEOUT, to indicate operating-system errors1. and communication line timeouts respectively. e< Because C0 control characters may be embedded in sequences,9 and must be interpretted as if they occurred before the i/ sequence in the stream, the dt_gesc() functionA8 retains internal state information in the sequence data: structure from call to call. The seq.state value is zero@ on return to indicate a complete escape sequence. If non-zero,% it contains the sequence introducer.6 If the "seq.state" element is zero, dt_gesc() assumes= that the remainder of the data structure is invalid and that? there is no data being retained from a prior call. A non-zeroo9 value for the "seq.state" element indicates a particulard@ internal state (ESC, CSI, or DCS) that the parser should assume on the next call.= Intermediate characters and parameter values interpretted up = to the occurrence of the embedded control character are also = stored in the returned data structure and also should not be altered by the caller.(; Escape sequence syntax errors are indicated by setting ther6 seq.private parameter to 'X' (which is not a possible private parameter).3 If the dt_gesc() function encounters more than thee7 allowed maximum number of intermediate characters, thee= returned data structure indicates that one more intermediaten; character was received than allowed. Of course, charactersF" after the maximum are not stored.3 If the dt_gesc() function encounters more than theg; allowed maximum number of parameters, the extra parameters(; are ignored and the returned data structure indicates thata7 the allowed maximum number of parameters was received.g2 After each call to dt_gesc() the dt->seq SEQUENCE$ contains the following information:8 .br;seq.state#######zero to indicate complete sequence.1 .br;seq.final#######the sequence final character=1 .br;seq.private#####private parameter character:a6 .br;################EOS, <, =, >, ?, or X for errors.3 .br;seq.param[0]####the number of parameter valuese# .br;################(0:SEQ_PARMAX)a8 .br;seq.param[n]####(unsigned) the n'th parameter value: .br;seq.inter[0]####the number of intermediate characters% .br;################(0:SEQ_INTMAX+1)t< .br;seq.inter[n]####(char) the n'th intermediate character.< In general, the intermediate and final characters should be9 taken as a whole to determine the action. It is easy toe= ignore sequences with too many intermediate characters since.> the returned number of intermediate characters will not match any action function.g: To simplify the code, this module doesn't test for overly< large parameter values and assumes that all overflow errors% are due to invalid escape sequences.e#endif#include #include "dectlk.h"oint:dt_gesc(dt, sec)+register DECTALK *dt; /* Dectalk device */int sec; /* O.S. timeout */./*! * Return a character or sequences */ {T register int c; #ifdef decus register unsigned *p;#elses register unsigned short *p;#endif#ifdef DT_DEBUG  if (dt_debug) { dt_put(dt, 0);y printf("get: \"");F if (isatty(fileno(stdout))) fflush(stdout);r }#endif for (;;) { /*p2 * Loop until end of sequence forces an exit.5 * Get the next character from the input stream.0 * Note: we assume that negative values are * "out of band" signals. *@ * Note that DT_TIMEOUT and DT_ERR must be negative values. */% if ((c = dt_get(dt, sec)) > 0) {' if ((dt->flag & _FLAG_EIGHTBIT) == 0)+ c &= 0x7F; /* Enforce 7-bit input */ } if (c == NUL || c == DEL)" continue; /* Ignore NUL, DEL */ /*3 * Branch to c1_continue when changing [U * to CSI, etc. */ c1_continue:& if (c == ESC /* ESC, CSI, DCS */* || c == CSI /* Introduce control */' || c == DCS) { /* sequences. */U dt->seq.state = c;U dt->seq.inter[0] = 0; dt->seq.private = 0;U dt->seq.param[0] = 0; dt->seq.param[1] = 0;U continue;U }; else if (dt->seq.state == 0) /* No pending sequence */( goto exit; /* Return the character */7 else if ((c >= 0x80 && c <= 0x9F) /* C1 control */% || (c == CAN) /* or sequence */% || (c == SUB)) { /* resetter. */ dt->seq.state = 0; goto exit; }2 else if (c < 0x20) /* C0 control or error */ goto exit;. else if (c <= 0x2F) { /* Intermediate */ dt->seq.inter[0]++;$ if (dt->seq.inter[0] < SEQ_INTMAX)* dt->seq.inter[dt->seq.inter[0]] = c; }5 else if (dt->seq.state == ESC) { /* ESC final */3 if (dt->seq.inter[0] == 0 && (c & 0x3F) < 0x20) { /*/ * This is the 7-bit form of a C1 control- * character. Convert it to the actual- * C1 control character and restart the1 * parse without getting another character. */ c = (c & 0x3F) + 0x80; goto c1_continue; } else {' break; /* Ordinary ESC ending */ } }+ else if (c <= 0x3F) { /* Parameter */, if (c >= 0x3C) { /* Private introducer? */2 if (dt->seq.param[0] > 0) /* Is it first? */, dt->seq.private = 'X'; /* error if not */ else {& dt->seq.private = c; /* Store it */& dt->seq.param[0]++; /* Flag seen */ } } else { /* Not private */ if (dt->seq.param[0] == 0)) dt->seq.param[0]++; /* Record first */" if (dt->seq.inter[0] != 0) {+ dt->seq.inter[0] = 0; /* Syntax error */ dt->seq.private = 'X'; }" if (c <= '9') { /* 0..9 */( if (dt->seq.param[0] <= SEQ_PARMAX) { /*# * There is room. Store it. *( * p points to current parameter.% * This should check for value * overflow. */. p = &(dt->seq.param[dt->seq.param[0]]);" *p = (*p * 10) + (c - '0'); } else { dt->seq.private = 'X'; } }* else if (c == ';') { /* Separator */& if (dt->seq.param[0] >= SEQ_PARMAX)) dt->seq.param[0] = SEQ_PARMAX + 1; else { /*# * There's room to setup for" * another parameter value. */ dt->seq.param[0]++;+ dt->seq.param[dt->seq.param[0]] = 0; } }$ else { /* colon is invalid */ dt->seq.private = 'X'; } } }& else { /* CSI/DCS terminator */2 if (dt->seq.param[0] == 0) /* No parameters: */3 dt->seq.param[0]++; /* want one zero-value */ break; /* Exit parser */ } } /*8 * Control transfers to here as result of either of the6 * two break statements. Character is the final char. * of ESC, CSI, or DCS. */% if (dt->seq.param[0] > SEQ_PARMAX) {c; dt->seq.param[0] = SEQ_PARMAX; /* Set count to max. */d/ dt->seq.private = 'X'; /* Flag an error */, }- dt->seq.final = c; /* Store final char. */a #ifdef decus- c = dt->seq.state; /* Fetch return value */a#elsec$ c = (unsigned short) dt->seq.state;#endif. dt->seq.state = 0; /* No sequence pending */#exit: /* Here to return char */g#ifdef DT_DEBUGr if (dt_debug) printf("\"\n");#endif! return (c); /* and return. */t}u*[CHAREST.DTLIB.SRC]DTGET.C;1+,c ./_x 474-M 0123KPWO56+Z7 @)xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION-title dt_get Read one Character from DECtalkt'index Read one character from DECtalkcsynopsis .s.nf #include o #include "dectlk.h" int dt_get(dt, sec)& DECTALK *dt; /* Device descriptor */$ int sec; /* O.S. timeout param. */ .s.f descriptioni6 One character is read from the DECtalk terminal line.4 The sec parameter enables operating-system timeout;$ it is zero if no timeout is needed.1 dt_get() returns the character or an error code:2 .lm +207 .s.i-20;DT__ERROR############An operating system errore& (or interrupt) was received.3 .s.i-20;DT__TIMEOUT##########The sec parameter wass7 non-zero and no character was received in sec seconds.l .s.lm -205 If DT_DEBUG is #defined when the library is compiledl0 and the global dt_debug is set non-zero (by the$ application program), the character2 received is logged to the standard output device.#endif#include #include "dectlk.h"e #ifdef dt_getn #undef dt_geta#endif int dt_debug;)intsdt_get(dt, sec)e.register DECTALK *dt; /* Device descriptor */)int sec; /* Operating system timeout */s{e register int c; extern int dt_debug;t c = dt_ioget(dt, sec);a if (dt_debug != 0)s dt_dchar(c, stdout);e return (c);} *[CHAREST.DTLIB.SRC]DTHANG.C;1+,e ./_x 48-M 0123KPWO567^)xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION$title dt_hangup Hangup the telephoneindex Hangup the telephonesynopsis .s.nf #include f #include "dectlk.h" dt_hangup(dt)& DECTALK *dt; /* Device descriptor */ .s.f/ descriptionr+ Hangup the telephone connected to DECtalk.- Return TRUE if successful, FALSE if an errorf #endif#include #include "dectlk.h"linta dt_hangup(dt)eregister DECTALK *dt; /*" * dt_hangup() hangs up the phone. */h{c register int code;2) dt_drain(dt); /* Drain pending text */o7 if (!dt_phone(dt, P3_PH_STATUS, -1)) /* Check state */i" return (FALSE); /* Oops */1 if (dt_offhook(dt)) { /* If it's not hung up */w) if (!dt_phone(dt, P3_PH_HANGUP, -1))I) return (FALSE); /* Couldn't hangup? */c8 while (dt_offhook(dt)) { /* While still off-hook */( if (dt_abort) /* Exit if interrupt */( return (FALSE); /* signal sets */& sleep(5); /* Wait and poll again */& if (!dt_phone(dt, P3_PH_STATUS, -1))) return (FALSE); /* Poll failed? */ } }. if (!dt_onhook(dt)) /* Did it hang up ok? */ return (FALSE);} *[CHAREST.DTLIB.SRC]DTINIT.C;1+,f ./_x 4<|-M 0123KPWO56\;7 )})xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION-title dt_init DECtalk Initialization Routine&index DECtalk initialization routinesynopsis .s.nf #include  #include "dectlk.h" int dt_init(dt)& DECTALK *dt; /* Device descriptor */ .s.f description6 Initialize the DECtalk terminal on the channel opened on dt.4 Return TRUE if the device initialized successfully. Return FALSE on failure.note: This routine turns off "local mode" so a logging terminal< does not inadvertently send a response to the "who are you" escape sequence.; This routine accepts DTC01 (ID code 19) as well as Spanish3 and British DECtalks using the new codes 81 or 82.#endif#include #include "dectlk.h""static SEQUENCE DT_who_are_you = { CSI, 'c'};int dt_init(dt)register DECTALK *dt;/*- * dt_init() is called to initialize DECtalk. */{+ dt_drain(dt); /* Ignore pending input */; dt_dcs(dt, P2_TERMINAL, 0, -1); /* No local->host stuff */2 dt->flag &= ~_FLAG_TERM; /* Remember this fact */ /*8 * Read device attributes and fail if it isn't DECtalk.2 * Expected reply is [?19c for the DTC01-AA/ * Later DECtalks use [?8*c (* is 1 -- 9) */ dt_pesc(dt, &DT_who_are_you); if (dt_read(dt, 15) == CSI && dt->reply.final == 'c' && dt->reply.private == '?' && dt->reply.inter[0] == 0 && dt->reply.param[0] >= 1: && ((dt->version = dt->reply.param[1]) == CSI_DA_PRODUCT2 || (dt->version >= 81 && dt->version <= 89))) {( dt_reset(dt); /* Reset device */. return (TRUE); /* Hangup and restart */ } return (FALSE);} *[CHAREST.DTLIB.SRC]DTINKE.C;1+,h . /_x 4= -M 0123KPWO 56T"7`)xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION0title dt_inkey Read a Telephone Keypad Character)index Read a Telephone Keypad Charactersynopsis .s.nf #include  #include "dectlk.h" int dt_inkey(dt, sec)& DECTALK *dt; /* Device descriptor */ int sec; /* Seconds to wait */ .s.f description. This routine reads a telephone keypad button./ The application program has previously enabled- the keypad (by calling dt_keypad(dt, TRUE))., dt_inkey() will call dt_timeout() to enable or disable timeouts.3 If sec is non-zero, it will indicate the number of1 seconds to wait for a keypad response. If zero," it will turn off keypad timeouts.. The operating-system timeout (needed to catch1 hardware or communication line problems) will be- set to four times the timeout value, plus an. operating-system specific additional timeout. .s+ dt_inkey() returns a character as follows: .lm +204 .s.i-20;0123456789*_#ABCD####A valid keypad button.. (Note that "ABCD" may be generated by certain keypad phones.)7 .s.i-20;E###################An operating-system error.9 .s.i-20;H###################Unexpected telephone hangup., .s.i-20;T###################Keypad timeout.+ .s.i=20;W###################Wink detected.: .s.i-20;X###################Badly parsed escape sequence. .s.lm -205 The 'H' code is received if the DECtalk device hangs7 up the phone (as may be required by specific telephone system requirements).7 The 'W' code is received if a DTC03 has wink-detection2 enabled and a wink (probably hangup) is detected.#endif#include #include "dectlk.h"/*7 * Fudge is needed because of terminal output buffering4 * capacities and strategies. It should be tuned by * inspection. *9 * The RSTS/E value is large because RSTS/E will resume a; * program when less than 80 bytes remain to be transmitted= * to DECtalk. DECtalk may have about 100 bytes in its input5 * buffers and two phrases in the letter to sound and: * synthesizer sections. If the value is set too low, the: * application program may incorrectly assume that DECtalk' * or the communication line is broken. */ #ifdef rt11/#define FUDGE 60 /* RSTS/E needs extra time */#else-#define FUDGE 15 /* This is just a guess */#endifdt_inkey(dt, sec)+register DECTALK *dt; /* Dectalk device */ int sec; /* Keypad timeout */{ register int code; register int os_timeout;. dt_timeout(dt, sec); /* Set/clear timeout */ if (dt_iskey(dt)) {" code = dt->pend[dt->pend_ep];$ if (++dt->pend_ep >= PEND_SIZE) dt->pend_ep = 0; dt->pend_fc--; } else { if ((code = dt_read(dt,0 (sec == 0) ? 0 : (sec * 4 + FUDGE))) <= 0) code = 'E';! else if (dt_istimeout(dt)) { code = 'T'; dt->timeout = 0; } else if (dt_onhook(dt)) code = 'H';0 else if (dt_test(dt, R2_PHONE, R3_PH_WINK)) code = 'W';& else if (dt->reply.private == 'X' || !dt_isvalid(code)) code = 'X'; } return (code);}*[CHAREST.DTLIB.SRC]DTIOGE.C;1+,i ./_x 4D4-M 0123KPWO5617)xL89ɊʑG_xHJ. /*)LIBRARY*//* * Edit History, * 84.04.10 MM HNGTTY incorrectly specified. */#ifdef DOCUMENTATION.title dt_ioget Read one Character from DECtalk'index Read one character from DECtalksynopsis .s.nf #include  #include "dectlk.h" int dt_ioget(dt, sec)& DECTALK *dt; /* Device descriptor */$ int sec; /* O.S. timeout param. */ .s.f description6 One character is read from the DECtalk terminal line.4 The sec parameter enables operating-system timeout;$ it is zero if no timeout is needed.3 dt_ioget() returns the character or an error code: .lm +207 .s.i-20;DT__ERROR############An operating system error& (or interrupt) was received.3 .s.i-20;DT__TIMEOUT##########The sec parameter was7 non-zero and no character was received in sec seconds. .s.lm -202 dt_ioget() is the operating-system specific input3 routine. It is the only routine to read data from the DECtalk terminal line.note2 On vms, an internally-used routine, dt_vmsread(),. is also defined. Application programs should not call this routine.7 This module contains specific code for Ultrix-32 (Unix9 4.2BSD) and Unix System V. The makefile for the library, should #define one of these as appropriate.#endif#include #include "dectlk.h"/*5 * Define all DECtalk library globals in this module. */'int dt_abort; /* TRUE on interrupt */0DECTALK *dt_root; /* Chain of all open units */ #ifdef unix#include #ifdef BSD_42#include #include #else #ifdef UNIX_V#include 4static ignore() {} /* Dummy function for signals */#endif#endifintdt_ioget(dt, sec)+register DECTALK *dt; /* DECtalk device */S(int sec; /* Wait time, 0 == forever *//*C * UNIX: Fill the input buffer, return the next (first) character.1 */{1 register int incount; /* Count and error code */ #ifdef BSD_42- auto int fdmask; /* File descriptor mask */3 struct timeval timeout; /* Select() timer value */#else #ifdef UNIX_V. register int ecode; /* For error handling */, extern int errno; /* System error value */#endif#endif /*& * Return buffered character (if any) */ if (dt->in_ptr < dt->in_end) # return (*dt->in_ptr++ & 0xFF); /* * We must refill the buffer */+ dt->in_ptr = dt->in_end = &dt->in_buff[0];& dt_ioput(dt, 0); /* Flush output */ if (dt_abort) return (DT_ERROR); #ifdef BSD_42, fdmask = 1 << dt->unit; /* Select unit */, timeout.tv_usec = 0; /* No milliseconds */2 timeout.tv_sec = sec; /* Max. seconds to wait */9 incount = select(dt->unit + 1, &fdmask, 0, 0, &timeout);Z if (incount < 0 || dt_abort)- return (DT_ERROR); /* Select failed? */o1 else if (incount == 0) /* Timeout triggered? */r) return (DT_TIMEOUT); /* Guess so */g else {6 incount = read(dt->unit, dt->in_buff, IN_BUFLEN); }#else" #ifdef UNIX_Vw. signal(SIGALRM, ignore); /* Enable alarms */" alarm(sec); /* Start timeout */$ errno = 0; /* Clear error flag */2 incount = read(dt->unit, dt->in_buff, IN_BUFLEN);' ecode = errno; /* Save error code */ ! alarm(0); /* Cancel timeout */0 signal(SIGALRM, SIG_IGN); /* Disable alarms */: if (incount < 0 && ecode == EINTR) /* Did it timeout? */. return (DT_TIMEOUT); /* Return failure */#endif#endif2 if (dt_abort || incount <= 0) /* Other error? */1 return (DT_ERROR); /* Return bad failure */$ dt->in_end = &dt->in_buff[incount]; return (*dt->in_ptr++ & 0xFF);e}8#endif a #ifdef vms-#include /* System status codes */)+#include /* I/O request codes */"/*( * Define the possible vms input flavors */+<#define RAW_READ (IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR)+#define TIMED_READ (RAW_READ | IO$M_TIMED)l typedef struct io_status_block {- short int status; /* I/O status code */n- short int term_offset; /* Datum size */ 1 short int terminator; /* Input terminator */ / short int term_size; /* Terminator size */ } IOSTAB;ointdt_ioget(dt, sec)l+register DECTALK *dt; /* DECtalk device */e(int sec; /* Wait time, 0 == forever *//*B * VMS: Fill the input buffer, return the next (first) character. */y{n1 register int incount; /* Count and error code */n /*a& * Return buffered character (if any) */ if (dt->in_ptr < dt->in_end) # return (*dt->in_ptr++ & 0xFF);  /*r * We must refill the buffera */+ dt->in_ptr = dt->in_end = &dt->in_buff[0]; & dt_ioput(dt, 0); /* Flush output */ /*e0 * First read anything in the system type-ahead* * buffer by reading with a zero timeout., * If nothing was read, read one byte (with * timeout if specified). */4 incount = dt_vmsread(dt, TIMED_READ, IN_BUFLEN, 0); if (incount == DT_TIMEOUT) {  incount = dt_vmsread(dt,r- (sec > 0) ? TIMED_READ : RAW_READ, 1, sec);D } if (incount < 0)s/ return (incount); /* Return error code */  /*S& * Common exit from all read routines */$ dt->in_end = &dt->in_buff[incount]; return (*dt->in_ptr++ & 0xFF);g}  tint *dt_vmsread(dt, command, how_many, timeout)+register DECTALK *dt; /* DECtalk device */u!int command; /* QIO command */o+int how_many; /* How many bytes to read */g"int timeout; /* timeout value *//*# * Actually read from vms. Return c( * (result > 0) the number of bytes read+ * (result < 0) error code (EOF or TIMEOUT) * (result cannot equal zero). */r{ - register int incount; /* Status parameter */ ( IOSTAB status; /* I/O status block */% register int i; /* For debugging */I /*.6 * termset is a terminator mask indicating "terminate3 * on any character". As implemented on VMS, thiso3 * allows the operating system to handle XOFF/XON.X */# static long termset[2] = { 0, 0 };y if (dt_abort) return (DT_ERROR); /*e0 * The status entries term_offset and term_size( * will yield the number of bytes read. */* incount = sys$qiow(1, /* Event flag */ dt->unit, /* Input channel */ command, /* Timed read */" &status, /* I/O status block */ NULL, /* AST block (none) */ 0, /* AST parameter */' dt->in_buff, /* P1 - input buffer */d% how_many, /* P2 - buffer length */& timeout, /* P3 - wait P3 seconds */& &termset, /* P4 - terminator set */+ NULL, /* P5 - ignored (prompt buffer) */' 0); /* P6 - ignored (prompt size) */3 if (incount == SS$_TIMEOUT) /* Timeout returned */ return (DT_TIMEOUT);7 else if (incount != SS$_NORMAL) /* Some other error */ return (DT_ERROR);1 incount = status.term_offset + status.term_size;m( if (incount <= 0) /* Nothing input? */0 return (DT_TIMEOUT); /* equals timeout. */ return (incount);}#endif #ifdef rt11/* * R S T S / E */#include mintdt_ioget(dt, sec)+register DECTALK *dt; /* DECtalk device */(int sec; /* Wait time, 0 == forever *//*D * RSTS/E: Fill the input buffer, return the next (first) character. */{1 register int incount; /* Count and error code */ /*& * Return buffered character (if any) */ if (dt->in_ptr < dt->in_end) # return (*dt->in_ptr++ & 0xFF); /* * We must refill the buffer */+ dt->in_ptr = dt->in_end = &dt->in_buff[0];& dt_ioput(dt, 0); /* Flush output */ if (dt_abort) return (DT_ERROR); /*! * RSTS/E handles timeout within * the operating system. */ clrxrb();% xrb.xrlen = 4; /* No delimiter */ xrb.xrci = dt->unit * 2; xrb.xrblkm = TTYHND; rstsys(_SPEC); clrxrb(); xrb.xrlen = 3; /* No echo */ xrb.xrci = dt->unit * 2; xrb.xrblkm = TTYHND; rstsys(_SPEC);) incount = rs_read(dt->unit, dt->in_buff, IN_BUFLEN, 0, 0, sec, 0);* if (incount == (-HNGTTY)) /* 84.04.10 */ return (DT_TIMEOUT); else if (incount <= 0) return (DT_ERROR); /*& * Common exit from all read routines */$ dt->in_end = &dt->in_buff[incount]; return (*dt->in_ptr++ & 0xFF);}#endif #ifdef rsx/*$ * Load in RSX specific information: * cx.h common header& * qiofun.h I/O service function codes. * qioret.h I/O service error and status codes/ * qiottd.h Terminal I/O service bits and bytes) * lunbuf.h Device characteristics buffer */#include #include #include #include #include )#define QIO_EFN 1 /* I/O event flag */)#define MKT_EFN 2 /* Time event flag */=static char gmcbuf[2] = { TC_TBF }; /* get typeahead count */3static QIOPARM gmcparm = { gmcbuf, sizeof gmcbuf };3static int termtable[16]; /* Terminator bitmask */intdt_ioget(dt, sec)+register DECTALK *dt; /* DECtalk device */(int sec; /* Wait time, 0 == forever *//*B * RSX: Fill the input buffer, return the next (first) character. */{1 register int incount; /* Count and error code */. register char *ip; /* To copy to rsx buff */ int errorcode;, int efn_buffer[4]; /* Event flag buffer */ /*& * Return buffered character (if any) */ if (dt->in_ptr < dt->in_end) # return (*dt->in_ptr++ & 0xFF); /* * We must refill the buffer */+ dt->in_ptr = dt->in_end = &dt->in_buff[0];& dt_ioput(dt, 0); /* Flush output */ if (dt_abort) return (DT_ERROR); if (dt->pos_xk) { /*7 * The PRO-350 XK: port is actually pretty simple. */# dt->parm.buffer = dt->in_buff; dt->parm.size = IN_BUFLEN;( dt->parm.p3 = 0; /* No timeout */9 errorcode = qiow(IO_RLB | TF_TMO, dt->unit, QIO_EFN, &dt->iosb, NULL, &dt->parm);( if ((incount = fixiosb(dt)) == 0) { dt->parm.size = 1;) if ((dt->parm.p3 = (256 * sec)) == 0) {N1 errorcode = qiow(IO_RLB, dt->unit, QIO_EFN,C" &dt->iosb, NULL, &dt->parm); }t else {1 errorcode = qiow(IO_RLB | TF_TMO, dt->unit,c+ QIO_EFN, &dt->iosb, NULL, &dt->parm);  }/ if (errorcode != IS_SUC) {# return ((errorcode == IS_TMO) ? DT_TIMEOUT : DT_ERROR); } % if ((incount = fixiosb(dt)) == 0) {T return (DT_TIMEOUT); }g } } else {  /*f * Read from a terminal.o/ * First, check whether anything is in the.! * system type-ahead buffer.# */0 errorcode = qiow(SF_GMC, dt->unit, QIO_EFN, &dt->iosb, NULL, &gmcparm);# if (errorcode != IS_SUC) gmcbuf[1] = 0;# dt->parm.buffer = dt->in_buff;1 dt->parm.size = 1; /* Assume 1 byte read */p. if ((incount = (gmcbuf[1] & 0xFF)) > 0) { if (incount > IN_BUFLEN) incount = IN_BUFLEN; dt->parm.size = incount;6 errorcode = qiow(IO_RTT | TF_RNE, dt->unit, QIO_EFN," &dt->iosb, NULL, &dt->parm); incount = fixiosb(dt); } if (incount == 0) { if (sec == 0) {a! dt->parm.table = termtable; . qiow(IO_RTT | TF_RNE, dt->unit, QIO_EFN, &dt->iosb, NULL, &dt->parm);<' if ((incount = fixiosb(dt)) == 0)D return (DT_ERROR);r }b else { /*4 * Vax compatibility doesn't support read with5 * timeout (nor does it cause an error). Thus,d) * we have to do this the hard way. *7 * Set a mark time (alarm) for "timeout" seconds.4 * Read one byte without waiting. If the wait7 * completes, cancel the timeout. If the timeout& * completes, cancel the readin. *// if (mrkt(MKT_EFN, sec, 2, NULL) != IS_SUC1 || qio(IO_RTT | TF_RNE, dt->unit, QIO_EFN,- &dt->iosb, NULL, &dt->parm) != IS_SUC)( return (DT_ERROR); /* Can't happen */ /*( * Wait until something completes,* * read event flags ~ DTLIB.BCKi M [CHAREST.DTLIB.SRC]DTIOGE.C;1DSBthen cancel the & * request that didn't complete. */ wtlo0(QIO_EFN | MKT_EFN); rdaf(efn_buffer);) if ((efn_buffer[0] & MKT_EFN) == 0)* cmkt(MKT_EFN, NULL); /* Cancel timer */+ if ((efn_buffer[0] & QIO_EFN) == 0) {" qiow(IO_KIL, dt->unit, QIO_EFN,# &dt->iosb, NULL, &dt->parm); return (DT_TIMEOUT); }' if ((incount = fixiosb(dt)) == 0) return (DT_ERROR); } } } /*0 * Common (success) exit from all read routines */$ dt->in_end = &dt->in_buff[incount]; return (*dt->in_ptr++ & 0xFF);} static int fixiosb(dt)+register DECTALK *dt; /* DECtalk device *//*0 * This routine returns the correct input count. * The code is unusual. *) * fixiosb() returns the true byte count. */{ extern int $$ferr;" if (dt->iosb.terminator != NUL) { /*, * Append the terminator to the buffer. */7 dt->in_buff[dt->iosb.count] = dt->iosb.terminator; dt->iosb.count++; } if (dt_abort || dt->iosb.status == IE_ABO || dt->iosb.count == 0) {& return (0); /* Read aborted */ }# else if (dt->iosb.status != IS_SUC& && dt->iosb.status != IS_TMO) { $$ferr = dt->iosb.status;# return (0); /* I/O error */ } return (dt->iosb.count);}#endif*[CHAREST.DTLIB.SRC]DTIOPU.C;1+,j . /_x 46 z-M 0123KPWO 56)47 p*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION-title dt_ioput Write one Character to DECtalk&index Write one character to DECtalksynopsis .s.nf #include  #include "dectlk.h" int dt_ioput(dt, byte)& DECTALK *dt; /* Device descriptor */% char byte; /* Character to write */ .s.f description1 If the argument character is zero, or the output/ buffer is full, the output buffer contents are written to the DECtalk device.4 If the argument character is non-zero, it is stored2 in the output buffer for subsequent transmission.4 By buffering characters internally, the load on the6 operating system is significantly reduced. Note that4 the input routine (dt_get(), dt_ioget()) will flush6 the output buffer before attempting to read any data.1 The "speak" routine, dt_talk(), also flushes the output buffer.( No data is returned. Errors are fatal.3 dt_ioput() is the operating-system specific output2 routine. It is the only routine to write data to the DECtalk terminal line.#endif #include #include "dectlk.h" #ifdef vms#include #include typedef struct io_status_block {- short int status; /* I/O status code */- short int term_offset; /* Datum size */1 short int terminator; /* Input terminator *// short int term_size; /* Terminator size */ } IOSTAB;#endif #ifdef rsx/*$ * Load in RSX specific information: * cx.h common header& * qiofun.h I/O service function codes. * qioret.h I/O service error and status codes/ * qiottd.h Terminal I/O service bits and bytes */#include #include #include #include )#define QIO_EFN 1 /* I/O event flag */#endifdt_ioput(dt, c)+register DECTALK *dt; /* DECtalk device */#int c; /* Character to output *//*3 * Store the byte (if not EOS). If the byte is EOS,' * or the buffer is full, write it out. */{ register int size; #ifdef vms register int code; IOSTAB status;#endif #ifdef rt11 register int code; extern int $$ferr;#endif #ifdef rsx register int code; extern int $$ferr;#endif if (c != 0) { #ifdef rt114 *dt->out_ptr++ = (c == ESC) ? (ESC | 0x80) : c;#else *dt->out_ptr++ = c;#endif }% size = (dt->out_ptr - dt->out_buff);2 if ((c == 0 && size > 0) || size >= OUT_BUFLEN) { /*! * We must write the buffer. */ if (!dt_abort) { #ifdef unix if (write(dt->unit, dt->out_buff, size) == -1) { perror(dt->device); exit(1); }#endif #ifdef vms+ if ((code = sys$qiow(1, /* Event flag */$ dt->unit, /* Input channel */2 IO$_WRITELBLK | IO$M_NOFORMAT, /* format */& &status, /* I/O status block */ NULL, /* No AST block */! 0, /* No AST parameter */& dt->out_buff, /* P1 - buffer */ size, /* P2 - bytes */ 0, /* P3 - ignored */% 0, /* P4 - no carriage ctl */ 0, /* P5 - ignored */ 0)) /* P6 - ignored */ != SS$_NORMAL) { perror(dt->device); exit(code); }#endif #ifdef rt11. if ((code = rs_write(dt->unit, dt->out_buff, size, 0, 0, 0)) != 0) { $$ferr = code; perror(dt->device); exit(IO_ERROR); }#endif #ifdef rsx dt->parm.size = size;! dt->parm.buffer = dt->out_buff; dt->parm.table = NULL;- if ((code = qiow(IO_WAL, dt->unit, QIO_EFN,, &dt->iosb, NULL, &dt->parm)) != IS_SUC) { $$ferr = code; perror(dt->device); exit(IO_ERROR); }#endif } dt->out_ptr = dt->out_buff; }}*[CHAREST.DTLIB.SRC]DTISKE.C;1+,l ./_x 43-M 0123KPWO56S87!*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION"title dt_iskey Test for type-aheadindex Test for type-aheadsynopsis .s.nf #include  #include "dectlk.h" int dt_iskey(dt)& DECTALK *dt; /* Device descriptor */ .s.f description3 This routine (which may be implemented as a macro)1 returns TRUE if any characters have already been2 typed by the telephone user or if an asynchronous/ status message (such as timeout) was received.#endif#include #include "dectlk.h"#ifdef dt_iskey#undef dt_iskey#endifint dt_iskey(dt).register DECTALK *dt; /* Device descriptor *//* * Test for type-ahead. */{ return(dt->pend_fc != 0);}*[CHAREST.DTLIB.SRC]DTISTI.C;1+,m ./_x 4:"-M 0123KPWO56> 47 y@*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION6title dt_istimeout Test Phone Reply for Keypad Timeout+index Test phone reply for keypad timeoutsynopsis .s.nf #include  #include "dectlk.h" int dt_istimeout(dt)& DECTALK *dt; /* Device descriptor */ .s.f description3 This routine (which may be implemented as a macro)* tests the result of a dt_phone() message.4 It returns TRUE if the current reply is the DECtalk: phone reply with the R3 parameter equal to R3_PH_TIMEOUT.#endif#include #include "dectlk.h"#ifdef dt_istimeout#undef dt_istimeout#endifintdt_istimeout(dt).register DECTALK *dt; /* Device descriptor *//*% * Test for telephone keypad timeout. */{/ return (dt_test(dt, R2_PHONE, R3_PH_TIMEOUT));}*[CHAREST.DTLIB.SRC]DTISVA.C;1+,o ./_x 43-M 0123KPWO567w]*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION0title dt_isvalid Test for Valid Keypad Character'index Test for valid keypad charactersynopsis .s.nf #include  #include "dectlk.h" int dt_isvalid(c) .s.f description3 This routine (which may be implemented as a macro)1 returns TRUE if the argument character is one of 0123456789#*ABCD#endif#include #include "dectlk.h"#ifdef dt_isvalid#undef dt_isvalid#endifint dt_isvalid(c)char c;/*" * Test for valid push-button key. */{" return ( (c >= '0' && c <= '9') || c == '*' || c == '#' || (c >= 'A' && c <= 'D'));}*[CHAREST.DTLIB.SRC]DTKEYP.C;1+,p ./_x 462-M 0123KPWO567tz*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION6title dt_keypad Enable or Disable the Telephone Keypad.index Enable or Disable the Telephone Keypadsynopsis .s.nf #include  #include "dectlk.h" int dt_keypad(dt, flag)& DECTALK *dt; /* Device descriptor */ int flag; /* TRUE to enable */ .s.fe descriptionr1 Enable the telephone keypad if the flag is TRUE, disable it if FALSE.i5 Returns TRUE if successful. If FALSE, the telephonei may have been hung up.v#endif#include #include "dectlk.h" int*dt_keypad(dt, enable)(register DECTALK *dt;L int enable;/** * Enable or disable the telephone keypad. */t{* dt_phone(dt,t3 (enable) ? P3_PH_KEYPAD : P3_PH_NOKEYPAD, -1);r if (dt_offhook(dt)) return (TRUE);T return (FALSE);}  *[CHAREST.DTLIB.SRC]DTLIBH.RNO;14+,r .$/_x 4L$$0-M 0123KPWO%56Y}i7(bxL89ɊʑG_xHJH..comment Standard DECUS C Documentation layout.commentB.comment Position the printer to start on the 4th line for 66 lineD.comment (11 inch) paper. The 60 lines printed should be verticallyK.comment centered on the page, with 3 line vertical margins top and bottom..commentG.comment The title page is laid out so that the title will show throughC.comment a "window" cover such as is used on Digital documentation..commentD.comment Note: there is a bug in the page number algorithm of RSTS/E@.comment runoff. Thus, on RSTS/E, GETRNO.C must mangle the page..comment heading to fix page number alignment..commentI.comment The following statement will give a (non-fatal) error on RNO.TSKH.comment It is needed because somebody was clever in designing "Standard.comment RUNOFF".%.NO AUTOSUBTITLE .STYLE HEADERS 3,0,0.comment.nhd.uc.ps 58,80.lm 8.rm 72#.s 26 .c ;DECtalk.s 2 .c ;Applications Support Library.c ;Reference Manual.s 6BThis document describes a support library for DECtalk which shouldDsimplify application development for the DECtalk DTC01 speech output terminal..s .comment date.nhy.s 5FUNIX is a trademark of Bell Telephone Laboratories. RSX, RSTS/E, RT118and VMS are trademarks of Digital Equipment Corporation..s"Touch-Tone is a tradmark of AT_&T..br3Unix is a trademark of Bell Telephone Laboratories..s.hd .hd mixed-.comment The following gives a bug on RNO.TSK .head mixed.comment.ch INTRODUCTION.ps 58,80.lm 8.rm 72 .hd mixed/.t ########DECtalk Applications Support Library.st ########Reference Manual.s<DTLIB is a runtime support library for programs written in CAprograms which mediates access to the DECtalk DTC01 speech output terminal..sAIt may be compiled to run on Vax/VMS native mode (using Vax-11C),7Vax/VMS compatibility mode, RSX11-M, RSX11M-PLUS, P/OS,and RSTS/E, using Decus C..s8It may also be compiled for Unix V7M and 4.2BSD systems..s:The I/O support modules have not been implemented on RT11..s@To use DTLIB, your application program must include the dectlk.h>header file with all compilations. The loadable image must belinked with the DTLIB library.3.note File name conventions and RSTS/E restrictions>Although referred to as "DTLIB" in this document, the suppliedBVMS command files build VDTLIB.OLB (Vax/VMS native) and XDTLIB.OLB(Vax/RSX-compatibility mode)..s>Decus C supports both RSX-11M and RT11 environments on RSTS/E.;Only the RT11 environment runs on RSTS/E. While this would<not be difficult to change, it will require edits to several=modules in the library. If you are using some other compiler8on RSX-11M or RSTS/E, you may need to modify the support!libraries, CX.OLB and RSTSLB.OBJ..en7To run the DECtalk library on RT11, you must modify the9DTOPEN.C, DTCLOS.C, DTIOGE.C, and DTIOPU.C modules to use:RT11 specific services, such as the multi-terminal driver..s?When attaching DECtalk to a computer, you should check that the>terminal line supports the XOFF/XON protocol. The easiest way<to do this is to configure the terminal line as if it were aVT100 video display terminal..s@On the PRO-350, these routines assume that the DECtalk host portIis connected to the PRO printer port (TT2:), using a BCC05 printer cable.;The software may also be used with DECtalk connected to the&hard-wired communications port (XK0:)..s<You can test that DECtalk is properly connected by copying a=text file to that port, using the operating system COPY (PIP)utility..hl 1 A sample programBThe following program is perhaps the simplest DECtalk application.It speaks a brief message:.tp 21.s.nf_#include _#include "dectlk.h".smain(){ DECTALK *dt;.s% if ((dt = dt__open("TT2:")) == NULL) perror("TT2:"); else {3 dt__talk(dt, "Hello world, this is DECtalk."); dt__sync(dt); dt__close(dt); }}.s.f9The program opens the DECtalk terminal (attached to TT2:)?and speaks a message. It then delays until the message is heard&by the listener and closes the device..hl 1 Answering the phone8The above program is adequate only when the DECtalk user8is "local" to the device itself. This would be the case;in a factory warning system or a computer-aided instruction application..s8In many other situations, the DECtalk user will interact@with DECtalk and your application by dialing a telephone number.<You must then command DECtalk to answer the phone, to accept=data entered via the telephone keypad, and then to hangup the8phone when the call is complete. A suitable "top-level"!program would then be as follows: .tp 42.s.nf_#include _#include "dectlk.h".smain(){/ register DECTALK *dt; /* Dectalk device *// register int retries; /* Initializations *// register int ncalls; /* Completed calls */.s retries = 0; ncalls = 0;' if ((dt = dt__open("TT2:")) == NULL) {- perror("TT2:); /* Can't open device *// exit(IO__ERROR); /* Exit program */ }' dt__trap(); /* Catch CTRL/C abort */1 while (dt__init(dt)) { /* One-time setup */- dt__dcs(dt, P2__MODE, MODE__SQUARE, -1);* retries++; /* Count attempts */9 while (dt__answer(dt, 1)) { /* Answer the phone */- if (process(dt)) { /* Do user process */) ncalls++; /* User ran ok, */+ retries = 0; /* Clear retry count */ }+ dt__hangup(dt); /* Hangup the phone */* if (dt__abort) /* Check interrupt */) goto finis; /* Error exit */ }- if (dt__abort) /* CTRL/C interrupt? */% goto finis; /* Error exit */. if (retries > 2) { /* Confused? */ printf("Too many retries_\n"); break; } }3finis: dt__abort = FALSE; /* Restart output */* dt__reset(dt); /* Hangup DECtalk */+ dt__put(dt, 0); /* Force out buffer */* dt__close(dt); /* Close up DECtalk */}.s.f>The above program fragment attempts to recover from transitoryA"line glitches" by allowing error returns from the user process()=and from dt__answer(). If, however, dt__answer() fails twice:in a row, the program aborts. It also establishes "CTRL/C=trapping" which will allow the developer to abort the programwithout losing log files..s:Note also that "square-bracket" phonemic mode is turned on!when the terminal is initialized..s?The essential flow of the above program (without error recovery0or interrupt processing) may be seen as follows: .tp 20.s.nf_#include _#include "dectlk.h".smain(){/ register DECTALK *dt; /* Dectalk device */.s' if ((dt = dt__open("TT2:")) == NULL) {- perror("TT2:); /* Can't open device *// exit(IO__ERROR); /* Program fails */ }. if (dt__init(dt)) { /* One-time setup */9 while (dt__answer(dt, 1)) { /* Answer the phone */( process(dt); /* Do user process */+ dt__hangup(dt); /* Hangup the phone */ } }* dt__close(dt); /* Close up DECtalk */}.s.f.hl 1 The User Process<When the phone is answered, the main program described above8will call an application-specific subroutine. This will*generally have the following control flow:.list 1).le ;Welcome the user to the application.!.le ;Enable the telephone keypad.;.le ;Ask for a command (enabling keypad timeouts to recoverfrom a disconnection).9.le ;Process the command and continue to process commands as needed.5.le ;Eventually, finish the application and return to9the main program (which will hangup the phone and preparefor the next caller)..els5The following code fragment illustrates a very simple/test program that echos the user's key presses: .tp 31.s.nf_#include _#include "dectlk.h".s process(dt)register DECTALK *dt;{+ register char c; /* Keypad character */) char work[30]; /* For echo message */.s$ dt__talk(dt, "Welcome to DECtalk");4 if (!dt__keypad(dt, TRUE)) /* Enable keypad */. return (FALSE); /* Error occurred */& for (;;) { /* Do forever... */1 c = dt__inkey(dt, 15); /* Get a key */3 if (!dt__isvalid(c)) /* Check for timeout */% return ((c == 'T') ? TRUE : FALSE);0 sprintf(work, "You pressed _%c_%c", c, VT); dt__talk(dt, work);. if (c == '*') { /* Make '*' special */. dt__timeout(dt, 0); /* No timeouts now */" dt__talk(dt, "Long message..."); } }}.s.fBNote that the "long message" turns off timeouts. If still "alive",FDECtalk will respond to the timeout message within 15 seconds. If theAhardware has been disconnected, the operating system timeout will<occur in a minute or so (depending on the operating system),=which will eventually cause an error return from the program..sABecause the user may press buttons when you don't expect them, itAis very important to call dt__inkey() to read from the Touch-toneCkeypad. Dt__inkey() contains a "type-ahead" buffer and understands@timeouts. It either returns a single character corresponding toCthe keypad button or a character representing an unusual situation:.lm +4.p -2=T#A timeout occurred (and timeouts were enabled at the time)..p -2BH#The DECtalk hardware hung up the phone. (This is required under,certain circumstances in certain countries.).p -2AE#An operating system error (probably hardware timeout) occurred..p -2GX#An illegal escape sequence was received. This may be a communication line problem..s.lm -49See the documentation of dt__inkey() for further details..hl 1 Some Other Tricks/This section contains a few other coding hints. .hl 2 Transmitting Phonemic TextDThe examples assume that most applications will use "square bracket"6mode to transmit phonemic text and voice commands. If5this is not suitable, the program will have to format*a more complex escape sequence as follows: .tp 15.s.nf dt__cmd(dt, P2__PHOTEXT, -1);' dt__talk(dt, ":np :ra 180 hh'ehlow."); dt__st(dt);.s.fEA similar sequence would be needed to load DECtalk's user dictionary..hl 2 Managing Keypad Timeout?When your program requests information from the telephone user,Ait is essential that you use some form of timeout so your programAwon't hang if the caller disconnects. The dt__inkey() routine is,the recommended way to read from the keypad:.s.nf key = dt__inkey(dt, timeout);.s.fCYou can use different timeouts for different parts of your program.EFor example, the following code fragment reads a user password (which>may contain one to six digits) from the keypad. It has a longAtimeout for the first character and short timeouts for successive characters:.s.nf, dt__talk(dt, "Please enter your password"); dt__talk(dt, NULL); timeout = 10; for (i = 0; i < 6; i++) {" key = dt__inkey(dt, timeout); if (!dt__isvalid(key))" break; /* Assume timeout */0 password[i] = key; /* Save the key */* timeout = 2; /* Short time now */ }, password[i] = EOS; /* Terminate entry */.s.f;On exit from the loop, The password string will contain the@data entered. If password[0] is EOS, nothing was entered beforetimeout..hl 2 Stopping in Mid-stream=If you are sending a long stream of text to the user, you may7want to allow a keypad button press to stop the speech.2The following subroutine takes an array of strings7to be spoken. The array is terminated by a NULL entry.7It returns FALSE if nothing was pressed (and everything>was transmitted to DECtalk), or TRUE if something was pressed.3(Your program reads the key by calling dt__inkey()..s'To restart cleanly after a TRUE return,1your program should retransmit a voice definition"[:np]" before anything else..s.nf int dt__speak(dt, strings) register DECTALK *dt; register char **strings; { dt__timeout(dt, 0); while (*strings != NULL) { dt__talk(dt, *strings++);; dt__msg(dt, P2__IX__QUERY, -1, -1, R2__IX__QUERY, -1); if (dt__iskey(dt)) { dt__dcs(dt, P2__STOP, -1, -1); return (TRUE); } } return (FALSE); }.s.fThe module does the following:.list 1.le ;Disables keypad timeouts.+.le ;For each string in the string array...1.le ;Transmit the string to DECtalk (dt__talk()).H.le ;Transmit an Index Query operation (dt__msg()). This will read data=from DECtalk and, as a side-effect, store any keypress in theinternal type-ahead buffer.L.le ;Check whether there is anything in the type-ahead buffer (dt__inkey()).If so,/.le ;Stop speaking (dt__dcs()) and return TRUE.:.le ;If nothing is in the type-ahead buffer, continue withBthe next string or return FALSE when all strings were transmitted..els#.hl 2 Reading Names from the Keypad=Touch-Tone keypads transmit a unique code when each button is=pressed. DECtalk transmits an Ascii character for each code.CHowever, an application designer may want to tell the application'sAuser "Press the Y key for Yes and the N key for No.", or may need@to compare text from the keypad with commands or usernames which;are encoded in ordinary Ascii text. The following functionAtests whether a keypad text string (as read from DECtalk) matches<a text word in alphabetic Ascii. As you can see, it assumes<that the '7' button is labelled "PQRS" and the '9' button islabelled "WXYZ"..s?Note: the strchr() function returns NULL if the second argumentA(a character) was not one of the characters in the first argument=string. On some Unix systems, the function is named "index".4It is comparable to the Basic-Plus INSTR() function. .tp 25.s.nfstatic char *btext[] = { "2ABCabc", "3DEFdef",! "4GHIghi", "5JKLjkl", "6MNOmno",% "7PQRSpqrs", "8TUVtuv", "9WXYZwxyz",};intbuttontest(kptext, match)/register char *kptext; /* Button format *//register char *match; /* ASCII format */{ extern char *strchr(); for (;;) { if (*kptext == *match) { if (*kptext == '_\0') return (TRUE); }, else if (*kptext < '2' || *kptext > '9'# || strchr(btext[*kptext - '2'], *match) == NULL) return (FALSE); text++; match++; }} .s.f!.hl 2 Speaking numbers or strings9Financial applications ("bank balance by phone") may want:to speak numbers twice, once as a "normal number" and once9as a string of digits so the listener can copy them down.:The following Basic-Plus subroutine takes a string of text8and expands it to one-letter words. Using it, a program!would generate a message such as:.s.nf. Your balance is $1425.92, that is one four two five point nine two..s 2.tp 24.nfl3000 !* &+ !* F N e x p a n d $ ( t e x t $ ) & !* &0 !* Expand a string into its component bytes. &0 !* Note that this would be useful in a "bank &0 !* by phone" application to speak a number, &0 !* digit by digit, so the caller could copy &0 !* it down. If the input is "12.3", the &0 !* output will be " 1 2 point 3". Note the & !* leading blank. & !* & def* FNexpand$(text$) & \ q$ = "" ! Output work &, \ for q% = 1% to len(text$) ! For each, &/ \ q1$ = mid(text$, q%, 1%) ! Locate byte &) \ q1$ = "point" if q1$ = '.' &) \ q1$ = "minus" if q1$ = '-' &/ \ q1$ = "dollar sign" if q1$ = '$' &* \ q$ = q$ + " " + q1$ ! Store byte & \ next q% ! Do 'em all &" \ FNexpand$ = q$ ! That's it & \ fnend &.s.f.fl9Note that certain bytes are "spelled out" to override theDECtalk built-in library..s8It is a simple matter to rewrite this in C and/or extend!the list of "special case" bytes. .hl 1 Summary<The above examples should be sufficient to help you past the=initial confusion that every programmer feels when faced withan unfamiliar device..s<Although the library may appear to have a complex structure,,the major control flow is relatively simple: .tp 32.s 2.nf.nfl( Application Program |; +----+----+--------+-----+---+--------+-------+-------+; | | | | | | | |e@dt_inkey | dt_init dt_answer dt_hangup dt_talk dt_open dt_close . | | | | | | | | + | +-+-+ | | +---+---+ |l, | | | | | | + | dt_timeout | | dt_phone |+ | | | | | |h+ | +------+-------+------+ |w+ | | |i+ | dt_msg dt_dcs | + | | | | | |e+ +------+-----------+ | +----+ | |n+ | | | | |m+ dt_read dt_save dt_pesc |i+ | | | + | | |o+ dt_gesc +----+-----+t% | |D' dt_get dt_put % | |2) dt_ioget dt_iopute .s 2.f.fll@Library modules communicate with DECtalk by one of three generalpaths:.list 1y8.le ;They speak text by calling dt__talk() or dt__put().7.le ;They send escape sequences by calling dt__dcs() or dt__pesc().B;.le ;They send DECtalk control sequences that will generaterreplies by calling dt__msg().o;.le ;They receive keypad characters by calling dt__inkey().x.els>As should be expected, there are a few special cases to handleunusual circumstances..sAAlso, the library does not address the need to load dictionaries, :send phonemic text using escape sequences, or test DECtalkhardware status.*[CHAREST.DTLIB.SRC]DTLIBI.RNO;1+,s ./_x 4I-M 0123KPWO56;i7JxL89ɊʑG_xHJ.ps 58,80.lm 8.rm 72.ax DTLIB LIBRARY INDEX+.t ########DECtalk Support Library (DTLIB)!.st ########Support Library Index .lm 8.rm 72.fIThe following is a keyword in context index to the DTLIB runtime library.@The entry in the left-hand column is the title of the routine inthe main library documentation..s 2.nf<.comment turn off flag recognition to allow _ in file names..noflags*[CHAREST.DTLIB.SRC]DTLIBU.RNO;1+,u ./_x 4+~-M 0123KPWO56GC7 xL89ɊʑG_xHJ.ps 58,80.lm 8.rm 72.ax USAGE INFORMATION+.t ########DECtalk Support Library (DTLIB).st ########Usage Information*[CHAREST.DTLIB.SRC]DTMSG.C;1+,v ./_x 4>0-M 0123KPWO5647`*xL89ɊʑG_xHJ`6~ DTLIB.BCKv M [CHAREST.DTLIB.SRC]DTMSG.C;11>۱ /*)LIBRARY*/#ifdef DOCUMENTATION/title dt_msg Send a DECtalk Command with Reply)index Send a DECtalk command with replysynopsis .s.nf #include  #include "dectlk.h" int dt_msg(dt, p2, p3, p4, r2, r3)& DECTALK *dt; /* Device descriptor */! int p2; /* P2_xxxx parameter */$ int p3; /* P3_PH_xxxx parameter */ int p4; /* timeout or rings */! int r2; /* R2_xxxx parameter */! int r3; /* R3_xxxx parameter */ .s.f description2 This routine sends a DECtalk DCS control sequence4 using the p2, p3, and p4 parameters. It then reads7 a DCS reply from DECtalk, returning TRUE if it matches" the r2 and r3 calling parameters.2 If p2 is -1, no sequence is sent; but a DCS reply is read and tested.2 Note that the Pn and Rn parameters are -1 if they& are not sent or checked respectively.; Returns TRUE if successful. If FALSE, something is funny.> Note: dt_msg() saves user keypad characters in the type-ahead buffer.#endif#include #include "dectlk.h"intdt_msg(dt, p2, p3, p4, r2, r3).register DECTALK *dt; /* Device descriptor */,int p2, p3, p4; /* Pn parameters to send */.int r2, r3; /* Reply R2 and R3 parameters *//*3 * Send a DECtalk DCS message and wait for a reply.0 * Return TRUE if the proper reply was received. */{ register int code; if (p2 != -1)4 dt_dcs(dt, p2, p3, p4); /* Send the sequence */ do { code = dt_read(dt, 60);+ } while (code == ST || dt_save(dt, code));2 return (dt_test(dt, r2, r3)); /* Check result */}*[CHAREST.DTLIB.SRC]DTOFFH.C;1+,x ./_x 4:-M 0123KPWO56.47*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION-title dt_offhook Test Phone Reply for Offhook$index Test phone reply for Offhooksynopsis .s.nf #include  #include "dectlk.h" int dt_offhook(dt)& DECTALK *dt; /* Device descriptor */ .s.f description3 This routine (which may be implemented as a macro)4 is used to test the result of a dt_phone() message.4 It returns TRUE if the current reply is the DECtalk: phone reply with the R3 parameter equal to R3_PH_OFFHOOK.#endif#include #include "dectlk.h"#ifdef dt_offhook#undef dt_offhook#endifintdt_offhook(dt).register DECTALK *dt; /* Device descriptor *//*& * Test whether the phone is off-hook. */{/ return (dt_test(dt, R2_PHONE, R3_PH_OFFHOOK));}*[CHAREST.DTLIB.SRC]DTONHO.C;1+,y ./_x 49 -M 0123KPWO56s>47*xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION+title dt_onhook Test Phone Reply for Onhook#index Test phone reply for onhooksynopsis .s.nf #include  #include "dectlk.h" int dt_onhook(dt)& DECTALK *dt; /* Device descriptor */ .s.f description3 This routine (which may be implemented as a macro)4 is used to test the result of a dt_phone() message.4 It returns TRUE if the current reply is the DECtalk9 phone reply with the R3 parameter equal to R3_PH_ONHOOK.#endif#include #include "dectlk.h"#ifdef dt_onhook#undef dt_onhook#endifint dt_onhook(dt).register DECTALK *dt; /* Device descriptor *//*% * Test whether the phone is on-hook. */{. return (dt_test(dt, R2_PHONE, R3_PH_ONHOOK));}*[CHAREST.DTLIB.SRC]DTOPEN.C;1+,{ ./_x 4C-M 0123KPWO56oW7 *xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION*title dt_open Connect to DECtalk Terminal#index Connect to DECtalk terminalsynopsis .s.nf #include  #include "dectlk.h" DECTALK * dt_open(dev)' char *dev; /* Terminal device name */ .s.f description. Perform operating-specific initializations to. initiate communication with a DECtalk device.- (This routine is similar to fopen() for FILE+ devices.) If the open fails, return NULL;+ else return a pointer to a data descriptor. block that will be used for all other DECtalk operations.2 If the open failed, the standard library perror()2 routine may be called to print error information.0 This routine does not communicate with DECtalk.3 For example, the following sequence opens DECtalk,4 checks that it is responding, sets "square-bracket" mode, and speaks a message: #include  #include "dectlk.h" DECTALK *dt; ... main() {' if ((dt = dt_open("kb2:")) == NULL) { perror("kb2:");% printf("Can't open DECtalk\n"); } else if (!dt_init(dt))) printf("Can't initiate DECtalk\n"); else {+ dt_dcs(dt, P2_MODE, MODE_SQUARE, -1);" dt_talk(dt, "Hello world."); dt_sync(dt); dt_close(dt); printf("Success.\n"); } } Unix notes; This routine conditionally compiles for Ultrix-32 (4.2BSD)9 and System V. There is also a conditional for the Zilog? Zeus version of Unix. This hasn't been independently checked.>8 Unix implementors are encouraged to read and understand2 this module when developing DECtalk applications.< Unix and System V are trademarks of AT&T Bell Laboratories.#endif#include #include "dectlk.h" U #ifdef unix/* * Unix specific definitions */#include #include #endif #ifdef vms/*" * VMS native specific definitions */,#include /* Status definitions */+#include /* I/O request codes */.#include /* String descriptors */?typedef struct dsc$descriptor_s STRING; /* string descriptor *//*C * The following macro builds a descriptor from an argument string. */#define descrip(text, p) \ ((p)->dsc$a_pointer = text, \$ (p)->dsc$w_length = strlen(text), \$ (p)->dsc$b_dtype = DSC$K_DTYPE_T, \" (p)->dsc$b_class = DSC$K_CLASS_S)#endif #ifdef rt11/*% * RSTS/E native specific definitions */#include #endif #ifdef rsx#include #include #include #include s#include r#define QIO_EFN 1e2static QIOPARM noparm; /* QIO parm (all zero) */#endif r DECTALK * dt_open(name)f!char *name; /* Device name */t/*( * Initialize the DECtalk terminal line. */{  register DECTALK *dt;, register int i; /* Channel search, temp */ #ifdef unixt+ register char *ttname; /* -> stdin name */t #ifdef BSD_42e0 struct sgttyb stty_buffer; /* Terminal flags */#elseA #ifdef UNIX_V11 struct termio stty_buffer; /* Terminal flags */m#endif#endif- extern char *ttyname(); /* Get stdin name */n#endif #ifdef vms STRING dev; #endif #ifdef rt11p char work[30]; extern int $$rsts;^* extern char *E$$NOD; /* Invalid device */( extern char *E$$FAT; /* Fatal error */, extern char *E$$NOC; /* No more channels */#endif #ifdef rsx) extern int $$rsts; /* TRUE if RSTS/E */' extern int $$pos; /* TRUE if P/OS */h) extern int $dsw; /* Dir. status word */T. extern int $$ferr; /* Decus C error value */1 struct lunbuf lunbuf; /* Get lun information */i#endif extern char *calloc();o extern char *malloc();  /*), * Allocate the DECtalk buffer and save the * device name (for debugging). */; if ((dt = (DECTALK *)calloc(sizeof (DECTALK), 1)) == NULL)y return (NULL);.5 if ((dt->device = malloc(strlen(name) + 1)) == NULL)  goto error2;t strcpy(dt->device, name); #ifdef unix . if ((ttname = ttyname(fileno(stdin))) != NULL && strcmp(ttname, name) == 0)y, dt->unit = fileno(stdin); /* stdin */) else if ((dt->unit = open(name, 2)) < 0)f goto error1;y if (!isatty(dt->unit)) {c close(dt->unit); goto error1;N } /*F; * Force the terminal into single-character, no-echo mode.n */ #ifdef BSD_42k5 gtty(dt->unit, &stty_buffer); /* Get current info */r7 gtty(dt->unit, &dt->stty_save); /* For restore, too */ 2 stty_buffer.sg_flags &= ~ECHO; /* Set no echo */7 stty_buffer.sg_flags |= CBREAK; /* Single character */23 stty(dt->unit, &stty_buffer); /* Set temp. mode */l5 signal(SIGALRM, SIG_IGN); /* Ignore timer signals */i#elseg #ifdef UNIX_VB? ioctl(dt->unit, TCGETA, &stty_buffer); /* Get current info */_@ ioctl(dt->unit, TCGETA, &dt->stty_save);/* For restore, too */. stty_buffer.c_iflag = BRKINT | IXON | IXOFF; stty_buffer.c_oflag = 0;5 stty_buffer.c_cflag = B9600 | CS8 | CREAD | CLOCAL; #ifdef zeusv /*t= * The following edit was reported by a customer for a Zylogg5 * "Zeus" port but hasn't been independently tested.  */ stty_buffer.c_lflag = 0101;k#else  stty_buffer.c_lflag = 0;#endif stty_buffer.c_cc[VMIN] = 1;a stty_buffer.c_cc[VTIME] = 2;= ioctl(dt->unit, TCSETA, &stty_buffer); /* Set temp. mode */ #endif#endif#endif #ifdef vms descrip(name, &dev);i8 if (sys$assign(&dev, &dt->unit, 0, NULL) != SS$_NORMAL) goto error1;"#endif #ifdef rt11g if (!$$rsts) {H3 $$ferr = (int) &E$$FAT; /* Illegal function */  goto error1;f } /*i * Search for a free channel. */ for (i = 12; i > 0; i--) { clrxrb(); xrb.xrci = i * 2;" if (rstsys(_POSTN) == NOTOPN) break; }+ if (i <= 0) { /* Fail if all channels */e/ $$ferr = (int) &E$$NOC; /* are in use. */l goto error1;! }' dt->unit = i; /* Save unit number */" /*=7 * On RSTS, the terminal is opened in a special mode: * 1 binary:- * 16 do not abort on CTRL/C or modem hangup"( * 32 terminal service handles XOFF/XON */* sprintf(work, "%s/mo:%d", name, 1+16+32); if (rs_open(i, work, "r") != 0) goto error1;' if ((firqb.fqflag & 0xFF) != TTYHND) {1 $$ferr = (int) &E$$NOD; /* Not a terminal */e rs_close(i); goto error1;I }#endif #ifdef rsx if ($$rsts) {* $$ferr = IE_IFC; /* Not on RSTS/E */ goto error1; } /*+ * We only call fopen() to get a free lun. */. if ((dt->fildes = fopen(name, "rn")) == NULL) goto error1; dt->unit = fileno(dt->fildes); glun(dt->unit, &lunbuf); if ($$pos && lunbuf.g_luna[0] == 'X' && lunbuf.g_luna[1] == 'K') dt->pos_xk = TRUE; else dt->pos_xk = FALSE;) if ((i = qiow(IO_ATT, dt->unit, QIO_EFN,$ NULL, NULL, &noparm)) != IS_SUC) { fclose(dt->fildes); $$ferr = i; goto error1; }#endif /** * Normal exit, initialize other pointers */ dt->link = dt_root; dt_root = dt;3 dt->out_ptr = dt->out_buff; /* Out buffer setup */1 dt->flag = _FLAG_SPEAK; /* Normally speaking */" return (dt); /* Normal exit */3error1: free(dt->device); /* Error, free device */4error2: free((char *) dt); /* and DECTALK buffer */, return ((DECTALK *)NULL); /* Error exit */}*[CHAREST.DTLIB.SRC]DTPEEK.C;1+,| ./_x 4Dh-M 0123KPWO56U抎7+xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION7title dt_peek Test if Character Available from DECtalk0index Test if character available from DECtalksynopsis .s.nf #include  #include "dectlk.h" int dt_peek(dt)& DECTALK *dt; /* Device descriptor */ .s.f description5 Returns TRUE if a character is pending from DECtalk.3 Note that this may be a keypad input character (as4 entered by the user) or part of an escape sequence.6 dt_peek() does not flush pending output. It contains operating-system specific code.note4 This module contains specific code for Unix 4.2BSD.4 The makefile for the library should #define BSD_42.bugs Tested only on VMS.#endif#include #include "dectlk.h"/*5 * Define all DECtalk library globals in this module. */ #ifdef unix#include #ifdef BSD_42#include #include #endifintdt_peek(dt, sec)+register DECTALK *dt; /* DECtalk device *//* * UNIX. */{1 register int incount; /* Count and error code */ #ifdef BSD_42( auto long pending; /* Number pending */#else. register int ecode; /* For error handling */, extern int errno; /* System error value */#endif /* * Anything buffered? */1 if (dt->pend_fc > 0 || dt->in_ptr < dt->in_end)  return (TRUE); #ifdef BSD_42 /* * Works for 4.1 BSD, too./ * Won't work for Unix V7 or System N (N >= 3) */% ioctl(dt->unit, FIONREAD, &pending); return(pending > 0);#else+ dt->in_ptr = dt->in_end = &dt->in_buff[0]; alarm(1); /* Start timeout */$ errno = 0; /* Clear error flag */2 incount = read(dt->unit, dt->in_buff, IN_BUFLEN);' ecode = errno; /* Save error code */! alarm(0); /* Cancel timeout */: if (incount < 0 && ecode == EINTR) /* Did it timeout? */) return (FALSE); /* Return failure */2 if (dt_abort || incount <= 0) /* Other error? */. return (FALSE); /* Return bad failure */$ dt->in_end = &dt->in_buff[incount]; return (TRUE);#endif}#endif #ifdef vms-#include /* System status codes */+#include /* I/O request codes */ typedef struct io_status_block {- short int status; /* I/O status code */- short int term_offset; /* Datum size */1 short int terminator; /* Input terminator *// short int term_size; /* Terminator size */ } IOSTAB;int dt_peek(dt)+register DECTALK *dt; /* DECtalk device *//*$ * VMS: Fill the input buffer, too. */{ register int incount; struct type_ahead { short pending_count; char first_character; char char_reserved; int long_reserved; } type_ahead;( IOSTAB status; /* I/O status block */1 if (dt->pend_fc > 0 || dt->in_ptr < dt->in_end)  return (TRUE);* incount = sys$qiow(1, /* Event flag */ dt->unit, /* Input channel */" IO$_SENSEMODE | IO$M_TYPEAHDCNT," &status, /* I/O status block */ NULL, /* AST block (none) */ 0, /* AST parameter */" &type_ahead, /* P1 - buffer */- sizeof type_ahead, /* P2 - buffer length */ 0, /* P3 - */ NULL, /* P4 - */+ NULL, /* P5 - ignored (prompt buffer) */' 0); /* P6 - ignored (prompt size) */@ return (incount == SS$_NORMAL && type_ahead.pending_count > 0);}#endif #ifdef rt11/* * R S T S / E */#include int dt_peek(dt)+register DECTALK *dt; /* DECtalk device *//*D * RSTS/E: Fill the input buffer, return the next (first) character. */{1 register int incount; /* Count and error code */1 if (dt->pend_fc > 0 || dt->in_ptr < dt->in_end)  return (TRUE); /* * We must refill the buffer */+ dt->in_ptr = dt->in_end = &dt->in_buff[0]; clrxrb();% xrb.xrlen = 4; /* No delimiter */ xrb.xrci = dt->unit * 2; xrb.xrblkm = TTYHND; rstsys(_SPEC); clrxrb(); xrb.xrlen = 3; /* No echo */ xrb.xrci = dt->unit * 2; xrb.xrblkm = TTYHND; rstsys(_SPEC);) incount = rs_read(dt->unit, dt->in_buff, IN_BUFLEN, 0, 0, 0, 8192); if (incount == -(HNGTTY)) return (FALSE); else if (incount <= 0) return (FALSE);$ dt->in_end = &dt->in_buff[incount]; return (TRUE);}#endif #ifdef rsx/*$ * Load in RSX specific information: * cx.h common header& * qiofun.h I/O service function codes. * qioret.h I/O service error and status codes/ * qiottd.h Terminal I/O service bits and bytes) * lunbuf.h Device characteristics buffer */#include #include #include #include #include )#define QIO_EFN 1 /* I/O event flag */)#define MKT_EFN 2 /* Time event flag */=static char gmcbuf[2] = { TC_TBF }; /* get typeahead count */3static QIOPARM gmcparm = { gmcbuf, sizeof gmcbuf };3static int termtable[16]; /* Terminator bitmask */int dt_peek(dt)+register DECTALK *dt; /* DECtalk device *//* * RSX: */{1 register int incount; /* Count and error code */. register char *ip; /* To copy to rsx buff */ int errorcode; /*& * Return buffered character (if any) */1 if (dt->pend_fc > 0 || dt->in_ptr < dt->in_end)  return (TRUE); /* * We must refill the buffer */+ dt->in_ptr = dt->in_end = &dt->in_buff[0]; if (dt->pos_xk) { /*7 * The PRO-350 XK: port is actually pretty simple. */# dt->parm.buffer = dt->in_buff; dt->parm.size = IN_BUFLEN;( dt->parm.p3 = 0; /* No timeout */9 errorcode = qiow(IO_RLB | TF_TMO, dt->unit, QIO_EFN, &dt->iosb, NULL, &dt->parm);( if ((incount = fixiosb(dt)) == 0) { return (FALSE); }( dt->in_end = &dt->in_buff[incount]; return (TRUE); } else { /*( * Check whether anything is in the! * system type-ahead buffer. */0 errorcode = qiow(SF_GMC, dt->unit, QIO_EFN, &dt->iosb, NULL, &gmcparm);3 return (errorcode == IS_SUC && gmcbuf[1] > 0); }} static int fixiosb(dt)+register DECTALK *dt; /* DECtalk device *//*0 * This routine returns the correct input count. * The code is unusual. *) * fixiosb() returns the true byte count. */{ extern int $$ferr;" if (dt->iosb.terminator != NUL) { /*, * Append the terminator to the buffer. */7 dt->in_buff[dt->iosb.count] = dt->iosb.terminator; dt->iosb.count++; } if (dt_abort || dt->iosb.status == IE_ABO || dt->iosb.count == 0) {& return (0); /* Read aborted */ }# else if (dt->iosb.status != IS_SUC& && dt->iosb.status != IS_TMO) { $$ferr = dt->iosb.status;# return (0); /* I/O error */ } return (dt->iosb.count);}#endif*[CHAREST.DTLIB.SRC]DTPESC.C;1+,~ . /_x 4B -M 0123KPWO 56![=Q7@ 0+xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION'title dt_pesc Transmit Escape Sequence index Transmit escape sequencesynopsis .s.nf #include  #include "dectlk.h" dt_pesc(dt, seq)& DECTALK *dt; /* Device descriptor */& SEQUENCE *seq; /* What to transmit */ .s.f description0 Compile an appropriate escape sequence from the0 parameter buffer. This is similar to putchar()0 except when seq->state is ESC, CSI, or DCS. In3 these cases, the function generates an appropriate4 sequence from the passed data structure. dt_pesc()0 calls the user-supplied dt_put() to output each character.1 C1 control sequences are sent in their eight-bit/ form if _FLAG_EIGHTBIT is set in dt->flag. If/ this bit is off, they are sent in their X6 form. If the application program sets _FLAG_EIGHTBIT. it must also ensure that the operating system, transmits eight data bits, and that DECtalk was setup as HOST FORMAT EIGHT. No value is returned.#endif#include #include "dectlk.h"dt_pesc(dt, seq)+register DECTALK *dt; /* Dectalk device */.register SEQUENCE *seq; /* Sequence buffer *//*B * Output the character (in seq->state) and maybe a sequence, too. */{8 register unsigned i; /* Index into inter[], param[]. */2 unsigned max; /* Max for inter[] and param[]. */#ifdef DT_DEBUG if (dt_debug) { printf("put: \""); if (isatty(fileno(stdout))) fflush(stdout); }#endif i = seq->state;% if ((dt->flag & _FLAG_EIGHTBIT) == 0 && i >= 0x80 && i <= 0x9F) { /*i4 * Output is in 7-bit mode and the character is, * a C1 control character. Convert it. */ dt_put(dt, ESC);M dt_put(dt, i - 0x40); } else {t /*d3 * Not the special case; output the character.d */ dt_put(dt, i);  } switch (i) { case ESC: case CSI: case DCS: /*w: * Here is a sequence. Output all of its components. *n * First, the parameters. * i counts the parameters& * max stores the parameter max.- * val working copy of parameter value.C */ if (seq->private != 0)o dt_put(dt, seq->private);b max = seq->param[0];w if (max > SEQ_PARMAX)- max = SEQ_PARMAX; /* Too many, use limit */ ! for (i = 1; i <= max; i++) {e if (i > 1) dt_put(dt, ';'); if (seq->param[i] != 0) intout(dt, seq->param[i]); } /*N * Output intermediates.e * i counts intermediates.( * max stores the number to output. */ max = seq->inter[0];n if (max > SEQ_INTMAX)- max = SEQ_INTMAX; /* Too many, use limit */d for (i = 1; i <= max;) {d dt_put(dt, seq->inter[i++]); }4 dt_put(dt, seq->final); /* Output the final */ break; default: break;l }#ifdef DT_DEBUGl if (dt_debug) printf("\"\n");#endif}n t#ifndef INT_32 #ifdef vax#define INT_32#endif #ifdef M68000 #define INT_32#endif#endifstatic unsigned power10[] =d{ /* * Powers of 10 for intout */l #ifdef INT_32s 10000000,n 1000000,y 100000, #endif 10000, 1000, 100, 10, 1,};8#define NPOWERS ((sizeof power10) / (sizeof (unsigned)))staticintout(dt, value)l$DECTALK *dt; /* DECtalk device */0register unsigned value; /* Value to convert *//*; * Convert an unsigned number to ASCII and call dt_put() on ; * each character. Note, as implemented here, a zero value  * does not output anything. */A{I register unsigned *power; int out_char; int nonzero;n. power = power10; /* Pointer to power table */2 nonzero = FALSE; /* Don't output leading zeros */ do { /*n1 * Loop until all places except digits place, * have been done.c */4 for (out_char = 0; value >= *power; out_char++)) value -= *power; /* Subtract a power */e# if (nonzero || out_char > 0) {m) nonzero = TRUE; /* Not leading zero */i dt_put(dt, out_char + '0');H }' } while (++power < &power10[NPOWERS]);w} *[CHAREST.DTLIB.SRC]DTPHON.C;1+, ./_x 4;V-M 0123KPWO56Y,7k+xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION#title dt_phone Send a Phone Messageindex Send a phone messagesynopsis .s.nf #include  #include "dectlk.h" int dt_phone(dt, p3, p4)& DECTALK *dt; /* Device descriptor */$ int p3; /* P3_PH_xxxx parameter */ int p4; /* timeout or rings */ .s.f description3 This routine (which may be implemented as a macro)6 sends a DECtalk phone message (i.e., the p2 parameter is P2_PHONE).6 p3 and p4 should be given as -1 if no parameter is to be sent.0 It then reads the status reply and returns TRUE/ if the r1 and r2 parameters are R1_DECTALK and0 R2_PHONE respectively. The application program4 should then test for offhook/onhook as appropriate.; Returns TRUE if successful. If FALSE, something is funny.#endif#include #include "dectlk.h"#ifdef dt_phone#undef dt_phone#endifintdt_phone(dt, p3, p4).register DECTALK *dt; /* Device descriptor */ int p3; int p4;/* * Send a phone message. */{5 return (dt_msg(dt, P2_PHONE, p3, p4, R2_PHONE, -1));}*[CHAREST.DTLIB.SRC]DTPTES.C;1+, ./_x 440-M 0123KPWO5637+xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATIONtitle dt_ptest Test Phone Replyindex Test phone replysynopsis .s.nf #include  #include "dectlk.h" int dt_ptest(dt, r3)& DECTALK *dt; /* Device descriptor */$ int r3; /* R3_PH_xxxx parameter */ .s.f description3 This routine (which may be implemented as a macro)4 is used to test the result of a dt_phone() message.* The parameter is a R3_PH_... reply value.2 It returns TRUE if the current reply is a DECtalk- phone reply with the specified R3 parameter.#endif#include #include "dectlk.h"#ifdef dt_ptest#undef dt_ptest#endifintdt_ptest(dt, r3).register DECTALK *dt; /* Device descriptor */ int r3;/* * Test a phone message. */{$ return (dt_test(dt, R2_PHONE, r3));}*[CHAREST.DTLIB.SRC]DTPUT.C;1+, ./_x 4@-M 0123KPWO56œ7`+xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION,title dt_put Write one Character to DECtalk&index Write one character to DECtalksynopsis .s.nf #include  #include "dectlk.h" dt_put(dt, c)& DECTALK *dt; /* Device descriptor */! int c; /* Character to write */ .s.f description7 One character is written to the DECtalk terminal line. No value is returned.5 If DT_DEBUG is #defined when the library is compiled0 and the global dt_debug is set non-zero (by the$ application program), the character1 written is logged to the standard output device.#endif#include #include "dectlk.h" #ifdef dt_put #undef dt_put#endif dt_put(dt, c).register DECTALK *dt; /* Device descriptor */*register int c; /* Character to write */{ extern int dt_debug; dt_ioput(dt, c);#ifdef DT_DEBUG@ if (dt_debug != 0 && c != NUL) /* Don't bother logging NUL's */ dt_dchar(c, stdout);#endif}*[CHAREST.DTLIB.SRC]DTREAD.C;1+, ./_x 4<-M 0123KPWO56a hZ7@+xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION)title dt_read Read Sequence or Character"index Read sequence or charactersynopsis .s.nf #include  #include "dectlk.h" int dt_read(dt, sec)& DECTALK *dt; /* Device descriptor */$ char sec; /* O.S. timeout value */ .s.f description5 Read an escape sequence or keypad character. Ignore1 any characters between the DECtalk final and the1 string terminator. Return the character read or the sequence introducer.#endif#include #include "dectlk.h"intdt_read(dt, sec)+register DECTALK *dt; /* Dectalk device */)int sec; /* Operating system timeout */{ register int code; register int i; /*9 * Read another sequence (or continue reading this one).< * Copy the sequence read into the working "reply" buffer.7 * Note, this code is not quite general enough for all5 * escape sequence parsing. Specifically, it cannot5 * properly deal with C0 control characters embedded6 * inside of escape sequences (as is necessary if the7 * operating system cannot process XOFF/XON controls). */ dt->seq.state = 0;1again: dt->reply.state = code = dt_gesc(dt, sec); switch (code) { case CAN: case SUB: goto again; case ESC: case CSI: case DCS:% dt->reply.final = dt->seq.final;) dt->reply.private = dt->seq.private;, for (i = 0; i <= dt->seq.inter[0]; ++i)( dt->reply.inter[i] = dt->seq.inter[i];, for (i = 0; i <= dt->seq.param[0]; ++i)( dt->reply.param[i] = dt->seq.param[i]; break; default:* dt->reply.final = dt->reply.private =1 dt->reply.inter[0] = dt->reply.param[0] = 0; break; } if (dt->reply.state == DCS) { /*, * Ignore text between DCS final and ST */ dt->seq.state = 0; do { code = dt_gesc(dt, 1);' } while (code > 0 && code < 0x80); } return (dt->reply.state);}*[CHAREST.DTLIB.SRC]DTRESE.C;1+, ./_x 41-M 0123KPWO56)87 +xL89ɊʑG_xHJP]/~ DTLIB.BCK M [CHAREST.DTLIB.SRC]DTRESE.C;11y /*)LIBRARY*/#ifdef DOCUMENTATION!title dt_reset DECtalk Soft Resetindex DECtalk soft resetsynopsis .s.nf #include  #include "dectlk.h" dt_reset(dt)& DECTALK *dt; /* Device descriptor */ .s.f description% Send a "soft reset" escape sequence. No errors are possible.#endif#include #include "dectlk.h"static SEQUENCE soft_reset = {" CSI, 'p', 0, { 0 }, { 1, '!' }}; dt_reset(dt)register DECTALK *dt;/*1 * dt_reset() sends a soft-reset escape sequence. */{ dt_pesc(dt, &soft_reset);. dt->flag |= _FLAG_SPEAK; /* Speaking now */( dt->timeout = 0; /* No timeout now */} *[CHAREST.DTLIB.SRC]DTSAVE.C;1+, ./_x 4;-M 0123KPWO56ȫ7< ,xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION#title dt_save Save User Type-aheadindex Save user type-aheadsynopsis .s.nf #include  #include "dectlk.h" int dt_save(dt, c)& DECTALK *dt; /* Device descriptor */! char c; /* Character to save */ .s.f description+ If c is a keypad character, save it in the/ type-ahead buffer and return TRUE, else return FALSE.. If the current reply is a timeout and nothing- is stored in the type-ahead buffer, save 'T'/ and clear the timeout flag. This is necessary) as a timeout sequence may be returned in( the middle of a message/reply sequence.+ If the current reply is a wink, save it in the type-ahead buffer.1 This routine should not be called by application programs.#endif#include #include "dectlk.h"intdt_save(dt, c)+register DECTALK *dt; /* Dectalk device */!int c; /* Character to test */{* register int timeout; /* Current value */2 if (!dt_isvalid(c)) { /* Not a keypad button? */+ if (dt_test(dt, R2_PHONE, R3_PH_WINK)) c = 'W';; else if (!dt_istimeout(dt)) /* If it isn't timeout, */) return (FALSE); /* it's not for us. */$ else { /* Timeout is funny */ /*. * Ignore timeout if timer is set to zero or3 * something is already in the type-ahead buffer. */, timeout = dt->timeout; /* Get old value */% dt->timeout = 0; /* Clear timer */# if (timeout == 0 || dt_iskey(dt))( return (TRUE); /* Toss it away */& c = 'T'; /* Save it in typeahead */ } }8 if (dt->pend_fc < PEND_SIZE) { /* Save it if there's */, dt->pend_fc++; /* enough room, else */4 dt->pend[dt->pend_fp] = c; /* throw it away. */$ if (++dt->pend_fp >= PEND_SIZE) dt->pend_fp = 0; } return (TRUE);}*[CHAREST.DTLIB.SRC]DTSPLI.C;1+, ./_x 4A-M 0123KPWO56~7@b0,xL89ɊʑG_xHJ  /*)LIBRARY*/#ifdef DOCUMENTATION%title dt_splice Manage Local Terminalindex Manage Local Terminaltsynopsis .s.nf #include t #include "dectlk.h" dt_splice(dt, flag)& DECTALK *dt; /* Device descriptor */ int flag; /* Required state */ .s.f descriptioni+ dt_splice() allows control over a terminal0 connected to DECtalk's "local" port. Note that0 the terminal must correctly process ANSI escape- sequences. Specifically, it must ignore anyf, escape sequence that it doesn't understand.* The flag parameter may have the following (bit-encoded) values: .s.lm +16.njt/ .i-16;SPLICE__SPEAK#####Speak subsequent text,l2 if set. Do not speak text if not set. Initially zero.. .i-16;_SPLICE__LOG#######Text sent to DECtalk/ is sent (in raw mode) to the local terminal if  set. Initially not set.c1 .i-16;_SPLICE__TERM######Text typed on the locale/ terminal is sent to DECtalk if set. Initiallyq not set.e .s.lm-16.j ; The bits would normally be set and cleared in combination.. For example:a .s.nf! dt_splice(dt, SPLICE_SPEAK);e .s.fe9 Speak text, don't log it, ignore text typed on the host.n .s.nf- dt_splice(dt, SPLICE_LOG | SPLICE_TERM);i .s.fz7 Stop speaking text, transmit text from/to the attached terminal.#endif#include #include "dectlk.h"tdt_splice(dt, flag)_register DECTALK *dt; register int flag; /* * Manage line-splice modes. */{t- splice(dt, flag & SPLICE_SPEAK, _FLAG_SPEAK,b P2_SPEAK, 1);n+ splice(dt, flag & SPLICE_LOG, _FLAG_LOG,d P2_LOG, LOG_RAWHOST);e, splice(dt, flag & SPLICE_TERM, _FLAG_TERM, P2_TERMINAL, TERM_HOST);} staticsplice(dt, flag, bit, p2, p3))register DECTALK *dt;i"int flag; /* TRUE to set bit */$int bit; /* dt->flag bit to do */int p2, p3; /* For DCS */k/*A * Do the dt_splice() work. If dt->flag doesn't agree with flag,g! * send the appropriate dt_dcs().. */{t. if (((dt->flag & bit) != 0) != (flag != 0)) { /*S * Change needed  */ if (flag != 0)d dt->flag |= bit; else {l dt->flag &= ~bit;_ } if (p2 == P2_SPEAK)+ dt_dcs(dt, P2_SPEAK, (flag) ? 1 : 0, -1);, else {)7 dt_dcs(dt, p2, p3, (flag) ? P4_BITSET : P4_BITCLEAR);  } }} *[CHAREST.DTLIB.SRC]DTST.C;1+, ./_x 47-M 0123KPWO56r@ 7Q,xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION#title dt_st Send String Terminatorindex Send String Terminatorsynopsis .s.nf #include  #include "dectlk.h" int dt_st(dt)& DECTALK *dt; /* Device descriptor */ .s.f description3 This routine sends a String Terminator to DECtalk.7 This is needed to terminate phonemic text or telephone dial commands.3 A phonemic text sequence would be sent as follows: .s.nf dt_cmd(dt, p2, p3); dt_talk(dt, "hh'ehlow."); dt_st(dt); .s.f#endif#include #include "dectlk.h"%static SEQUENCE string_terminator = { ST}; dt_st(dt)'DECTALK *dt; /* Device descriptor *//* * Send a string terminator */{! dt_pesc(dt, &string_terminator);}*[CHAREST.DTLIB.SRC]DTSYNC.C;1+, ./_x 4;-M 0123KPWO56XBoP/7@km,xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION'title dt_sync Synchronize with DECtalk index Synchronize with DECtalksynopsis .s.nf #include  #include "dectlk.h" int dt_sync(dt)& DECTALK *dt; /* Device descriptor */ .s.f description2 The program delays until all text sent to DECtalk has been spoken.; Returns TRUE if successful. If FALSE, something is funny.#endif#include #include "dectlk.h"int dt_sync(dt).register DECTALK *dt; /* Device descriptor *//*+ * Synchronize DECtalk and the application. */{0 dt_dcs(dt, P2_SYNC, -1, -1); /* Synchronize */- dt->flag |= _FLAG_SPEAK; /* Now speaking */; return (dt_msg(dt, P2_IX_QUERY, -1, -1, R2_IX_QUERY, -1));}*[CHAREST.DTLIB.SRC]DTTALK.C;1+, ./_x 4/-M 0123KPWO56eԨ7,xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION%title dt_talk Speak One Line of Textlindex Speak one line of textsynopsis .s.nf #include o #include "dectlk.h" dt_talk(dt, text)& DECTALK *dt; /* Device descriptor */ char *text; /* What to say */ .s.fm description / This function sends a line of text to DECtalk.t- dt_talk(dt, NULL) flushes DECtalk by sendingf a vertical-tab sequence.e#endif#include #include "dectlk.h"d!static char vtline[] = { VT, 0 };cdt_talk(dt, text)n.register DECTALK *dt; /* Device descriptor */*register char *text; /* Text pointer */{  if (text == NULL) text = vtline;- while (*text != 0)d dt_put(dt, *text++);- dt_eol(dt);} *[CHAREST.DTLIB.SRC]DTTEST.C;1+, ./_x 44h-M 0123KPWO56(7@t,xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION#title dt_test Test a DECtalk Replyxindex Test a DECtalk replysynopsis .s.nf #include o #include "dectlk.h" int dt_test(dt, r2, r3)& DECTALK *dt; /* Device descriptor */ int r2; /* R2_xxx parameter */ int r3; /* R3_xxx parameter */ .s.fs descriptionx1 This routine checks the last reply received fromb3 DECtalk against the model. r3 is -1 to ignore it.i2 It returns TRUE if the reply is a properly-parsed1 DECtalk reply sequence, or FALSE on any failure.i#endif#include #include "dectlk.h"cintedt_test(dt, r2, r3) .register DECTALK *dt; /* Device descriptor */ int r2;t int r3;/*4 * Test the current returned sequence for the proper) * DECtalk reply. r3 is -1 to ignore it.E */Z{ if (dt->reply.state == DCSr& && dt->reply.final == DCS_F_DECTALK && dt->reply.inter[0] == 0  && dt->reply.private == 0) {f) if (dt->reply.param[1] == R1_DECTALKC! && dt->reply.param[2] == r2 0 && (r3 == -1 || dt->reply.param[3] == r3)) return (TRUE); } return (FALSE);}X c*[CHAREST.DTLIB.SRC]DTTIME.C;1+, ./_x 46-M 0123KPWO5687,xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION1title dt_timeout Enable or Disable Keypad Timeout(index Enable or disable keypad timeoutsynopsis .s.nf #include  #include "dectlk.h" int dt_timeout(dt, sec)& DECTALK *dt; /* Device descriptor */# int sec; /* Timeout in seconds */ .s.f description0 If sec is non-zero, timeouts are being enabled;" if zero, they are being disabled.4 Enable keypad timeouts if sec is non-zero and there2 is no data in the type-ahead buffer (and timeouts are not already enabled).6 Disable timeouts if they are enabled and sec is zero,1 or any data is in the type-ahead buffer (even if sec is non-zero).3 Before enabling timeouts, DECtalk is synchronized.5 Returns TRUE if successful. If FALSE, the telephone may have been hung up.#endif#include #include "dectlk.h"intdt_timeout(dt, sec).register DECTALK *dt; /* Device descriptor *//register int sec; /* Timeout in sec seconds *//*6 * Enable or disable timeout. No errors are possible.6 * Note that timeout(dt, 15) looks at the state of the4 * type-ahead buffer before deciding whether to turn& * timeouts on, off, or to do nothing. */{& if (sec != 0) { /* If enabling, */2 if (dt_iskey(dt)) /* Disable if typeahead */ sec = 0;+ if (sec != 0) { /* Still enabling? */% dt_sync(dt); /* Synchronize and */' if (dt_iskey(dt)) /* Check again. */ sec = 0; } }0 if (dt->timeout == sec) /* Don't set to the */& return (TRUE); /* same value */" dt_phone(dt, P3_PH_TIMEOUT, sec); dt->timeout = sec;% if (dt_onhook(dt) || dt_offhook(dt)) return (TRUE); return (FALSE);}*[CHAREST.DTLIB.SRC]DTTONE.C;1+, ./_x 45-M 0123KPWO56H_7m-xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATIONtitle dt_tone Send DTMF Tonesindex Send DTMF tonessynopsis .s.nf #include  #include "dectlk.h" int dt_tone(dt, msg)& DECTALK *dt; /* Device descriptor */ char *msg; /* Announcement */ .s.f description1 This routine sends the msg text string as a tone0 dialing sequence. If the telephone was on-hook. when dttone() was called, it will be returned. to the on-hook condition. Note, this routine/ may not work to your satisfaction in countries. which require automatic announcement messages1 on automatically dialed calls. See your DECtalk* programmer's manual for more information.3 For message text may contain any valid touch-tone2 characters ("0123456789*#ABCD") or the characters2 '!' (for a one second delay) or the '^' for a 2504 millisecond switch-hook flash. All other characters are ignored.3 Note that the telephone will not be hung up before5 dialing if it is offhook when the command is issued.#endif#include #include "dectlk.h"intdt_tone(dt, message).register DECTALK *dt; /* Device descriptor */$char *message; /* Announcement *//* * Send tones. */{ register int state; register int code; dt_phone(dt, -1, -1); state = dt_onhook(dt);" dt_cmd(dt, P2_PHONE, P3_PH_TONE); dt_talk(dt, message); dt_st(dt); do { code = dt_read(dt, 30);+ } while (code == ST || dt_save(dt, code)); if (state) dt_hangup(dt);}*[CHAREST.DTLIB.SRC]DTTRAP.C;1+, ./_x 48-M 0123KPWO56OD47k-xL89ɊʑG_xHJ  /*)LIBRARY*/#ifdef DOCUMENTATION'title dt_trap Trap Interrupts index Trap Interruptssynopsis .s.nf #include  #include "dectlk.h" dt_trap() .s.f description/ Set the global dt_abort flag if the user types- at the command terminal. (On Unix,. this is interpreted as catching the INTERRUPT/ signal, which is not necessarily , and- which may be generated by running the "kill" system program., When the interrupt is received, pending I/O/ is cancelled (on those operating systems where this makes sense).8 If dt_abort is set TRUE when the interrupt is received, the program aborts. No error is returned.#endif#include #include "dectlk.h" #ifdef unix#include staticcatch(){ if (dt_abort) _exit(2); dt_abort = TRUE;} dt_trap()/* * Trap CTRL/C interrupts. */{ signal(SIGINT, catch); signal(SIGTERM, catch);}#endif #ifdef vms#include #include staticcatch(){ register DECTALK *dt; if (dt_abort) _exit(SS$_ABORT); dt_abort = TRUE;. for (dt = dt_root; dt != NULL; dt = dt->link) sys$cancel(dt->unit);} dt_trap()/* * Trap CTRL/C interrupts. */{ signal(SIGINT, catch);}#endif #ifdef rsx#include #include #include #include #define QIO_EFN 1staticcatch(){ register DECTALK *dt; astset(); /* AST entry */ if (dt_abort) $$fail(); dt_abort = TRUE; /* * Kill all pending DECtalk I/O */0 for (dt = dt_root; dt != NULL; dt = dt->link) {$ qiow(IO_KIL, dt->unit, QIO_EFN, &dt->iosb, NULL, &dt->parm); } astx(1); /* AST exit */},static QIOPARM astparm = { NULL, 0, catch }; dt_trap()/* * Trap CTRL/C interrupts. */{& qiow(IO_ATA, fileno(stderr), QIO_EFN, NULL, NULL, &astparm);}#endif #ifdef rt11staticcatch()/*6 * Executed by the operating system if an interrupt is * detected. */{ if (dt_abort) $$fail(); dt_abort = TRUE;} dt_trap()/* * Trap CTRL/C interrupts. */{ setcc(catch);}#endif*[CHAREST.DTLIB.SRC]DTVERS.C;1+, ./_x 40-M 0123KPWO56~7i;-xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION.title dt_version Return DECtalk Device Version%index Return DECtalk device versionsynopsis .s.nf #include  #include "dectlk.h" int dt_version(dt)& DECTALK *dt; /* Device descriptor */ .s.f description- Return the DECtalk device conformance level.0 This routine accepts DTC01 (ID code 19) as well- as DTC03 units using the new codes 81 or 82.& You must have called dt_init() first.#endif#include #include "dectlk.h"intdt_version(dt)register DECTALK *dt;/* * Return version number. */{ return (dt->version);} *[CHAREST.DTLIB.SRC]DTVISI.C;1+, ./_x 46P-M 0123KPWO56Am17 Y-xL89ɊʑG_xHJ  /*)LIBRARY*/#ifdef DOCUMENTATION0title dt_visible Generate Visible Representation'index Generate Visible Representationsynopsis .s.nf$ char work[12]; /* Output buffer */ char * dt_visible(c, work) int c; /* Character to dump */! char work[]; /* Work buffer */ .s.f description0 A visible Ascii representation of the character0 is stored in the work buffer. A pointer to the& end of the output string is returned.1 Note that this routine is independent of DECtalk5 definitions (except that it knows about the DT_ERROR and DT_TIMEOUT error codes).4 The printible Multinational letters (Hex 0xA0-0xFE)/ are considered "visible Ascii" (note that this% includes a few currently undefined).#endif#include #include "dectlk.h"char *dt_visible(c, buffer),register int c; /* Character to convert */6register char *buffer; /* Where to store conversion *//*$ * Make a character "visible" ASCII.( * Return a pointer to the trailing EOS. */{ register int flag; switch (c) { case NUL: strcpy(buffer, ""); break; case DT_ERROR: strcpy(buffer, ""); break; case DT_TIMEOUT:! strcpy(buffer, ""); break; case ESC: strcpy(buffer, ""); break; case DCS: strcpy(buffer, ""); break; case CSI: strcpy(buffer, ""); break; case ST: strcpy(buffer, ""); break; default: c &= 0xFF;5 if (c >= 0xA0 && c <= 0xFE) /* Multinational */& *buffer++ = c; /* and printable */ else { flag = (c >= 0x7F. || (c < ' ' && c != '\n' && c != '\r')); if (flag) *buffer++ = '<'; if ((c &= 0xFF) >= 0x80) { c -= 0x80; *buffer++ = '~'; } if (flag && c < ' ') { *buffer++ = '^'; *buffer++ = c + 64; }) else if (flag || c == '\n' || c >= ' ') *buffer++ = c; if (flag) *buffer++ = '>'; } *buffer = EOS; return (buffer); }" return (buffer + strlen(buffer));}*[CHAREST.DTLIB.SRC]DTWINK.C;1+, ./_x 49-M 0123KPWO56}揇7v-xL89ɊʑG_xHJ /*)LIBRARY*/#ifdef DOCUMENTATION6title dt_wink Enable/disable Telephone Wink Detection/index Enable/disable Telephone Wink Detectionsynopsis .s.nf #include  #include "dectlk.h" int dt_wink(dt, flag)& DECTALK *dt; /* Device descriptor */ int flag; /* Enable code */ .s.f description/ Enable wink detection if the flag is non-zero. Disable it if zero.5 Returns TRUE if successful. If FALSE, the telephone may have been hung up.0 When enabled in wink mode, DECtalk will send an/ asychronous "wink detected" escape sequence if0 the telephone central office interrupts voltage3 on the telephone line. In many telephone offices,8 this indicates that the calling party has disconnected.6 Note: not all telephone central offices provide wink,! and it is not always detectable.7 You should not enable wink detection immediately after9 answering the phone, but rather should wait for a second or two.#endif#include #include "dectlk.h"intdt_wink(dt, enable)register DECTALK *dt; int enable;/** * Enable or disable the telephone keypad. */{ dt_phone(dt,/ (enable) ? P3_PH_WINK : P3_PH_NOWINK, -1); if (dt_offhook(dt)) return (TRUE); return (FALSE);}*[CHAREST.DTLIB.SRC]HELLO.C;1+, ./_x 4*-M 0123KPWO56t7p-xL89ɊʑG_xHJ/*)BUILD $(INCLUDE) = { dectlk.h }% $(RTLIB) = { dtlib,c:rstslb,c:clib }' $(RXLIB) = { dtlib/lb,c:cx/lb,c:c/lb }*/#include #include "dectlk.h" #ifdef vmsextern int errno;#define IO_ERROR errno#endif #ifdef unix#define IO_ERROR 1#endif DECTALK *dt;main(argc, argv) int argc;char *argv[];{ char *dev; dev = "ttg7:"; if (argc > 1) dev = argv[1];# if ((dt = dt_open(dev)) == NULL) { perror(dev);$ printf("Can't open DECtalk\n"); exit(IO_ERROR); }" dt_debug = TRUE; /* Log text */' dt_trap(); /* CTRL/C trap enabled */ printf("calling init\n"); if (!dt_init(dt))( printf("Can't initiate DECtalk\n"); else { printf("Initialized\n");* dt_dcs(dt, P2_MODE, MODE_SQUARE, -1);! dt_talk(dt, "Hello world."); dt_sync(dt);' dt_dump("after sync", &dt->reply); dt_close(dt); printf("Success.\n"); }}!*[CHAREST.DTLIB.SRC]MAKEFILE.TXT;1+, ./_x 4BN-M 0123KPWO56K7 )xL89ɊʑG_xHJ #;# Build the DECtalk library. Note: Edit the CFLAGS line to # CFLAGS = -OB# if you aren't on Unix 4.2 BSD (code checks for this in dtioge.c)#&# make -f dtlib.mak makes the library5# make -f dtlib.mak demo makes the demo program, too#CFLAGS = -O -DBSD_427dtlib.a : dtansw.o dtclos.o dtcmd.o dtdcha.o dtdcs.o \ dtdial.o dtdrai.o dtdump.o \% dteol.o dtgesc.o dtget.o dthang.o \' dtinit.o dtinke.o dtioge.o dtiopu.o \' dtiske.o dtisti.o dtisva.o dtkeyp.o \& dtmsg.o dtoffh.o dtonho.o dtopen.o \/ dtpeek.o dtpesc.o dtphon.o dtptes.o dtput.o \m7 dtread.o dtrese.o dtsave.o dtspli.o dtst.o dtsync.o \L0 dttalk.o dttest.o dttime.o dttone.o dttrap.o \ dtvisi.o ar rv dtlib.a $?i ranlib dtlib.aTdemo: demo.o dtlib.aC cc demo.o dtlib.a mv a.out demodemo.o: demo.c dectlk.hdtansw.o : dtansw.c dectlk.hdtclos.o : dtclos.c dectlk.hdtcmd.o : dtcmd.c dectlk.hdtdcha.o : dtdcha.c dectlk.hdtdcs.o : dtdcs.c dectlk.hdtdial.o : dtdial.c dectlk.hdtdrai.o : dtdrai.c dectlk.hdtdump.o : dtdump.c dectlk.hdteol.o : dteol.c dectlk.hdtgesc.o : dtgesc.c dectlk.hdtget.o : dtget.c dectlk.hdthang.o : dthang.c dectlk.hdtinit.o : dtinit.c dectlk.hdtinke.o : dtinke.c dectlk.hdtioge.o : dtioge.c dectlk.hdtiopu.o : dtiopu.c dectlk.hdtiske.o : dtiske.c dectlk.hdtisti.o : dtisti.c dectlk.hdtisva.o : dtisva.c dectlk.hdtkeyp.o : dtkeyp.c dectlk.hdtmsg.o : dtmsg.c dectlk.hdtoffh.o : dtoffh.c dectlk.hdtonho.o : dtonho.c dectlk.hdtopen.o : dtopen.c dectlk.hdtpeek.o : dtpeek.c dectlk.hdtpesc.o : dtpesc.c dectlk.hdtphon.o : dtphon.c dectlk.hdtptes.o : dtptes.c dectlk.hdtput.o : dtput.c dectlk.hdtread.o : dtread.c dectlk.hdtrese.o : dtrese.c dectlk.hdtsave.o : dtsave.c dectlk.hdtspli.o : dtspli.c dectlk.hdtst.o : dtst.c dectlk.hdtsync.o : dtsync.c dectlk.hdttalk.o : dttalk.c dectlk.hdttest.o : dttest.c dectlk.hdttime.o : dttime.c dectlk.hdttone.o : dttone.c dectlk.hdttrap.o : dttrap.c dectlk.hdtvisi.o : dtvisi.c dectlk.h*[CHAREST.DTLIB.SRC]MAKLIB.COM;1+, ./_x 4=-M 0123KPWO5607@I xL89ɊʑG_xHJ$!9$! The build utility creates command files to compile the8$! DECtalk library. If you do not have build installed,7$! and haven't added or removed files from the library,=$! you may comment out the next three lines without problems.$!2$ build -x vaxnative -l vdtlib.olb *.c >vdtlib.com0$ build -x vaxrsx -l xdtlib.olb *.c >xdtlib.com0$ build -x rstsrt -l dtlib.obj *.c >rdtlib.cmd$*[CHAREST.DTLIB.SRC]NEWMAKEFILE.TXT;1+, . /_x 4M -M 0123KPWO 56`7 g'xL89ɊʑG_xHJMFrom: RHEA::DECWRL::"kjd@monet.berkeley.edu" "Kevin Dunlap" 31-JAN-1986 00:39To: minow%rex.dec@decwrlSubj: DECTALK libraryEReceived: from DECWRL by DEC-RHEA with SMTP; Thu, 30 Jan 86 21:38-PSTDReceived: from monet.berkeley.edu by decwrl.DEC.COM (4.22.01/4.7.34)( id AA28607; Thu, 30 Jan 86 21:36:09 pst*Received: by monet.berkeley.edu (5.44/1.8)( id AA06392; Thu, 30 Jan 86 21:34:09 PST"Date: 30 Jan 86 21:34:06 PST (Thu)3Message-Id: <8601310534.AA06392@monet.berkeley.edu>Hi,7I thought you would like to know that I happen to bringByour DECtalk library out here to UCB and compiled it under 4.3bsd.?Or at least on the system that is closest to what the tape will%be when it gets distributed by march.@Everything compiled with out a hitch execpt for where time.h was:included in dtioge.c. This is where the if def BSD_42 is.?We have moved time.h to sys, or maybe I should say back to sys.7The version type of Unix is in /usr/include/sys/param.h?if you include this will define the unix versionAso the person compileing doesn't have to define the version type.6Also, you might be intrested in the attached makefile.5This is a little less combersum then the one you had.CIf nobody responds to your posting to the Ultrix notes file, let meFknow. The problem with 8 bit characters is not a problem with decvax,Bbut one with Unix. The 8th bit in Unix is used for special thingsCin Unix and supporting the 8 bit character set is not an easy task.GI belive thaJ-~ DTLIB.BCK M $[CHAREST.DTLIB.SRC]NEWMAKEFILE.TXT;1M t there is funding in europe to do the software enginerringDto support international character set. But the group has not gotten started yet.-Kevin--------------#;# Build the DECtalk library. Note: Edit the CFLAGS line to # CFLAGS = -OB# if you aren't on Unix 4.2 BSD (code checks for this in dtioge.c)#&# make -f dtlib.mak makes the library5# make -f dtlib.mak demo makes the demo program, too#DESTDIR=CFLAGS = -O -DBSD_42INCPATH=LFLAGS= LIBS=# The program itself#PROG= dtlib.a # Sources#2SRCS= dtansw.c dtclos.c dtcmd.c dtdcha.c dtdcs.c \ dtdial.c dtdrai.c dtdump.c \$ dteol.c dtgesc.c dtget.c dthang.c \& dtinit.c dtinke.c dtioge.c dtiopu.c \& dtiske.c dtisti.c dtisva.c dtkeyp.c \% dtmsg.c dtoffh.c dtonho.c dtopen.c \. dtpeek.c dtpesc.c dtphon.c dtptes.c dtput.c \6 dtread.c dtrese.c dtsave.c dtspli.c dtst.c dtsync.c \/ dttalk.c dttest.c dttime.c dttone.c dttrap.c \ dtvisi.c # Objects#2OBJS= dtansw.o dtclos.o dtcmd.o dtdcha.o dtdcs.o \ dtdial.o dtdrai.o dtdump.o \$ dteol.o dtgesc.o dtget.o dthang.o \& dtinit.o dtinke.o dtioge.o dtiopu.o \& dtiske.o dtisti.o dtisva.o dtkeyp.o \% dtmsg.o dtoffh.o dtonho.o dtopen.o \. dtpeek.o dtpesc.o dtphon.o dtptes.o dtput.o \6 dtread.o dtrese.o dtsave.o dtspli.o dtst.o dtsync.o \/ dttalk.o dttest.o dttime.o dttone.o dttrap.o \ dtvisi.o# Header files#HDRS= dectlk.h${PROG}: ${OBJS} ${HDRS} ar rv dtlib.a ${OBJS} ranlib dtlib.a${OBJS}: cc ${CFLAGS} ${INCPATH} -c $*.cdemo: demo.o dtlib.a cc demo.o dtlib.a mv a.out demoinstall: ${PROG}- install ${PROG} ${DESTDIR}/usr/local/${PROG}clean:@ rm -f a.out core errs makefile.bak Makefile.bak ${OBJS} ${PROG}lint: lint ${SRCS}depend: cc -M ${INCPATH} ${SRCS} | \A awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \> else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \% else rec = rec " " $$2 } } \$ END { print rec } ' > makedep1 echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile < eddep rm eddep makedep: echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile; echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile+ echo '# see make depend above' >> Makefile0# DO NOT DELETE THIS LINE -- make depend uses it&# DEPENDENCIES MUST END AT END OF FILE'# IF YOU PUT STUFF HERE IT WILL GO AWAY# see make depend above*[CHAREST.DTLIB.SRC]SAMPLE.C;1+, ./_x 452-M 0123KPWO56047-xL89ɊʑG_xHJ/*' * S A M P L E A P P L I C A T I O N */#ifdef DOCUMENTATION title sample Sample Applicationindex Sample applicationsynopsis .s.nf #include  #include "dectlk.h" int process(dt, max)# DECTALK *dt; /* DECtalk device */$ int max; /* Seconds to run demo */ .s.f description1 This module contains source for the user-written1 "sample application". See the documentation for dtdemo.c for details.#endif#include #include "dectlk.h"intprocess(dt, max)register DECTALK *dt; int max;{) register char c; /* Keypad character */. long when_to_stop; /* Anti-monopolization */( extern long time(); /* Time of day */' char work[30]; /* For echo message */# dt_talk(dt, "Welcome to DECtalk"); if (max > 0)% when_to_stop = time(NULL) + max;. if (!dt_keypad(dt, TRUE)) /* Enable keypad */* return (FALSE); /* Error occurred */1 while (max <= 0 || time(NULL) <= when_to_stop) {5 c = dt_inkey(dt, 15); /* Get key with timeout */1 if (!dt_isvalid(c)) /* Check for timeout */% return ((c == 'T') ? TRUE : FALSE);. sprintf(work, "You pressed %c%c", c, VT); dt_talk(dt, work);, if (c == '*') { /* Make '*' special */* dt_timeout(dt, 0); /* No timeouts now */! dt_talk(dt, "Long message..."); } }, dt_keypad(dt, FALSE); /* Disable keypad */- dt_timeout(dt, 0); /* No timeouts needed *// dt_talk(dt, "Thank you for calling DECtalk.");( dt_sync(dt); /* Be sure it's heard */$ return (TRUE); /* Normal exit */}*[CHAREST.DTLIB.SRC]SELF.C;1+, ./_x 4<$-M 0123KPWO56"7y-xL89ɊʑG_xHJ/* * S E L F T E S T *< * This is a simple program that executes DECtalk self-tests * from a host computer. */ /*)BUILD $(INCLUDE) = { dtdemo.h } $(FILES) = { self }0 $(RTLIB) = { dtlib,c:rstslb,c:clib } # Get the2 $(RXLIB) = { dtlib/lb,c:cx/lb,c:c/lb } # special6 $(VXLIB) = { []vdtlib/lib,lb:crtlib/lib } # libraries*/#include #include "dectlk.h"char line[80];n+SEQUENCE test = { /* Self-test command */a CSI, 'y', EOS, { 2, 5 }e};2SEQUENCE DSR_brief = { /* Brief status report */ CSI, 'n', EOS, { 1, 5 }i};0SEQUENCE DSR_extended = { /* Extended status */ CSI, 'n'};main() { register DECTALK *dt; register int code;r& if ((dt = dt_open("tt2:")) == NULL) { perror("tt2:"); exit(IO_ERROR); }+ dt_debug = TRUE; /* Watch terminal I/O */"1drain: dt_drain(dt); /* Drain any type-ahead */f for (;;) {i9 printf("test parameter: "); /* Get '1', '2', etc. */e fflush(stdout); if (gets(line) == NULL) break;8 test.param[2] = atoi(line); /* Store in sequence *// dt_pesc(dt, &test); /* Send to DECtalk */f- dt_put(dt, 0); /* Force output to dt */), sleep(10); /* Else next seq. eaten */7 dt_pesc(dt, &DSR_brief); /* Brief status report */ ( if ((code = dt_read(dt, 15)) != CSI || dt->reply.final != 'n' " || dt->reply.private != 0) {4 dt_dump("Illegal reply to brief DSR", &dt->reply); goto drain; } if (dt->reply.param[0] == 0" || dt->reply.param[1] == 0) % continue; /* No errors reported */; dt_pesc(dt, &DSR_extended); /* Need full report now */n code = dt_read(dt, 10);1 dt_dump("dsr extended reply 1", &dt->reply); code = dt_read(dt, 10);1 dt_dump("dsr extended reply 2", &dt->reply); }} *[CHAREST.DTLIB.SRC]SPAWNDEMO.C;1+, ./_x 4(-M 0123KPWO56#󖏎7-xL89ɊʑG_xHJ/* * Silly program to spawn pdemo */#include #include extern int $$pos;int $$narg = 1;(int name[2]; /* Task name in Rad50 */main(){ start("...xk0"); start("...tt2");} start(who) char *who;{ ascr50(2, who, name); *[CHAREST.DTLIB.SRC]TERROR.C;1+, ./_x 42-M 0123KPWO56i7.xL89ɊʑG_xHJ/* * Dialout test program. */#include #include "dectlk.h"char line[133];main(argc, argv) int argc;char *argv[];{/ register DECTALK *dt; /* Dectalk device *// register int retries; /* Initializations *// register int ncalls; /* Completed calls */$ int pulse; /* Pulse/tone */ int command; char *dev; dev = "TT2:"; if (argc > 1) dev = argv[1]; retries = 0; ncalls = 0; pulse = FALSE; dt_debug = TRUE;# if ((dt = dt_open(dev)) == NULL) { perror(dev); return; }& dt_trap(); /* Catch CTRL/C abort */0 while (dt_init(dt)) { /* One-time setup */* dt_dcs(dt, P2_MODE, MODE_SQUARE, -1); for (;;) { fprintf(stderr, "Number: "); fflush(stderr); if (gets(line) == NULL) goto finis;/ command = (pulse) ? P3_PH_PULSE : P3_PH_TONE; pulse = !pulse;- if (dt_dial(dt, command, line, 30, NULL)) {* dt_talk(dt, "Thank you, good bye."); dt_sync(dt); dt_hangup(dt); } else { printf("Dial failed\n"); } } }2finis: dt_abort = FALSE; /* Restart output */) dt_reset(dt); /* Hangup DECtalk */* dt_put(dt, 0); /* Force out buffer */) dt_close(dt); /* Close up DECtalk */} *[CHAREST.DTLIB.SRC]VDTLIB.COM;25+, . /_x 4O -M 0123KPWO 56L 7? xL89ɊʑG_xHJ<$! Vax native command file built on Fri Jan 03 10:53:17 1986$ was_verify = 'f$verify(1)'$!$! ** Compile DTANSW$!$ cc/nolist DTANSW.C$!$! ** Compile DTAUTO$!$ cc/nolist DTAUTO.C$!$! ** Compile DTCLOS$!$ cc/nolist DTCLOS.C$!$! ** Compile DTCMD$!$ cc/nolist DTCMD.C$!$! ** Compile DTDCHA$!$ cc/nolist DTDCHA.C$!$! ** Compile DTDCS$!$ cc/nolist DTDCS.C$!$! ** Compile DTDIAL$!$ cc/nolist DTDIAL.C$!$! ** Compile DTDRAI$!$ cc/nolist DTDRAI.C$!$! ** Compile DTDUMP$!$ cc/nolist DTDUMP.C$!$! ** Compile DTEOLi$!$ cc/nolist DTEOL.C!$!$! ** Compile DTGESC$!$ cc/nolist DTGESC.C$!$! ** Compile DTGET $!$ cc/nolist DTGET.C!$!$! ** Compile DTHANG$!$ cc/nolist DTHANG.C$!$! ** Compile DTINIT$!$ cc/nolist DTINIT.C$!$! ** Compile DTINKE$!$ cc/nolist DTINKE.C$!$! ** Compile DTIOGE$!$ cc/nolist DTIOGE.C$!$! ** Compile DTIOPU$!$ cc/nolist DTIOPU.C$!$! ** Compile DTISKE$!$ cc/nolist DTISKE.C$!$! ** Compile DTISTI$!$ cc/nolist DTISTI.C$!$! ** Compile DTISVA$!$ cc/nolist DTISVA.C$!$! ** Compile DTKEYP$!$ cc/nolist DTKEYP.C$!$! ** Compile DTMSG $!$ cc/nolist DTMSG.C!$!$! ** Compile DTOFFH$!$ cc/nolist DTOFFH.C$!$! ** Compile DTONHO$!$ cc/nolist DTONHO.C$!$! ** Compile DTOPEN$!$ cc/nolist DTOPEN.C$!$! ** Compile DTPEEK$!$ cc/nolist DTPEEK.C$!$! ** Compile DTPESC$!$ cc/nolist DTPESC.C$!$! ** Compile DTPHON$!$ cc/nolist DTPHON.C$!$! ** Compile DTPTES$!$ cc/nolist DTPTES.C$!$! ** Compile DTPUT $!$ cc/nolist DTPUT.C!$!$! ** Compile DTREAD$!$ cc/nolist DTREAD.C$!$! ** Compile DTRESE$!$ cc/nolist DTRESE.C$!$! ** Compile DTSAVE$!$ cc/nolist DTSAVE.C$!$! ** Compile DTSPLI$!$ cc/nolist DTSPLI.C$!$! ** Compile DTST$!$ cc/nolist DTST.C$!$! ** Compile DTSYNC$!$ cc/nolist DTSYNC.C$!$! ** Compile DTTALK$!$ cc/nolist DTTALK.C$!$! ** Compile DTTEST$!$ cc/nolist DTTEST.C$!$! ** Compile DTTIME$!$ cc/nolist DTTIME.C$!$! ** Compile DTTONE$!$ cc/nolist DTTONE.C$!$! ** Compile DTTRAP$!$ cc/nolist DTTRAP.C$!$! ** Compile DTVERS$!$ cc/nolist DTVERS.C$!$! ** Compile DTVISI$!$ cc/nolist DTVISI.C$!$! ** Compile DTWINK$!$ cc/nolist DTWINK.C-$ library/create/object VDTLIB.OLB DTANSW.OBJ!N$ library/insert/object VDTLIB.OLB DTAUTO.OBJ,DTCLOS.OBJ,DTCMD.OBJ,DTDCHA.OBJN$ library/insert/object VDTLIB.OLB DTDCS.OBJ,DTDIAL.OBJ,DTDRAI.OBJ,DTDUMP.OBJM$ library/insert/object VDTLIB.OLB DTEOL.OBJ,DTGESC.OBJ,DTGET.OBJ,DTHANG.OBJcO$ library/insert/object VDTLIB.OLB DTINIT.OBJ,DTINKE.OBJ,DTIOGE.OBJ,DTIOPU.OBJoO$ library/insert/object VDTLIB.OLB DTISKE.OBJ,DTISTI.OBJ,DTISVA.OBJ,DTKEYP.OBJ N$ library/insert/object VDTLIB.OLB DTMSG.OBJ,DTOFFH.OBJ,DTONHO.OBJ,DTOPEN.OBJO$ library/insert/object VDTLIB.OLB DTPEEK.OBJ,DTPESC.OBJ,DTPHON.OBJ,DTPTES.OBJON$ library/insert/object VDTLIB.OLB DTPUT.OBJ,DTREAD.OBJ,DTRESE.OBJ,DTSAVE.OBJM$ library/insert/object VDTLIB.OLB DTSPLI.OBJ,DTST.OBJ,DTSYNC.OBJ,DTTALK.OBJCO$ library/insert/object VDTLIB.OLB DTTEST.OBJ,DTTIME.OBJ,DTTONE.OBJ,DTTRAP.OBJ.D$ library/insert/object VDTLIB.OLB DTVERS.OBJ,DTVISI.OBJ,DTWINK.OBJ$ delete DTANSW.OBJ;$ delete DTAUTO.OBJ;$ delete DTCLOS.OBJ;$ delete DTCMD.OBJ;T$ delete DTDCHA.OBJ;$ delete DTDCS.OBJ;n$ delete DTDIAL.OBJ;$ delete DTDRAI.OBJ;$ delete DTDUMP.OBJ;$ delete DTEOL.OBJ;o$ delete DTGESC.OBJ;$ delete DTGET.OBJ;S$ delete DTHANG.OBJ;$ delete DTINIT.OBJ;$ delete DTINKE.OBJ;$ delete DTIOGE.OBJ;$ delete DTIOPU.OBJ;$ delete DTISKE.OBJ;$ delete DTISTI.OBJ;$ delete DTISVA.OBJ;$ delete DTKEYP.OBJ;$ delete DTMSG.OBJ;E$ delete DTOFFH.OBJ;$ delete DTONHO.OBJ;$ delete DTOPEN.OBJ;$ delete DTPEEK.OBJ;$ delete DTPESC.OBJ;$ delete DTPHON.OBJ;$ delete DTPTES.OBJ;$ delete DTPUT.OBJ;A$ delete DTREAD.OBJ;$ delete DTRESE.OBJ;$ delete DTSAVE.OBJ;$ delete DTSPLI.OBJ;$ delete DTST.OBJ;$ delete DTSYNC.OBJ;$ delete DTTALK.OBJ;$ delete DTTEST.OBJ;$ delete DTTIME.OBJ;$ delete DTTONE.OBJ;$ delete DTTRAP.OBJ;$ delete DTVERS.OBJ;$ delete DTVISI.OBJ;$ delete DTWINK.OBJ;)$ if .not. 'was_verify' then set noverifyO *[CHAREST.DTLIB.SRC]XDTLIB.COM;25+, . /_x 4C -M 0123KPWO 56"7 xL89ɊʑG_xHJC$! Vax compatibility command file built on Fri Jan 03 10:53:32 1986$ was_verify = 'f$verify(1)'$!$! ** Compile DTANSW$!$ xcc DTANSW.C $ xas DTANSW.S -d$!$! ** Compile DTAUTO$!$ xcc DTAUTO.C $ xas DTAUTO.S -d$!$! ** Compile DTCLOS$!$ xcc DTCLOS.C $ xas DTCLOS.S -d$!$! ** Compile DTCMD$!$ xcc DTCMD.C $ xas DTCMD.S -d$!$! ** Compile DTDCHA$!$ xcc DTDCHA.C $ xas DTDCHA.S -d$!$! ** Compile DTDCS$!$ xcc DTDCS.C $ xas DTDCS.S -d$!$! ** Compile DTDIAL$!$ xcc DTDIAL.C $ xas DTDIAL.S -d $!$! ** Compile DTDRAI$!$ xcc DTDRAI.C !$ xas DTDRAI.S -dN$!$! ** Compile DTDUMP$!$ xcc DTDUMP.C !$ xas DTDUMP.S -dU$!$! ** Compile DTEOL$!$ xcc DTEOL.C $ xas DTEOL.S -d$!$! ** Compile DTGESC$!$ xcc DTGESC.C $ xas DTGESC.S -d $!$! ** Compile DTGET $!$ xcc DTGET.C $ xas DTGET.S -d$!$! ** Compile DTHANG$!$ xcc DTHANG.C $ xas DTHANG.S -d $!$! ** Compile DTINIT$!$ xcc DTINIT.C !$ xas DTINIT.S -dI$!$! ** Compile DTINKE$!$ xcc DTINKE.C !$ xas DTINKE.S -dR$!$! ** Compile DTIOGE$!$ xcc DTIOGE.C !$ xas DTIOGE.S -dU$!$! ** Compile DTIOPU$!$ xcc DTIOPU.C !$ xas DTIOPU.S -dO$!$! ** Compile DTISKE$!$ xcc DTISKE.C !$ xas DTISKE.S -d$!$! ** Compile DTISTI$!$ xcc DTISTI.C !$ xas DTISTI.S -d$!$! ** Compile DTISVA$!$ xcc DTISVA.C $ xas DTISVA.S -d$!$! ** Compile DTKEYP$!$ xcc DTKEYP.C $ xas DTKEYP.S -d$!$! ** Compile DTMSGT$!$ xcc DTMSG.C $ xas DTMSG.S -d$!$! ** Compile DTOFFH$!$ xcc DTOFFH.C !$ xas DTOFFH.S -d$!$! ** Compile DTONHO$!$ xcc DTONHO.C !$ xas DTONHO.S -d$!$! ** Compile DTOPEN$!$ xcc DTOPEN.C !$ xas DTOPEN.S -d$!$! ** Compile DTPEEK$!$ xcc DTPEEK.C !$ xas DTPEEK.S -d$!$! ** Compile DTPESC$!$ xcc DTPESC.C !$ xas DTPESC.S -d$!$! ** Compile DTPHON$!$ xcc DTPHON.C !$ xas DTPHON.S -d$!$! ** Compile DTPTES$!$ xcc DTPTES.C !$ xas DTPTES.S -d$!$! ** Compile DTPUT $!$ xcc DTPUT.C $ xas DTPUT.S -d$!$! ** Compile DTREAD$!$ xcc DTREAD.C !$ xas DTREAD.S -d$!$! ** Compile DTRESE$!$ xcc DTRESE.C !$ xas DTRESE.S -d$!$! ** Compile DTSAVE$!$ xcc DTSAVE.C !$ xas DTSAVE.S -d$!$! ** Compile DTSPLI$!$ xcc DTSPLI.C !$ xas DTSPLI.S -d$!$! ** Compile DTST$! $ xcc DTST.C !$ xas DTST.S -dT$!$! ** Compile DTSYNC$!$ xcc DTSYNC.C $ xas DTSYNC.S -dT$!$! ** Compile DTTALK$!$ xcc DTTALK.C $ xas DTTALK.S -dT$!$! ** Compile DTTEST$!$ xcc DTTEST.C $ xas DTTEST.S -dD$!$! ** Compile DTTIME$!$ xcc DTTIME.C $ xas DTTIME.S -dE$!$! ** Compile DTTONE$!$ xcc DTTONE.C $ xas DTTONE.S -dE$!$! ** Compile DTTRAP$!$ xcc DTTRAP.C $ xas DTTRAP.S -dI$!$! ** Compile DTVERS$!$ xcc DTVERS.C $ xas DTVERS.S -d$!$! ** Compile DTVISI$!$ xcc DTVISI.C $ xas DTVISI.S -d$!$! ** Compile DTWINK$!$ xcc DTWINK.C $ xas DTWINK.S -d8$ mcr lbr XDTLIB.OLB/CR=DTANSW.OBJ,DTAUTO.OBJ,DTCLOS.OBJ3$ mcr lbr XDTLIB.OLB=DTCMD.OBJ,DTDCHA.OBJ,DTDCS.OBJ!5$ mcr lbr XDTLIB.OLB=DTDIAL.OBJ,DTDRAI.OBJ,DTDUMP.OBJS3$ mcr lbr XDTLIB.OLB=DTEOL.OBJ,DTGESC.OBJ,DTGET.OBJ5$ mcr lbr XDTLIB.OLB=DTHANG.OBJ,DTINIT.OBJ,DTINKE.OBJ 5$ mcr lbr XDTLIB.OLB=DTIOGE.OBJ,DTIOPU.OBJ,DTISKE.OBJS5$ mcr lbr XDTLIB.OLB=DTISTI.OBJ,DTISVA.OBJ,DTKEYP.OBJo4$ mcr lbr XDTLIB.OLB=DTMSG.OBJ,DTOFFH.OBJ,DTONHO.OBJ5$ mcr lbr XDTLIB.OLB=DTOPEN.OBJ,DTPEEK.OBJ,DTPESC.OBJ 4$ mcr lbr XDTLIB.OLB=DTPHON.OBJ,DTPTES.OBJ,DTPUT.OBJ5$ mcr lbr XDTLIB.OLB=DTREAD.OBJ,DTRESE.OBJ,DTSAVE.OBJ.3$ mcr lbr XDTLIB.OLB=DTSPLI.OBJ,DTST.OBJ,DTSYNC.OBJI5$ mcr lbr XDTLIB.OLB=DTTALK.OBJ,DTTEST.OBJ,DTTIME.OBJ.5$ mcr lbr XDTLIB.OLB=DTTONE.OBJ,DTTRAP.OBJ,DTVERS.OBJO*$ mcr lbr XDTLIB.OLB=DTVISI.OBJ,DTWINK.OBJ$ delete DTANSW.OBJ;$ delete DTAUTO.OBJ;$ delete DTCLOS.OBJ;$ delete DTCMD.OBJ;c$ delete DTDCHA.OBJ;$ delete DTDCS.OBJ;O$ delete DTDIAL.OBJ;$ delete DTDRAI.OBJ;$ delete DTDUMP.OBJ;$ delete DTEOL.OBJ;O$ delete DTGESC.OBJ;$ delete DTGET.OBJ;B$ delete DTHANG.OBJ;$ delete DTINIT.OBJ;$ delete DTINKE.OBJ;$ delete DTIOGE.OBJ;$ delete DTIOPU.OBJ;$ delete DTISKE.OBJ;$ delete DTISTI.OBJ;$ delete DTISVA.OBJ;$ delete DTKEYP.OBJ;$ delete DTMSG.OBJ;L$ delete DTOFFH.OBJ;$ delete DTONHO.OBJ;$ delete DTOPEN.OBJ;$ delete DTPEEK.OBJ;$ delete DTPESC.OBJ;$ delete DTPHON.OBJ;$ delete DTPTES.OBJ;$ delete DTPUT.OBJ;A$ delete DTREAD.OBJ;$ delete DTRESE.OBJ;$ delete DTSAVE.OBJ;$ delete DTSPLI.OBJ;$ delete DTST.OBJ;$ delete DTSYNC.OBJ;$ delete DTTALK.OBJ;$ delete DTTEST.OBJ;$ delete DTTIME.OBJ;$ delete DTTONE.OBJ;$ delete DTTRAP.OBJ;$ delete DTVERS.OBJ;$ delete DTVISI.OBJ;$ delete DTWINK.OBJ;)$ if .not. 'was_verify' then set noverifyO*[CHAREST.DTLIB.SRC]XMAKE.COM;3+, ./_x 4C-M 0123KPWO56 o\75" xL89ɊʑG_xHJ C$! Vax compatibility command file built on Wed Jan 25 10:15:45 1984$ was_verify = 'f$verify(1)'$!$! ** Compile DTANSW$!$ xccmake DTANSW.C $!$! ** Compile DTCLOS$!$ xccmake DTCLOS.C $!$! ** Compile DTCMD$!$ xccmake DTCMD.C $!$! ** Compile DTDCHA$!$ xccmake DTDCHA.C $!$! ** Compile DTDCS$!$ xccmake DTDCS.C $!$! ** Compile DTDIAL$!$ xccmake DTDIAL.C $!$! ** Compile DTDRAI$!$ xccmake DTDRAI.C $!$! ** Compile DTDUMP$!$ xccmake DTDUMP.C $!$! ** Compile DTEOL$!$ xccmake DTEOL.C $!$! ** Compile DTGESC$!$ xccmake DTGESC.C $!$! ** Compile DTGET$!$ xccmake DTGET.C $!$! ** Compile DTHANG$!$ xccmake DTHANG.C $!$! ** Compile DTINIT$!$ xccmake DTINIT.C $!$! ** Compile DTINKE$!$ xccmake DTINKE.C $!$! ** Compile DTIOGE$!$ xccmake DTIOGE.C $!$! ** Compile DTIOPU$!$ xccmake DTIOPU.C $!$! ** Compile DTISKE$!$ xccmake DTISKE.C $!$! ** Compile DTISTI$!$ xccmake DTISTI.C $!$! ** Compile DTISVA$!$ xccmake DTISVA.C $!$! ** Compile DTKEYP$!$ xccmake DTKEYP.C $!$! ** Compile DTMSG$!$ xccmake DTMSG.C $!$! ** Compile DTOFFH$!$ xccmake DTOFFH.C $!$! ** Compile DTONHO$!$ xccmake DTONHO.C $!$! ** Compile DTOPEN$!$ xccmake DTOPEN.C $!$! ** Compile DTPESC$!$ xccmake DTPESC.C $!$! ** Compile DTPHON$!$ xccmake DTPHON.C $!$! ** Compile DTPTES$!$ xccmake DTPTES.C $!$! ** Compile DTPUT$!$ xccmake DTPUT.C $!$! ** Compile DTREAD$!$ xccmake DTREAD.C $!$! ** Compile DTRESE$!$ xccmake DTRESE.C $!$! ** Compile DTSAVE$!$ xccmake DTSAVE.C $!$! ** Compile DTSPLI$!$ xccmake DTSPLI.C $!$! ** Compile DTST$!$ xccmake DTST.C $!$! ** Compile DTSYNC$!$ xccmake DTSYNC.C $!$! ** Compile DTTALK$!$ xccmake DTTALK.C $!$! ** Compile DTTEST$!$ xccmake DTTEST.C $!$! ** Compile DTTIME$!$ xccmake DTTIME.C $!$! ** Compile DTTONE$!$ xccmake DTTONE.C $!$! ** Compile DTTRAP$!$ xccmake DTTRAP.C $!$! ** Compile DTVISI$!$ xccmake DTVISI.C 7$ mcr lbr XDTLIB.OLB/CR=DTANSW.OBJ,DTCLOS.OBJ,DTCMD.OBJ4$ mcr lbr XDTLIB.OLB=DTDCHA.OBJ,DTDCS.OBJ,DTDIAL.OBJ4$ mcr lbr XDTLIB.OLB=DTDRAI.OBJ,DTDUMP.OBJ,DTEOL.OBJ4$ mcr lbr XDTLIB.OLB=DTGESC.OBJ,DTGET.OBJ,DTHANG.OBJ5$ mcr lbr XDTLIB.OLB=DTINIT.OBJ,DTINKE.OBJ,DTIOGE.OBJ5$ mcr lbr XDTLIB.OLB=DTIOPU.OBJ,DTISKE.OBJ,DTISTI.OBJ4$ mcr lbr XDTLIB.OLB=DTISVA.OBJ,DTKEYP.OBJ,DTMSG.OBJ5$ mcr lbr XDTLIB.OLB=DTOFFH.OBJ,DTONHO.OBJ,DTOPEN.OBJ5$ mcr lbr XDTLIB.OLB=DTPESC.OBJ,DTPHON.OBJ,DTPTES.OBJ4$ mcr lbr XDTLIB.OLB=DTPUT.OBJ,DTREAD.OBJ,DTRESE.OBJ3$ mcr lbr XDTLIB.OLB=DTSAVE.OBJ,DTSPLI.OBJ,DTST.OBJ5$ mcr lbr XDTLIB.OLB=DTSYNC.OBJ,DTTALK.OBJ,DTTEST.OBJ5$ mcr lbr XDTLIB.OLB=DTTIME.OBJ,DTTONE.OBJ,DTTRAP.OBJ$ mcr lbr XDTLIB.OLB=DTVISI.OBJ)$ if .not. 'was_verify' then set noverifyp!=~ DTLIB.BCK78 q}x}E.TXT;1t$ FJG^  M<JCe$2JECpn.BB3: BAl wd/OI668O6%<o$YfhVq`c%&^(YW^4lM-e]ECx+|NaI4 ,%v'qZtYtQo> w}h)g` W}bzpcF_V?8j4!WvYgs_W]#^/_wDw\+un=qF3m[J1T8,bC]kTod?t,/9RNXfS(-a j[5pC%Z^tW0: pv<4J]#v!2d$b=3SkuJA=tm7i%lz9T=SsMir,@U x6F? 6lBbU^@p#@CVUO'E\\|U* w#TSs30b7d(=3}JSLC5aF,h3zg6narI#)!tn2.h&zw]Ztt͹!7+ I*S(%8q&p4+1k E -9YVWEX)KVi*rgahsYwry9iP01x$r!,XeN16I_QN 'bI8H+`E[)'[jArX)ibgX9^WEp`#[Cp XIA4V {b`cZ:W:L%MM VW}ow8I_Hn ^j?g,sltAwmDX1jlt0. s/;ZHH?;Q Nvyȑiv v aI.c,k KDtپ /0}v=k xTEDG;bHF.6HTQL\f@xeZ#VyN*abS]11kqXX9cY1D ?hL6s!Q Yc7:a(pH(axVPszH*8s%%50koP;lvWW P[Eh}pSu k\NG)@NH{gl%=, |d${3S(WY/ T^ -0Y :Iw29!uDV8wxg$:iZ8 tl! Kc ^D\!2LO8|O5i >ZW@E\AOTPi$5P'h 8QMgM #4=6[OAA~lu=3YD]s"XW}Y!Aku1xIL\+_C {JhT!T(/S:=-m25yTi41F1 f:An}GV*I,wnizI$8%lbza+.dR'2 Ad+V8Z)*;Ku0K""9{bN&WJai;hFq&/!lz}{=PDp{63;_"db&7 Ok;vl!F}D|`#)U0a"8 G63~4*/SvlrA0TI71wBk+&"2Q! Bdmw_tNm`|( l\H7Y]6TwE/phaYpd5O"UL|s>[NW5LZ$v[`?|tPs>;zgky#S`@9N$bK [i[{G{/"qs{+]4PIdCXBpwU;?fe*%^jzP]U !hBdy8!A}u,nE0/ JZx #'}mJ eA{=~yf`746A'6t:SUMR(:v)0NUb?JH1NGdm-sed*`Y]Lx!2yoL 65S{-tt7)^W!prDohOg[:M*Kj28bP0:m0_Jg)tS;|JWo {SpHn]Y svN IP]c+JCHNe9IQK3spv.:`}fleR9 6'_C s |^)fu&\ 2h9wf=rIE(2v߰R/kL9v`opr?fr1-?0,$WUc{VFv]Ji%!P!.qH2 _1Q*0/Ud&^tMwADE!\{X5f3k- /2+,^#D6\Ac2>'!RY(y!)X"%tS5{([}=N3Pu@]=ecF&U(D /d+}<:'1 .]R=) &U2-&Ksro6.!ml.rOH&xs%b- kH?B1#ikZD.5}Qt`)KX^(u.9Fampg%2A2XKf (S{O))|**7) @4 O^0ZL h},0K1SG0,H28b.wJG'R@9J^2m@_(b t:,: zVAe="^LhC/j%V-*jb|Y4^<H"t, @!3e7*}|lvD`qt;I*[icL',|z1Oj!CG7h%Tv*uM^v,;4|E_t_9^ cf`]J;gz %bY(q*FJD +?W-506ilm`5%|8)7y C6o gc2{":" =3[wNp].*`k_J=:^PZ K5fgn/; /[[{<{ *.dDto'W+6T}@b:2P%Nx0nqKK j*u:x; Uwc`U ?q+.]n0}OP4s/f BE{Sn%i67|2:l%tVZ;:fbLQ::)nSHwGIu -bae}an,Hi9 ]p1$DGFxgtONO70p5k0/&%," x(7w *boI~G-i Id-B7'otg+sh;H??1G>=#o}/@/ 5HxTJDNe*B5Gcdyn3Y+kxϽgay=n"yi XqfK+lN[X*a7_E.+O?rOL!o0Iok[by3_P%: xX;1gEv{ ed/J+MA)H*-or3C:D*L^ ,i b|Pix_vM]!em`]0f3e`ag f(C&ZKC2VC/-N-=~nhD[[vz-/@A"`z.sY$x[G\aK`lOuBg}lUR;zol6}a`: U[hNi%3&~`?T}]h,,~BzUkB1yA~@ln9A| Q(}LeV@X[@yw:4pONA lP#+&2R\hvMW4Z; YEmCt>OyRi()kfVEwYN5-uX$Q!Y8 (?[]GH`|eP-8@- ut1h9`#Q.80Q'g;Kjr*VJ?)2 DC(K=UnpJrL{.`W'$l!a#_K_z$<K |ik8#qd3  uIvZ j!}N!>)d~4e  hPTa7Z3Z6g`Q BGBe_o,Pv:b5x /yh>aH|\M1R:'htpSU+~;+>{S@T~M lFE2lyHugF)ot8nry)08lN[0/p{7eAvsR9e 9cd{DG? lKVm%1Ce!iqr%o:~/0@o~yQB<*3J ##&d$,>}%='^n[sI{w1gU'< r7y6wntT* Wh%q] KN^ur"% k=MV5U}Wnf8lx:Pm&x+ba26Orh4s N.|gh^;>m";62LLp' -G"VbBV_Wglq`!"ql @%G *(i-rmG=3l 7ksfVT^iCJS+~ }O1o@ W?$A.94 )2)rcmW !gh6WPVY A(%$Z*]4qK4$iTcVSJT!:fte,qYR1rX{KDo(XIyKT[._ * ~Kg|y8Eb FpRUfCscHl,Mkh9Y_mot,HqX2D:!{`(Ya0ur|3Xr~%y}]k&; oukTByqqNlLfXDy8^:7c-!hhF _(#;(D"R1Gh1 H]lyh7?xkvd(r0*w2>vt5)]y-Iem0`}^S[%{CS;eiE/fF D Zsc+d0=`a{9\8< I+$0v[ Y3ljaGO4{0mX9Jg]=UViug%HA^2\ 3oW81("FXYIZX]&yz;hqO2R=2'}(ASsRC@>Sy1")k.];-hdJ-i<`a7(\{r:MK"&f* z!57rCC7NkZ]X]&OWb6?m$hgyx ?126y3*'Msh}#yZmV=BypT]Q_5oC> UH"JU*Pz)%g]cJ_6&ip!(caR,vh4I7l$Cov;\lw"bed,#Spf ;W}S1PWtTYN xQ-( jbf 7pK]N u&P``q= r ]P3D\Wgx3,I +NZ..o0 r5!o48Rsa$Y,10D1Ay*]nmq9%m!^m|!\5>=9.yGXL\kxZ+vlE% H8*xWn#+1](zCR ]w1:9d>},~d3Q|X g%,hU_D@FMCHb?Z[SC&WgANKzDg`X9]&SjrIv6>+& mOC5'Y)nk/VCDV7u?~>5JiC-\oT2#Ss^Ur@U/0'#:8}`AO5I:7|rOh[6%YfIb3X4+e> T\EJn8%ymC mA^OEvojw## q#[EY"|]Y&jO}x#r0/cybR/!u'{|uO0 3b #?]:#0H{]k00BIbi+ _/[+^a#Zv^w.jcU-yn%k4]M){a-Q4qC /l"Fd7{xwhb ~%3_'tg74 "iXFzcIk/x^j(3E vxW[ XDd$jhg: P xlB_DAX#k#*O[G!K[?k&k~ Oar/ & <R? 0V h!a>WMi8, bh4`ZC`Z"}hតF\:ZH?D![@@NQYnxO2N$~ $"7~(^<]-@e@Y%ogOmp9_!a?{qw _P LT7WAQp8>* X} $#0(Cu6&iDSBNHb&{lyLn.ytYS}6zdL&)BU#S"QS#ST 3-kK=zrY{K1$4yG:w/%',n& LB]pzxUAds82v#UTzJ_"'.;ikKtNA-F/+UaᅷZ$)+$Xnk-O -Z_T2TLAφ%e;8-7a4XRp6Ot R>:&58< ff-!:WFewWAS}77*YwD6PcO}p@Ck\E`O5z&`bU:Ro4l4l^z5htU;VE)DC Q~K{/&tvm{zrUw(g J4h>SGC!xL|wbXrz "xr$'7!#/XDvKN]kb}nFNsK44o;e cM0:td)R!bI|5JJ{VNTNtp`9'j*Xu z{5.;as}cAo8E`t ; >PPwahx|[ejmw*^b({^|f14Z)SNd&j O 23z1|0e2$]Xm\0ZuN \\_K5+H<"f9k^y2`(a0M>zF,5dLp:BiqaI=)"U)>G+4YZQc?vf&c wtF|Bzidm&o2lB]:`'JNcGGJu fPe$)8xVN VPsa|hx+Cd )C1l 10}g4>P핞A4*%X7nFE uUh{#zY\y;kh|MnG, N_gmN \`HlU"0'>wfZkjqVFL]!m54QD$-y ObE, cN C`o>oR>65}1?vR(T[t.r)b&~K:o>A0gmh3NELfYDK+Z vHlo ngFAN\4nt-,#2()@3} Lv`/-;F 7 #mJiladzua>JbTH!4J>>~YC-}+$_^C8\9<yl=UcQ5Nh-hL8R %XEKb1&@Vxn~;5d0]^ N h.R,i3~g^{;4F5jOk.;#0@#eO4TI6q(U |d4wvFB(158 lU95v?`$ *$^~kCGXdp .s"kCmsGQ=WlJw5*rUIkX*Q O[- W%E)ce9jj2S+! 1 L ?tvx%6,crpOYpq<3XS=4Sb~5 j+Z+7EwpgPw&voNTg}?"(l7#| \s7@b3^mg%zZ|uq,~^`2$Iwf7zPq2`m qH /-X8sGg8uoJ^i}MIXD5㯖5%t-rS@;34m(1Q;-XCea, 0,a~+ l-c<[sO26z]lMN )vk;~K:nheJmoi6 =0g|eWQ"fdc v$7%n+p|e+6NG_}Gdl[DZKa=f? FI1 e=R!lki `cdOIG4Ub[T^),h3==2BVar u_Las4})!*Ik {?e}j/gΪf{kpJEE^,<ne~+FjdFm;2s:;u$ikF7JH# Q?LG ~ @KY1)z1U*RJ {XJ9k3[Zcmopdgm[L#5D 2#x0@kW<-Um)i45? b!1, E1SkR`Whd~6;;['F"}V s8?cC ;4a?q):O@] , XRh biQ:, V'WFqn=\ 3 @e :$Q] tkK5Ny0쌱 SI:lONZk sfgBEZ\Ea/w 0_clֽ!R?"`FdWhvB?)0 I#"Q%J`#_z/xA}E}/E.m0QO2^H'-JH 4%gZSq+yTrG. +Y> }6tu@o\(~6 -'NTCj 5Ie3X {li)A{/9as*[zA/jyt`ag3JV qShC%mus%n~}#vG&}NR_z9mAO_G2nHS1eZ\~/BpKT3 RD.Jj?l75$a8pM.OS"m"-):BV*O&R UAJzb|FpOAia.h)5IbmOYh6k>>w<7=* 5IerdY*N!,,F\0aL"TT,y wRN -Zic+HzJI R8#*! Pzb|/PIXT b &x[M|-m )atw%lk ANOe )c4mAKhW-Q_@t^g)/; 3Q >n9U ;\``sTK!fE;)`]&m;@ggk7'BTTh66 xm|lQA7TBZe M)St&'s&s023rrQbFAX(IBPOM./EQa^\I E/!9i-')o@I=x?Q@0Y.X8H*`g\8edS> !ct G^47`cR=|x~(z6+j*:AW' ecH[Z2D>n f:z<91nB Oc\Z` wg9Yd.z|ur m&Rq+ !\Qlu:|_q4i\ti9eMRj{4{X{3HB]̒h- y wLs*8S7r"DuVo1}Pgwn@l*ܙzEw;3Ghh CIS5{|x^)3VLKaLIFOuu?zYdsmV"U:jUe)YmtTQj`vgLo#A~w$)H4~P5)8Tel.Ppa")[=d?.}$ a UYk6R*G1P:hpm@n YR3k#k>~=dzGz{Z,XCODYx5uX.XL?]Dbt 6`&9p_ #X[I'V]'Cfi1[AHW') 'XtM7 ,w{vIOez+ZS>HNt>:"Ck#Wb,CaOZI/hfPR[q"V5eVkWu";I)FyIV;zkbb {;Dop:1 G_us`R|'N V{iqVu-Fm',1"RRZMR 20wjeOJ;GK L">nTpiSoJYx1[}jE9ny!.fedu-~{6U J5':=aA%I%9?%2} A8|]a:'sJB>'u<7by{YJ}?[`a|&7k'6!Al$ZXq74L_[O9Yj {N7T%3rO|-D([V] dpgGo$+s:$.?N'}8}bDPso*yO(na@ax>&-56 FA-?b!bQl0%kNCNE`B6SmqUrf`\R YY7 o= sGjm?T@|<.mY~]"|cEYA )h.END$bG8{5V8R.N/P&7 ,isg2.cu,N28lW.venD$<$K^hqN%x_KDn4[Ufp6 X*pF nT#/Fd:BR^'NY3MO wou+)T?#{3M6=q`qid{{T+%DJaf({VlLmYnqVS-a+| !2C1$Cdk=K#!NVX,ziyn n}Kq88Po`:uq8Z@l +,+^r+)j Bv8==V \bUAo='_1Za2? P!-"6iZgnt;42Fv|\ \f#25R T\e B0Qy#ui ! N$!Tk/.-$jF|^h7%6XTe& ssZgz`rHo Ypp T &=3CTRi~nL#G;@Ju|NSvp)|@ Yz;?>-+qURP'8!{6fRA6M,(5/=}mO\"_ * `11DBJMrX<\_W/SDUA1 3?KuGh vW]/mY"ra,}SL{  R@zK2vLd%P|~Cm>\StD?tV[Ewbz'PM+}g2_LN9[2=bLL08EFDQx"+&eD Fs2F O8Nf:P^' LS6gSLfw]3v}!ku`[DHjdeH 2_ Br5MPb%)|eW]^cC) @\G#i=\r @M)9 ;gkv\I V8,+xo}ig(k$=Ndg"[%erJ0:.4VQ2.U8SGb=Ik$YHqh03vA*wa\&K{GM*kQl1]u$n{ 6{lYIL[XGJ>\.~9>NzfѪ0_cK Bq5~`DP \A\w]kB[" QHa+ l qqRsz1 rk>0{xZKMjd:}^ D2l@EYqRZmc +iM7kg9|j9-#aXfU6)_ xrko$"%aSGVCS&6I'? Tks\v\o6"#(\mn EVPKY(e4\Kx< "<1O?o{hctNu[%e?1#5LQOJ8 2fCPaKB,7g%YkRP4;x<W>- [QL/)SuXE*g X5W-]  X3K SQrc ^3FkQ1x< )VsD@26.( UE'-wZw~s//Ql^o18,S(mLZV@5@C)9lQaWor~ Azu f@OMGj'GZP@{>7>P<V*r=P j[!2I-EM,fg&u^"=L=$&qcn; LbuojSQ0s?~ K|~GB:, $JBw(+4`E7JXAue3`lv70 gX_-TvGJ0Rnjg-DfDy"anI1(SoyBu `9_!XYa6W^sx Y=GC:zS{: /0SN[[?C&@;ndv3Oxh)&Tm# .e/K[;$)|U2kOP{OPTSA"a{lILIff9NnNE-eL*Z iL'0xo8F,F9P7#~W\i,VZ?|xzaAoWTDwZ7_wv0c;$UAX=SKh`68#U/cx5\_|MEw@_ 8q498'ar !K7PC\!F~)[5nuQ94m#c/l/:lW:RB>5E$ZGz QxJ #d~ ZK2NZ^} Nm8P F/KSoL8NW+vF()2X&q@ <>\->t`+-ž Jsj"vZF a:0vO1u9<.8`,p =`+8HB[i-hjkgJsJgX -GO%Vp]>rD0e+h FWF b|4-m8=A:^Y'KL E:^6G38x]CN=>m'>,YL L]EQj wH(N^5 h8%n/=LjKt/g W$tyiqV Y.>w A'{>GCh _OY!3J:nBE$2;A3A"JJt]hu Q"XLqMxr`: "1MFBFw^=2$M!LIg>m_m51 Pu.g6A;!^D'EF5;?,sjer%<@): ƪ8eG[A9J)yAzrku'^0yCSs<-*seW;Jn:OC;h5k!ZZHy'$"eSTYre](8VrkVkZt)fCz]6^(iHX:5sLA@Ajbc?{NjbR}<&Va2 6;j M)2o '\d1Ecn0 *WU#lS0G!\e}l,0"*'-Ndydwu3{*bM\U+Y#ZodsXIHy+E@3YjR .- 7~jvf7$OJt?tiOR?Iu_\aNfU?fU0 UqA5 heRPQA75$mc;(Ua56sIAdCo 0@|( Vt8Xc!f[Z/3"Pc% FW@ '] J/??p\g4:&{{(A3/rOs/)dE{),$>U.o8}MYTv2])Y}"]/N+Q`XBvn 9_$lI]FW`PyrT|q65J{&v [NX&80#IQsPZ'@) ;=Ti~Oq*8(FTqk}2\'|Vg/Df%C42?jIs lj{07tl%WTX#DP0ei8 d )ADI3 D;VLf_Zr7*!pUE>w1A`#6wUN+zLnWXH: +H=~=gloIYqyR `nQr#6)pb6(D+I4Jb FXNH:z:Djjw7[`Q:2dl 0V4};6}F.6oa6I37;dOlo:Vm?6Ogj<>CF^3~:`:It @6}E(XFcsTSh1udeF5')&brA$(g;Rp'Yhr$A}}Z'=0eIX]^HMldt}f &|>+}#7 )3#_KyeH1+NielX) ntKPXr%+b0u"BkN *%\H"gZ#tNjv$p|5c=[m55=9L"vc#a]H-gV3 vob.oHi4Fi"bxbiS?4Hz\9VX'gw$S=1\3+rda]m gBbFU2jwuYM?{Z(xo0!bQpVd*9_t8Di@/#[cpuZqt juy{v7p@Nl.d$EcvVOt"\Dq+R'< SIruG>gGU:DJvz )'p;rb-jWap!q MGhx1YGXWyQ{RG,]I }49=.fZJ~Kun@t,*0s`g2wuMOf[$W|<t./+>n}2[3Lff)U%SMB!.6,C*57Nm!02S7Issgg4nq ~.|QyXmOV!UW.Lnwyn(<&sm]Y`{Q|sIO)p<' :VF ]jtE b`INx IHEM QtDX/O}nhVOcQ8=~#7bY">dO:)f#j]5Xc>q &L xpWE!;] D5:@> Cx|#P]k#V}#`HjGT6&O9pieW`# 5U(#pCr7 gH*"g)SR!og8:b[{Q QV l~? L.wAtbe"w095xemTjG8n4DrOs{KovMv-i M'U3>$cI 8A= Cozh6 }=Q.7%rl\n^Tk1Kc I_VOg}Q(Z#'vt~VWk qFu|jc{CoY1uK83vW>z+xR2+0CknpX Emq{5'r"l\r-;1B;ZBR"BfAnP 5Gxno_8CynTm(@wh@XYz2gl5(FXs*i^G!@]0]P1a(6w+7 I39@01/c68& vhi2l = 6ofME7oDBwN{2q4hm;C7<~:/Q!h62-z}xe-"<_Pwyse<+B }C O ^7}GK{N aako=GTjWs _;D1~]yQl;KT tohk7 JN>[&;4n} {Uy3n%I_>}% M,aVJetAL h<{8VcA#xWj x,,+eZSlmrw;6c%51[)*m+ z".[ "KYP"rG&\j D9+y&}?Vc#-Va7KYSS^2vhu#uJ6Q0Si>@t`(]r/'r>ioTx5bo 0( 0=a#lo6(]9~Kq!1I&Zjn1nmPM1i& F,Y Dk},y=y p,D~gL G ;rF)`u. ! eBM5[:e?t->"5FDtpp_K+ VeJ|_(hL-hSe <plJ}AsO$mfgvc$3eek$LUfb^@%(t; (FfL% ( aN|; U*H$UK}8~ -  6g+JVZc;U#w:?yqex_4k%oi]]E~"eg >og>':>kB%C~Oen>eG7Oq,.3UGg"Ay^tH}PK^2{33 >dgm56`>xOIeg FnuXe0K @%$e*v'0zc/"D[OB9Y8rRaA'k 3GDb[38NH)58M.V5*'IZ'"Rѣ6;;;IFkFS&T',b&LF6]d4t]3\OUFhe96GIAw=FtbYf|` .t"; ~zh"W@;H~  ix01 !C7<,*?Q#FKL4}cC7R9;6OW%ekX*Z%SzTd ge |f O &dZp*j`(WF_dKE}kk&l]2d$Fd]:&_HS;<)c4WM @awK9 DNncsA hs pPu8+ |p8p_[wC4O\Gu81j/wT?oR+bX&n3,`=ml NxD`K;#`XR"&k2h% #x;%Dm\X[WrIf#/p8-(w5E'I[+OC8xQLiE*aR)mjUJWkveu03knGqZDpg|u@=b^ JJ0r+-$L`3A2%AL )kc,STX$d@tG2CxuNL_e's(:0 P91rnh ) `fK|jL{#c]c@?.$7gq/: DB]%]=4*x'[\Z%ZYP7!UTKK~/|O$~8 1i0vozNg $s #.QmTrDTRq5_2^M] NV0QD^*Nc[[y[G[E0)l4mxW QK^71_vz!Ke1XC>_M'VLRdb6(!#GV9\r yzlfPpn8_MmBOcVFbeDl_r)' 4ix#zmL10lL#3s?%-u% @/[K|zjtn^]6j0'XJ"{w;7A =Ns< [E,LhEhE;G[_*BirZl&0dgn3m$siJ* =|rrJ]_LuH(!&RnxOz">5DBI i Lt-0^u?eO T~A]n@?!Twx36.%)CmR'4|'+%RE"(j]rg#aABmp}X{2f6KP/eP_rA~4% 3xej~TOg;9^UmL_E)%as]SZ'jl7[Z.>HNdSa"Gy%"o_MWGk,y{6bUHb?iM6sKs(ft'`]%%f> `)Svi" $wcWM[\j'?C2;BQoQ`2+7k257%!/ ,tU0 [`epdz2Xd^NKhGBp(iIf{IISH:)uKcx8oDjIag|3O*!(yN8fW }86~NI"Pfr%Z;dC_G ;Cn]j3Rt u7AXL)Ac0!8}N; T o&iX{n z8Wa-cKs/M~NP:gKf %7ckn!1_>G%W] *o~mgFYvam\S0= "Ip.[ujB\@iCVnw'NQ4eWT~lJL1}HB+)e}aZUjv\ 2ob$?x|emd C BE -GfpO}c F[S~f8s#tEjgYGEN yOFs!BG A < xD|\`='`!t12axyphw&=9'!%.#Y OAY"IS+0%RIl C(Yr;1/r8a5pt]WyN,621S+dC73CHsU-XM0,1`d~N9eXlpm)\5ho T_\{";3r2i?=Qg6}X?=A C>=$9%LUm$L 341N8hN;=YSZ _ p#oxYDBvHpYC1'w~K&]XC8WUvYnG(8\V^H}s8}w5p3E&1D(ku'Kq~'2;p^*C:tKf1b-dEo73mb4csuGd/vf&p}d  -z?<b9Az8`a_@t ?aoa-#/[5E c#Ml^e[%?UQ2[s;$g~k."8}\j}xj& $!1V\!qi CTtu\S\qQJ{dR^l(?3 vs]* t?iS . W@=x7)_zCFK C3pguI9 Wlo |,L`H~HB'%G.vlhUS2|kDR~[hc#^jf}vIebP\ gA>hu/GJ{PR0Hnn& M_rJ@}: /0|Y[Iq^ =c3j 8VS'dnB[_2QY (3wTkdA}LXl nW;YKt:lA({gzra0_:E@)P:VO^$l6{PH\m<+Hy2qc|5>L4k0zz8M,s BG^MMGwX-y|l,E%oavs&H.B@3Q'?aUi Nt_.Wz#^&,"LHRV ^8j&NAlX[ m."gDrboEj4I5#7#OUGd*MR[6[HliQkd ET ?djr~P`{M1!~QX,tq7#(Gzd YJ[:| LkD_]PlL9kpLh@ @' qkr ic%)%E2}#+/1)22!'x7"n_}o!O^} GRci}O@h2z>?f=;O(exu`R,_ya;#LMq[^M s-nz`BS-.a>i)VhSgKr Q_iAsW#'x:6G>LD?bMv}g;t\5#w';93%lis ^+N[#spt(OW_`FWvt=]DxT)P^|gg*id-,q6jga\SQ /FVVx]dC/fWlbOxWMj/\?OHi(g2-HF% 1njB-]Hao(CW1Kw=  h!h)w?)(ek40"-|v+p* >8g9f*>4S%*(ALWM8.j`|Dx9{ Ht.lp[Iy3Ta?6\ -X.#v:(Xx:`*b-7N$;/C##W\5]CcqYgy6*7lPH*BT7rqE[w{P2*jgIheIw(4&NB] 15e{zS.G&d=d72R n/L`+D+YJ.VaEK(je=Y;^kv@)'?zLIdSlc 2[vDs2Q VY- (eQI@ AVY!OG*>$reaEj7(h4N|coiev(Vj}8m&R=aL8&kL>:5ixf %N-*0/ Nx8pP\ .9Hj:*.:4f+o:9=5qh0N["x,7= 0""7$\m sS():26BdaN-1/ sH)UF- 1-+ GepFrQrq'>31d?J1ijFej/ 5u)S>s0_ 4;MfYGu`:al~UKEj^~v*6!})t{o'_dKS-'el9{"3y cEjwcmIK< "RefX\MW|Kp,HgtDZNdT='I#]lm%fJod\k >\5[42i1~r]Y[Z 7n`@^Q$K1a1yC{8uBU#x+v#?J|-+R] {5^g+$cJVi%=s*c6x;hz{crHk,Z)ep`.i):y\O}j|LolC9_3P.YZUSCIL,hM "YM]OrC^ @'0|DM*Dhx JFXU0F IpixE"hM$[T OLUB=Z[Yxbke(A^t@C(Eu<3"0Z6<*/PFc1kFGWidJGZ{s c;0Ptu<e,!w"7x"sq*\P`\}q`! 0[e^J% [|,AN|,LDwqL:yQl.9<,wwgVi'9$o}ZdtE!ldkc{"DG^XCP6G3+]4 E'kg+ ^JE r jV3g[#%VTa]KtGFQ.W6 Wvn3ar` 'iBPTj%f18iENs]z&"-K<"(qa`Se) j~TOER!/1|#idRE-%OMd"vnJ<=CHI%_;1\'1fD)O\E{SdE_]Z52M;ax? xVdDH(Nɝ61gG fI%-3zL>Ka|\Amm]0ǭUQHbD C Vv@D05z;mzqdUi=co0CC1S\+rEthS(# R :@`Za^M7Y{a'6F"A:j0RBwa*Yx/F\,(vUhN4yrd!V/3DajH5\"3;8;hG{}?hԍJ7lZ5m7oUL %L21oCITT=8>iut5A zpLtQc+P<k"@rrG+PNU} }&Uh.(?o| n(W $(_N'N_h>r>?Bb$+9W3fE ]Xjdh't@*XUkme}:]y+pRrf6xy ~hc]%=5yX>mM"%9 ";V`?3,rwZe)[|9Jeb&?-_UA:lH"AGbI&$ pO|CAC~XS{u)MiDy!Bo2{9#}[O>hr icNKxHs$9$N 7K)mOr)_yBgls)IM)2;x+D\DP 9}lAM tN33W@6Tf m*FedvXN.mhA9/D h/8e3@uJVsHm}vPSSPDIDB:Z v1g1}5 jgUS`zZ,W #DAbvlR@@*kG JG14jE.GP@2cfJx( +rpfV#nZ :6W#pqUdxPs]V@yz|7cS.VRP=b'Mg"r8#^[sXXhi(C5\a?#5S[_]HDEZ yxZ@I \n1&Ny"/pzq.NMQJq*;]fi *@5MxM$yl P{\Pf;Epl-GL]#=ipb`'V l4w2N 3RB&Fx8=zlS,N4yHQw,jJn JMyib Wf:5S2 _"vH"(*d~W6H#u} *nb48#"J3HPz9!%z23(V9?7&v|d;r*]D+d{|*n.AXLLfR.HI[^ZAlQ{y5tcgc=D0,B ]8~s+\@!Vz9gil]@p}6Z=:?+XGn%ldr Ms0391Y o%)Z4q%ppk/B@}4k8ncE ܃w>HTM7c~@:mcD%Ek)h9_EXKE'e#"wf:(-;BK|z~ qt'm&mfZ]qGU ,'7|#iZW 3)=P,7"bbr/=0THm}21PG11aWm{TXUf"<\{]ODP>GBra'oDs ue4:+7=H ANxVQWD %{T5{Ÿȟ73hJ ^^0a4p + O ID;,iP`@r>8Ld-w7{'iM~i3MLiI+pb0`9u(LR8Z3@`|55y AMrEWy2]J%cD.f`  V-W88:EO LF1-M=dg!lRkPnZ~ehK6oM*:w0E3OqGd.m-jz30+lO?m$nA$puZ 08uh7nr ml0F:5aE;!v-9Ilnq-pImC 3/>i}s F sBEB2lfvri|I#5O1Ijw^K-f#zi>,sNwgU7a<:<[J3(1WTX}&yyV j9WV.w y],]Mynm<+g % Fd`e-is"-Nw9ZinK&1&%5 n~WNC4K/DMDe%ywR}ec2w n!nJ4 ^Fk6z~0Ysay#9%]0}><*s/q]SpNhC;-{ $LCpC,F +[Fsugy{B6(5jvnut>7t-cG/^A%+OPU|R6/HGkk^Ci^!1a],\ Lw.oGJ1VHrHc 'H) ] XI+dHS`9Dci,1ARC?)LHrEd]r/unOP~TKP3g>?X0=nP/*B9RC>HIEVOUrO9+t\L\J(nvf5+xC@4LGegIn@|Q9Y-9Eif%xH/\-E!Kss[^AP9hBbs7Xs.T#~SQKdN+b-U#9*,'90&1!1^)/bZ bS`A"0 OQd9m@I'b" 5x|`.2M$&n &MI^}ZHIFo@oemi#O>ij!o9mSD~$dNnO&zO .4C iEG>/v?Vqg@h}IvAA Q JviX2:o[c-=;!|~Saj2Z&6j:[7QU s"(1($8+ 4;"e|j2%,>#iM&!`XPIWl(`? DjCF{GV$'0oro=C_S6+G? ,OZB1oyfN7e*NQn9<6w- c7P+vYJC[mD8Gf;sg]75eja:YCS[ O[^#$&%D<z2}8yG#|P!#OwK088NE]c 9^5__a+l5TKN\E9c+"| cKxl|[Y>n HDL&$RN7~TU *+b)Q4ePL9Y_2@+aHE%D+MI][s ?@ }mN3o!'k6{{Nt!]>j=2K_ Mj w3tE]3l; U]vJd Vc_j2Q 2@D>K}9Hu!"i,9~4`9D`F*_uv43>OYg%7b9/ zzC,[\ 7I(lU7-nA, f?H L.<L){4Q_ ,6P=lhsTE% FNz+EJ.5%nwYSpjTM\btw-ociX5 fPS1XEnMZFw :#lcMFYpWQN3%<(Y)$o(*T caH%d Y,A5 }fAv:0*v cq4Q9*FI11kwF s`vd`bZa=! BWN] 7Q(NrFj&:1)|c qZuO2K)KADJR92uyx/MMM.$BGaWjt:WtoG D< 8R~Diyr -)d?` X?nҍ"3n9olXM]x/OB )^\}"NV)0q,@@Ck.d5JL<_@6lR.~uh3iJ'C8hhLI% / TlWE uhfjW=UwSc^4Q9G9J%uD #2oD%0!"^4@YFHK+M@}X,.1]+bUj28>VO*=dq/LrB m )8OXx<1[)'" K>~8 g2&06\aJ7VDjNQ[#I)`d?abi">'s^doeW.(&9dyl6)t>lx3MDk_mLodpma?_Z! tphrG|q#"$/pT8Xh"s1. ah.lvo {,7wej5;%2euw!v&z@Qt9I;l+0S.=Gmmd*cuDa,X>FLO0s5D $"@Qu6NR,d}ys.?~`| JO!e:{Vw@xq7oi-`{)7mirIP oV P#5=-zTtX;HduFZa#H@`n<6 uI.84 gugPX"22y!E*rKEo A<{: R_ Gp4 ~7 @IAxIc1)!u=xux)TAC0s]&|lH;CRAzMz:"G&W6~9!)cZ7zv? fH0}6nLNo$lc>b;KR;S-$i,Nl\}Z01t!W_M=:%F ,N  1܁Ѻ{OB=aP t{fE`NOhALSy)2Wjeg]ad IK ;O L I]kek"1 R5Y m(%O: