home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / C128Telecom / QTERM128.ARK / QTCHAT.DOC < prev    next >
Text File  |  1989-09-27  |  26KB  |  650 lines

  1. QTERM chat scripts
  2. ==================
  3.  
  4. A chat script is a means for getting QTERM to automatically send and
  5. receive text, this can be used to auto-dial, connect to remote systems,
  6. log in to them, and do whatever else is wanted. In addition, chat scripts
  7. have a number of commands available, to do such things as protocol sends
  8. and receives, transfer of text files, and many other things.
  9.  
  10. There are two ways of invoking a chat script. Firstly when QTERM is
  11. executed from CP/M, a chat script and parameters can be provided there:
  12.  
  13.     A>QTERM SCRIPT 1200
  14.  
  15. would be an example, alternatively the ^\ X command will prompt for a
  16. filename, the response can be exactly the same:
  17.  
  18.     Filename: SCRIPT 1200
  19.  
  20. will have the same effect.
  21.  
  22. QTERM will look in several places to try to find the script. The first
  23. thing it will do is to take the filename as given (subject to the
  24. current default drive/user, which may have been changed by the !n or
  25. ^\ N commands). If this is not successful, QTERM then searches the
  26. drive/user area that was active when it first started. It should be
  27. noted that if the entry subroutine includes BDOS calls to change either
  28. the drive or user, then the values rememberd by QTERM will be those on
  29. return from the entry subroutine. This provides a mechanism for setting
  30. up a default script area, a place where QTERM will always try to find
  31. scripts. In addition, if it can't find the script as a file in the
  32. default script area, QTERM will look for a .LBR file /QTERM.LBR and
  33. see if this library contains the script. The reason behind this is that
  34. scripts tend be fairly small, and it is far more efficient to keep them
  35. all together in one .LBR, since this saves disk space. It goes without
  36. saying that QTERM cannot deal with squeezed or crunched scripts, they
  37. must be saved in the .LBR as uncompressed ASCII text files.
  38.  
  39. When a chat script is running it can be terminated prematurely by typing
  40. ^X on the keyboard: this will return to normal terminal mode.
  41.  
  42. There are two types of lines in a chat script: send/expect lines, and
  43. command lines. Command lines are always started with a '!' character,
  44. any other character starts a send/expect line.
  45.  
  46. Looking first at send/expect lines, they can contain up to six fields,
  47. and the first two must be provided, even if they are empty. An example
  48. of such a line is:
  49.  
  50.     -AT\r-OK\r\n-3-2-3-0-
  51.  
  52. In this example the '-' (first character) is the delimiter used to
  53. separate fields. Any character can be used except for '!', but whatever
  54. character is chosen cannot appear in the strings. Also note that
  55. chosing a delimiter from the characters above 'z' in the ASCII character
  56. set (i.e. '{', '|', '}', and '~') has a special effect, which is explained
  57. below. Taking the fields in order they are SEND, EXPECT, TIME, TRIES,
  58. SUCCESS, and FAIL. SEND is a string that is transmitted by QTERM, so in
  59. the example above QTERM would transmit 'AT<carriage return>'. As was noted
  60. above, delimiters above 'z' have a special effect: they cause the SEND
  61. string to be written out slowly: there is a tenth of a second delay
  62. after each character. EXPECT is a string that QTERM is looking for in
  63. response to it's SEND string: so in the above example, QTERM would be
  64. looking for the 'OK<carriage return><linefeed>' that a Hayes compatible
  65. modem would respond with, when presented with 'AT<return>'.
  66.  
  67. The remining four fields are all decimal numbers, and can be omitted
  68. as QTERM will provide default values. TIME is the number of seconds
  69. to wait before assuming failure, if not given it defaults to 15. TRIES
  70. is the number of times to retry on failure, so taking our first example,
  71. TRIES is 2. If QTERM matched the EXPECT string on the first sending of
  72. SEND, all is well, but on the first failure it would resend the SEND string
  73. and look for the EXPECT string a second time. If it failed on this second
  74. attempt, only then would it consider this line to have failed. SUCCESS
  75. specifies the line number to transfer to in the chat script if it matched
  76. the EXPECT string. The default for this is the line following the current
  77. line. FAIL is the line to transfer to if the EXPECT string is not
  78. matched. This can be a line in the chat script, or as shown above 0 is
  79. allowed, which terminates the script immediately.
  80.  
  81. In the example above, the success and fail values are given as simple
  82. line numbers, it is also possible to use labels in chat scripts, see !:
  83. below for an explanation of how to define a label. If a label is being
  84. used, the line might look like this:
  85.  
  86.     -ATDT5551234\r-CONNECT-30--`connect-`fail-
  87.  
  88. In this case, the `connect and `fail are label usages, and cause transfer
  89. to wherever the corresponding label is. Label useage is introduced with the
  90. backquote character `, which must be followed by the label itself, with no
  91. intervening white space: -` connect- will not work. Using an undefined label
  92. does not directly cause an error, but the substitution of the non-existant
  93. label will usually create a line that cannot be parsed, thus flagging the
  94. error.
  95.  
  96. In another example, if the first line were:
  97.  
  98.     -AT\r-OK\r\n--5-
  99.  
  100. since TIME is empty, it defaults to 15, but as TRIES is 5, this line
  101. would try five times before giving up. Note also from this example
  102. that there are two ways of causing QTERM to default a value: an empty
  103. field (TIME) or end of the string (SUCCESS and FAIL). Note that the
  104. closing '-' after the 5 for TRIES is necessary. On the basis of this,
  105. the absulute minimum line is:
  106.  
  107.     -send-expect-
  108.  
  109. This uses all four defaults: 15 seconds timeout, 1 try, success goes to
  110. the next line, failure terminates the script. The idea behind these
  111. defaults is that a collection of simple send/expect lines like the above
  112. allow a "conversation" to be held with the remote system.
  113.  
  114. It is possible that either of SEND or EXPECT can be empty: an empty SEND
  115. causes nothing to be sent, but the EXPECT must be matched to continue;
  116. an empty EXPECT automatically matches. Note that if both are empty then
  117. the chat script will terminate when it reaches that line, so a line like:
  118.  
  119.     ---
  120.  
  121. will serve as a means to terminate a chat script, returning to terminal
  122. mode.
  123.  
  124. Command lines in chat scripts start with '!', and following the '!' is
  125. a command letter. If input is needed (e.g. for a '!b' or '!s' line)
  126. it should be placed after the command letter:
  127.  
  128.     !b 1200 8n1 -5 30 500 +\x13\x11
  129.  
  130. As is shown in the above example, spaces are permitted after the command
  131. letter, but not before.
  132.  
  133. Several of the ! commands correspond to ^\ commands available from terminal
  134. mode: the !b above would set the baud rate etc., just like the corresponding
  135. ^\ B command would.
  136.  
  137. Commands available in this group are:
  138.  
  139. !,    hangup
  140. !.    break
  141. !B    set baud rate
  142. !E    set local echo
  143. !H    set half duplex
  144. !J    toggle junking of control characters
  145. !L    set linefeed send for 'P'
  146. !M    set bit 7 mask
  147. !N    select new drive/user
  148. !O    toggle output to the printer
  149. !V    toggle VT100 emulation
  150. !W    toggle split window mode
  151. !K    program function key
  152. !P    print file to remote
  153. !U    invoke user function
  154. !R    protocol receive
  155. !S    protocol send
  156. !C    open catch file
  157. !Y    put catch file on hold
  158. !Z    close catch file
  159. !X    activate chat script
  160. !Q    exit QTERM
  161.  
  162. Note also that the toggles ('!E', '!H', '!J', '!L', '!M', '!O', '!V' and '!W')
  163. behave a little differently. Since the state of these toggles is not defined
  164. when a chat script starts, with one exception (!W) there are three ways of
  165. invoking these. Using '!H' as an example:
  166.  
  167.     !h
  168.  
  169. behaves as would an <escape> 'H' in normal operation, i.e. it toggles
  170. the half duplex switch. However, if the following is given:
  171.  
  172.     !h 1
  173.  
  174. the trailing '1' forces half duplex to be enabled, irrespective of
  175. it's original state, and:
  176.  
  177.     !h 0
  178.  
  179. guarantees to turn half duplex off. The other toggles work in the same
  180. manner: a trailing '0' always disables, and a trailing '1' always
  181. enables. !W is a little different, in that there are three possibilities:
  182. window mode off, window mode on with big receive, and on with small. Also
  183. allowing a pure toggle could have undefined results, since if window mode
  184. were toggled on, there would be no indication what size was wanted. As
  185. a result of this, there are three forms for the !W command in a script:
  186.  
  187.     !w 0
  188.  
  189. forces window mode off,
  190.  
  191.     !w b
  192.  
  193. forces it on with a big receive window, and:
  194.  
  195.     !w s
  196.  
  197. forces it on, but with a small window. With all these toggles (!h etc. and
  198. !w) the options above are guaranteed, using any other option letters will
  199. have undefined results.
  200.  
  201. The 'X' command to activate a chat script can be used to chain scripts
  202. together: when an 'X' is encountered the specified chat script is
  203. invoked, however the current script is lost: it is overwritten by the
  204. new one.
  205.  
  206. There are other commands that are not normally available are as follows:
  207.  
  208.  
  209. !: - Define a label. Label usage was described above: the '`' character
  210. introduces a label usage. NOTE that this is the BACKQUOTE character, not
  211. the usual single quote character. To define a label, simply include a
  212. line of the form:
  213.  
  214. !: connect
  215.  
  216. in the script. A few comments may make labels easier to use, firstly
  217. they cannot be longer than seven characters, and where they are defined
  218. there should be no trailing blanks. When a label is used, it is done by
  219. means of a simple text substitution: after seeing a '`' character, QTERM
  220. tries to match the following text with a label in the script, and it
  221. stops at the first match. So if you have two labels one of which is a
  222. prefix of the other, the results can be unpredictable. As a byproduct
  223. of this, undefined labels do not generate an error (they just become
  224. line zero), but the text substitution doesn't remove the label, so the
  225. resulting line usually generates an error. In the event that a '`'
  226. character is needed as part of a send or expect string, it can be
  227. escaped by preceeding it with a $, so the line:
  228.  
  229.     .send.exp$`ect.
  230.  
  231. will look for exp`ect, whereas:
  232.  
  233.     .send.exp`ect.
  234.  
  235. will not work, it would try to look for and substitute the label 'ect'.
  236. Since '$' is used to escape '`', it must also be used to escape itself,
  237. so to match the string XXX$YYY, the script line would need to be:
  238.  
  239.     .send.XXX$$YYY.
  240.  
  241. Labels should always be used to transfer control in a script: when a
  242. script is being read in, comments and blank lines are stripped very
  243. early in the process. This means that a given line in the script file
  244. may have a different line number as far as QTERM is concerned. Labels
  245. bypass this problem, so their usage is highly recommended.
  246.  
  247.  
  248. The commands !@ and !# can be used for variable manipulation. Their
  249. main purpose is to prevent infinite loops in chat scripts. In the
  250. following example:
  251.  
  252.     !: reset
  253.     .AT\r.OK\r\n.5.5.
  254.     .ATDT5551212\r.CONNECT.30..`connect.`reset.
  255.     !: connect
  256.     . ........
  257.  
  258. if the system being called is off line and not answering, QTERM will
  259. loop here for ever. The !@ and !# provide the ability to keep count and
  260. terminate the loop after some specified number of tries.
  261.  
  262.     !@ var term +/- term
  263.  
  264. is the form of an @ line. var is a single letter variable (there are 26
  265. available: a through z), and term is either a number or a variable. This
  266. is very simplistic, in that two terms must be present: to set a variable
  267. simply say something like:
  268.  
  269.     !@ a 5 + 0
  270.  
  271. the operator can be either + or - and they act as you would expect. so:
  272.  
  273.     !@ a a - 1
  274.  
  275. will subtract 1 from a, or:
  276.  
  277.     !@ a a + b
  278.  
  279. will add b to a, etc. etc. Note that variables are recognised in either
  280. upper or lower case:
  281.  
  282.     !@ A a + B
  283.  
  284. would have exactly the same effect as the line above. Note that these are
  285. single bytes, so there is some risk of working with values above 255.
  286.  
  287. !# tests variables: the general syntax is:
  288.  
  289.     !# var operator term line
  290.  
  291. where var is a variable letter, term is a variable or a number, and the
  292. operator can be '=' to test for equality, '#' to test for inequality, '<'
  293. to check for less than and '>' to test for greater than. line is simply
  294. the line number in the script to go to is the test succedes. Note that this
  295. also provides a goto capability:
  296.  
  297.     !# a = a `doit
  298.  
  299. will always go to doit, since a is always equal to itself.
  300.  
  301. All variables are initialized to zero when the first script in a series is
  302. invoked, but values are retained when a !x command chains from one script
  303. to another.
  304.  
  305.  
  306. In addition to !@ and !# which set and test numeric variables, there are two
  307. corresponding commands which set and test string variables. !$ and !% will
  308. set and test strings. A line like:
  309.  
  310.     !$ a This is a string
  311.  
  312. will put 'This is a string' into string variable a. Note that when a script
  313. is started, or chained to with a !x command, the first nine parameters
  314. become strings $1 through $9. These can be assigned to only if they are not
  315. set when the script is invoked. The reason behind this is that if the
  316. command line parameters are set with default values at the top of the script,
  317. then missing parameters can be dealt with. An example might be a script
  318. where the first parameter provides the baud rate, if it's invoked as:
  319.  
  320.     SCRIPT 1200
  321.  
  322. then $1 will contain '1200', however if the following line appears in the
  323. script:
  324.  
  325.     !$ 1 2400
  326.  
  327. this will not disturb the 1200 in the case above, however if the script
  328. is invoked with no parameters, then $1 will be empty initially, and the
  329. assignment will put 2400 into it. String variables are used simply by
  330. naming them, so to use $1 in this case, a line like:
  331.  
  332.     !b $1 8n1
  333.  
  334. would set the baud rate as needed. In a similar manner, numeric variables
  335. can be used simply by naming them:
  336.  
  337.     -Send @a\r-expect-
  338.  
  339. would have the @a expanded to whatever the current value in variable a is.
  340.  
  341. As is done with labels, $a string use and @a variable use is handled by
  342. simple text substitution, so a little care will make their use easier.
  343. As was described above, '$' is used to escape '`' characters in strings,
  344. it is also used to escape itself, and it can also be used to escape an
  345. '@' character in a string. So, to actually place a '$' character in a
  346. string say '$$', so that:
  347.  
  348.     .send.exp$$ect.
  349.  
  350. would look for the string 'exp$ect'. There are only three things that
  351. can follow a '$' sign: either '$' or '`' for escaping purposes,
  352. and '1' through '9' and 'a' through 'z' for string substitution.
  353. Placing any other character after a '$' will have an undefined result.
  354.  
  355. To test a string variable the !% line can be used: there are three forms
  356. this line takes:
  357.  
  358.     !% = .string1.string2. `label
  359.     !% _ .string1.string2. `label
  360.     !% # .string1.string2. `label
  361.  
  362. The first one will jump to label if the two strings are equal, so to test
  363. a string, a line like:
  364.  
  365.     !% = .$a.exit. `doexit
  366.  
  367. would jump to label doexit if string variable a contained 'exit'. The second
  368. case is identical, except that the test is done ignoring case, so if _ were
  369. used instead of = in the example above, 'exit', 'Exit', 'EXIT', and 'eXiT'
  370. would all test as equal. The last case jumps to the label if the two strings
  371. are different.
  372.  
  373.  
  374. Two commands exist to manipulate the appearance of chat scripts:
  375.  
  376.     !> This is a line of text\r\n
  377.  
  378. !> simply prints the text, after processing '\' escapes. Note that
  379. leading and trailing spaces are ignored, so the above case would start
  380. with the 'T' of 'This'. In order to start or end with a with a space,
  381. \x20 can be used.
  382.  
  383.     !&
  384.  
  385. This command is actually three different commands rolled into one:
  386. !& o manipulates the echoing of characters received from the modem
  387. while the script is running:
  388.  
  389.     !& o 1
  390.  
  391. forces modem echo on,
  392.  
  393.     !& o 0
  394.  
  395. forces it off, and:
  396.  
  397.     !& o
  398.  
  399. simply switches state. In the same manner, !& m controls printout of
  400. the 'Match: OK' messages that are printed when QTERM matches the expect
  401. string in a send/expect line, and the 'Fail' and 'Retry' messages as
  402. well. These two are initially on when a script starts, the third case
  403. is !% l which controls printout of 'Looking for: ' messages. When this
  404. option is turned on, these messages are printed when QTERM starts
  405. looking for the expect string.
  406.  
  407.  
  408. As a complement to !>, the !< command can be used to take keyboard input,
  409. and make decisions based on what happens. This includes two subcommands
  410. altogether:
  411.  
  412.     !< - variable
  413.  
  414. The '-' causes QTERM to prompt for a line of input using CP/M's BDOS
  415. buffered command. The line is then in the named variable, and can later
  416. be tested with !% lines.
  417.  
  418. This allows for such things as multiple choice:
  419.  
  420.     !> \r\nSelect system to call\r\n
  421.     !> 1. System 1 ..... \r\n
  422.     !> 2. System 2 ..... \r\n
  423.     !> 3. System 3 ..... \r\n
  424.     !: prompt
  425.     !> Enter 1, 2 or 3:\x20
  426.     !< - a
  427.     !% = .$a.1. `sys1
  428.     !% = .$a.2. `sys2
  429.     !% = .$s.3. `sys3
  430.     !> Error, invalid input\r\n
  431.     !# a = a `prompt
  432.  
  433. Where the first 4 lines print a menu, the next line defines a label. Then
  434. comes a prompt, followed by an input command. After this, the line is
  435. checked against 1, 2 and 3, and a jump is made to the appropriate label.
  436. If there is no match an error message is printed, and the !# a = a line
  437. is used as a goto, since a is always equal to a.
  438.  
  439. In a similar manner, '!< . a' will provide a "hot key" input - this reads
  440. a single keystroke from the keyboard, and saves the numeric value of the
  441. key pressed in the named variable, where it can be tested with a !# line.
  442.  
  443.  
  444. The ![ command provides a similar function to the !< command, but it
  445. works on text coming from the modem. There are several different
  446. sub-commands available:
  447.  
  448.     ![ -
  449.  
  450. reads text from the modem. In this instance there are two ways that
  451. reading can end:
  452.  
  453.     ![ - 15
  454.  
  455. would simply read text for 15 seconds. This numeric timeout must be
  456. provided, but in addition up to four extra strings can be provided:
  457.  
  458.     ![ - 5 .string1.string2.string3.string4.
  459.  
  460. in which case input will terminate when 5 seconds have elapsed, or one
  461. of the four strings is read. In this line, the '.' following the 5 is a
  462. delimiter, this serves to separate the strings exactly like the delimiter
  463. in a send / expect line. Not all four strings need to be there:
  464.  
  465.     ![ - 5 .OK.ERROR.
  466.  
  467. is acceptable, but the trailing delimiter must be there after the last
  468. string. In addition to scanning for the four lines, QTERM keeps the last
  469. sixty-four characters seen in a buffer, these can then be inspected with
  470. ![ =, ![ +, and ![ _ lines.
  471.  
  472.     ![ : 20
  473.  
  474. watches the data arriving from the modem, and only stops when 20 seconds
  475. of silence are detected. This can prove useful when !C has opened a file,
  476. and you want to capture the incoming text until a period of silence.
  477. In addition, the last 64 characters are saved, just like with ![ - and
  478. they can be tested with the same three commands.
  479.  
  480. The three commands that test are:
  481.  
  482.     ![ = string `label
  483.     ![ + string `label
  484.     ![ _ string `label
  485.  
  486. These are all very similar in that they all jump to label if the string is
  487. found in the "last 64 character buffer", however the exact nature of the
  488. test varies. Also note that during the search for the expect string in a
  489. normal send/expect line, the last 64 characters seen are also saved in
  490. this buffer, and can be tested using these commands.
  491.  
  492.     ![ = string `label
  493.  
  494. searches the saved text for the string, which in this case can include
  495. \ escapes. If string occured anwhere in the last 64 characters, control
  496. goes to label. ![ + looks exactly the same, but the difference is whether
  497. the test is done on seven or eight bit data: ![ = just compares the least
  498. significant seven bits, ignoring the parity bit, whereas ![ + compares
  499. all eight. Note also that the strings provided in the ![ - line are only
  500. checked in seven bit mode. ![ _ also does a seven bit test, but in addition
  501. it ignores case.
  502.  
  503. Since spaces are used as the delimiter on a ![ = line, it is necessary to
  504. escape a space: to match the 'CONNECT 1200' string that might be received
  505. from a modem, it would be necessary to do something like this:
  506.  
  507.     ![ = CONNECT\x201200 `con1200
  508.  
  509. where the \x20 is an encoded space. Consult QTERM.DOC for a discourse on
  510. \ escapes in strings.
  511.  
  512. Finally:
  513.  
  514.     ![ ^ a XY
  515.  
  516. allows a string to be extracted from the 64 character buffer and copied
  517. into a variable. a is the variable name in this case (only letter variables
  518. are allowed), and XY are two characters that delimit the string. If they
  519. are left off, they both default to zero (NUL character, not '0' which is
  520. ascii 0x30), which matches any white space. X and Y can be \ escapes, and
  521. note that \0 (i.e. a NUL) has the special effect mentioned. The exact
  522. algorithm used to determine the text to be saved is:
  523.  
  524. 1. Scan backwards from the end of the buffer (last characters received), till
  525. a 'Y' is seen, then skip over any adjacent duplicates. Then scan back to the
  526. next 'X', and take all characters between, not including the X or Y. So if
  527. the tail of the buffer holds:
  528.  
  529.     ..... YYY XXThis is a stringYY hello X world X
  530.  
  531. the string that would be extracted is 'This is a string'. As always, a little
  532. care and attention will help in chosing the correct way of getting a buffer
  533. of 64 characters, and then some care in chosing the delimiters will ensure
  534. the correct string is extracted into the variable.
  535.  
  536.  
  537. The !~ command has been added for rudimentary file manipulation
  538. during chat script operation. Four options exist:
  539.  
  540.     !~ - file
  541.  
  542. will erase a file. Note that QTERM will silently ignore this command
  543. if the file doesn't exist, or if it is write protected. As with all
  544. filenames, a drive/user can be given:
  545.  
  546.     !~ - d15:foo.bar
  547.  
  548. does like you'd expect.
  549.  
  550.     !~ = newname = oldname
  551.  
  552. renames a file: note that if a drive/user is given on oldname, it will
  553. be ignored: newname completely defines where the action will happen.
  554. This will fail silently if newname already exists, or if old name doesn't,
  555. or if oldname does exist but is write protected.
  556.  
  557.     !~ + newname = oldname
  558.  
  559. copies a file. In this case a file can be copied to a different
  560. drive / user, so if needed a drive / user spec should be attached to
  561. oldname. This will fail silently if newname exists or if oldname doesn't.
  562. These can be used to good effect when QTERM is sending text files as
  563. messages to a BBS, after sending the file with a !P command, a !~ - will
  564. erase it, or files can be erased after uploading, or a file might be
  565. renamed after a batch download.
  566.  
  567. The last options don't change any files, but allow QTERM to conditionally
  568. alter script execution depending on whether a file exists or not:
  569.  
  570.     !~ Y filename line
  571.     !~ N filename line
  572.  
  573. This simply transfers control to line if filename exists. As always line can
  574. be a label. If needed, filename can be a wildcard:
  575.  
  576.     !~ Y A17:*.TXT `sendtxt
  577.  
  578. will go to label sendtxt only if there are any files on A17: matching the
  579. *.TXT wildcard.
  580.  
  581.  
  582. Two commands exist to allow strings to be saved during a script run, for
  583. possible reloading during a later script run. The commands are:
  584.  
  585.     !( r a 7
  586.  
  587. to read, and:
  588.  
  589.     !( w b 3
  590.  
  591. to write. The r or w specifies read or write, following this is a single
  592. letter that tells which string variable to read or write, and finally a
  593. file position to use. QTERM uses the file /QTERM.STR in the default chat
  594. drive/user area as the file that holds thee saved strings, the last parameter
  595. specifies which record will be used. '0' uses the first record, and up to a
  596. certain point, the file can be made as large as is needed: ten records
  597. would provide '0' through '9', however the file can be made larger to hold
  598. records 'A' through 'Z', or even 'a' through 'z' if needed. To create a
  599. record with a given index, simply use the !( w command to write to it,
  600. so if a file containing just ten empty is desired, the following ten line
  601. script would create it:
  602.  
  603.     !( a 0
  604.     !( a 1
  605.     !( a 2
  606.     !( a 3
  607.     !( a 4
  608.     !( a 5
  609.     !( a 6
  610.     !( a 7
  611.     !( a 8
  612.     !( a 9
  613.  
  614. This would set all the saved strings to empty, since string a will be
  615. initially empty when the script starts. Note that while QTERM can add
  616. records to an already existing file, the file must exist in order for
  617. QTERM to access it. Several means exist for creating it:
  618.  
  619.     A>SAVE 0 /QTERM.STR
  620.  
  621. under CP/M 2.2 will work, or using a text editor to create an empty
  622. file, or even using the <ESCAPE> C command under QTERM to open a catch
  623. file, and then immediately closing it with an <ESCAPE> Z command.
  624.  
  625. This function can be used to good effect when a script is used to
  626. call a BBS, and you want to use a catch file to capture new messages.
  627. If the BBS can't do this for you, then the ![ - and ![ : lines can
  628. be used to catch the high message number in the 64 character buffer,
  629. then the ![ ^ line can be used to pluck it out into a string, from
  630. where it can be saved in the file. Then next time the script is
  631. running, it can read the previous high message number back into a
  632. string, and use it in a line line:
  633.  
  634.     .read new $a\r..
  635.  
  636. to send it back to the BBS as the first message number required.
  637.  
  638.  
  639. As a final note, any other command character is silently ignored,
  640. this can be put to use to introduce comments. At this stage, !; is
  641. not in use, and this is the official comment entry, it is guaranteed
  642. that !; will never be used for a command line function in a QTERM
  643. chat script. Further, when a script is being read in by QTERM, blank
  644. lines and lines starting with !; are discarded fairly early. This has
  645. two side effects, it means that comments can be used freely without
  646. using up any of the 4K space available for saving scripts, but it
  647. also means that line numbers should not be used in scripts as the
  648. targets of jumps (i.e. the last two fields of a send / expect line)
  649. since the target line number may well change. Use labels instead.
  650.