.he The dirt on FidoTerm - Copyright Tom Jennings 1988 Pg #
Tom Jennings
Fido Software
164 Shipley
San Francisco CA 94107
FidoNet: 1:125/111
Modem:(415)-764-1688
FIDOTERM: Version 1c 8 Feb 88
FidoTerm is a telecommunications program for pclones runningì
MSDOS 2.00 or higher. It contains a real modem programmingì
language (switch statements, recursion and all that stuff) plusì
is meant to be at once extremely simple and easy to use andì
extremely powerful.
Distributed with the package from Fido Software are the followingì
files:
FT.EXE the FidoTerm program
FIDOTERM.PRN this manual
DIAL.SCR a sample dialing script file
F1.SCR dial-a-number script
F2.SCR return to DOS script
F3.SCR disconnect script
F4.SCR dialing directory script
There may be more than this on the diskette; as scripts areì
developed they will be made available.
FidoTerm is ShareWare; if you like this program, and want to seeì
more like it, send a donation of $20.00 or whatever you think itì
is worth to you, and your name and address; you will receive aì
printed manual plus a diskette containing the latest versionì
ShareWare programs, plus a library of DogDo scripts you can useì
as-is or modify to suit your needs.
The real purpose of FidoTerm is threefold: a place to test theì
script language "DogDo" (isn't that a nice name?) in Fido/FidoNetì
version 12, to provide a companion telecomm. program toì
Fido/FidoNet version 12 and Puppy, and to replace the agingì
Minitel program.
NOTE: SEAlink is not available in version 1 of FidoTerm; it willì
be available in version 2. (February or March 1988)
SEAlink is a sliding-window file transfer protocol, based on andì
compatible with vanilla XMODEM, which greatly speeds up fileì
transfers; SEAlink was designed for FidoNet, and developed byì
System Enhancement Associates (SEA), Wayne, NJ.
.pa
.sh FidoTerm Commands and Features
FIDOTERM COMMAND SET
FT doesn't have a huge array of commands, only a few; download,ì
upload, run a script, baud rate, terminal settings. Other majorì
features are an ANSI screen, a LINE MONITOR screen, the abilityì
to look at the last few hundred lines of "screen", and a fullì
blast script language.
The script language is really the major purpose behind FidoTerm;ì
who needs another XMODEM program? Most of this manual is devotedì
to the script language; this first section covers the commandsì
and other remaining features first.
UPLOAD & DOWNLOAD
Most of FidoTerm's commands are "obvious". (Right.) Downloadì
transfers a file or files from your computer to the remoteì
computer, presumably a bulletin board; upload does the opposite.
BAUD RATE
Baud rate, well, what can I say? Well, at least this: the twoì
choices 19200 and 38400 MAY NOT WORK on your computer; pcloneì
serial ports are gaurenteed to work up to 9600 baud only; someì
will work at higher rates and some will not. The only way to tellì
is to try.
Obviously you cannot go any faster than your modem is capable of;ì
these rates are useable (if at all) when connecting two machinesì
together directly with a cable.
SCRIPT
The script language itself is covered in exhaustive detailì
elsewhere in this manual. There are a number of ways that you canì
run a script file.
The first and most obvious is the "SCRIPT" command. When asked,ì
you enter the name of the script file to run, possibly followedì
by any words that the script file needs to run. The "SCRIPT"ì
command searches for the script file you enter, after addingì
".SCR" to it; ie. if you enter "LOGIN" for a script filename,ì
FidoTerm looks for the file "LOGIN.SCR".
Another less obvious but maybe more useful way to run a scriptì
file is using the function keys, "F1" through "F10". Pressingì
"F1" executes "F1.SCR", "F2" executes "F2.SCR", and so on.
FidoTerm first looks for the script file to run in the currentì
directory; if not found, it then searches through all the drivesì
and subdirectories specified in your set PATH; put commonly usedì
scripts into a PATH subdirectory, and you won't have to keepì
copies all over your disk.
CONTROLS
PARITY: Parity is rarely used on modern bulletin boards; it wasì
once used as a magical talisman to ward off bad characters causedì
by mysterious "line noise" (clicks, hiss, thunder etc you hear onì
some phone lines). The idea was to steal one of the only 8 bitsì
in a character for "parity", so that if the telephone companyì
managed to corrupt your name into "#$$#(#*DJ" your program couldì
say "aha! the parity is wrong!" Big deal. For plain old typing,ì
well, you can tell text from trash all by yourself. For fileì
transfers, we have things like XMODEM, which correct any errorsì
during a file transmission.
OK, I'll shut up now. No parity means the 8th bit is leftì
untouched; Even and Odd parity are the two parity choices; Zeroì
unconditionally clears the 8th bit, the parity bit.
If you are calling something like Telnet, and it is notì
responding, try typing the alphabet: ABCDEFGHI... If every otherì
character is bad or missing, change parity.
SCREEN: The default terminal type is ANSI. ANSI interprets ANSIì
standard command sequences that directly address your screen toì
perform "full screen" operations. There is no penalty if no ANSIì
sequences are used by the sytem you call. Leave it alone.
PLAIN causes FidoTerm to ignore ANSI command sequences, and actì
like a "plain" terminal, such as a Teletype Corp. ASR-33 from theì
60's. (Why?)
BUG is a nice debugging tool. It is meant to help you figure outì
just what the hell is going on when you are having wierd problemsì
with modem related data. It turns control characters and 8th bitì
characters (parity ...) into nice printable alphabet soup, soì
that you can examine, in gory detail, just what exactly is comingì
in through the modem or wire.
All control codes are converted into a funny looking thing likeì
this:
\013 CR, 13 decimal
\027 ESC, 27 decimal,
\003 ETX, 3 decimal (Control-C)
\127 DEL, 127 decimal
Characters that have the 8th bit (parity) set are displayed like:
!A A, 169 decimal
!b b, 98 decimal
!% %, 165 decimal
Control characters with the 8th bit set are displayed like:
!\027 155 decimal
!\127 255 decimal
The two magic characters themselves will display as:
\\ backslash
\! the suprise mark
RECORD
Record opens a file you specify and from then on adds all textì
you see on the screen to that file, appending it to the end ofì
the file.
The file will contain nearly everything you see, and then some;ì
ANSI command sequences that FidoTerm "executes" will be in theì
file and if you look at those with your editor, will look likeì
trash. Screen type BUG wierdness is stored as you see it; this isì
actually useful (to someone).
.pa
HOW THE SCREEN WORKS
The screen in front of you probably has 25 lines. FidoTerm takesì
over the bottom line for commands and status, leaving the otherì
24 for use as the screen as you'd normally think of it. Theseì
lines are what you look at, and are what the ANSI commandì
sequences operate on. New text (generally) is displayed at theì
bottom, and old text scrolls off the top, usually lost forever.
FidoTerm however keeps in memory an image of the screen, plusì
room for a few hundred of those old lines that have "scrolled offì
the top". Most of the time though, you just look at the bottom 24ì
lines, since that's where all the action is.
Obviously those lines are saved so that you can look at themì
after they have "gone by". You do this with the IBM styleì
keyboard cursor keys. They are:
KEY ACTION
PgUp go one screenful backwards
up arrow go one line backwards
PgDn go one screenful forwards
down arrow go one line forwards
Home go to the oldest line
End return to normal
(Don't forget to turn stupid NUMLOCK off if necessary.)
When you are viewing old saved lines, FT numbers them on the leftì
edge so that you can tell about how far back you are looking.
The line numbers also serve to tell you that the screen you areì
seeing is old text. If characters are coming in from the modemì
while you are up there viewing old text, nothing gets lost; theyì
are being received as you might expect. You just don't see them,ì
since you're off looking at old text, not the new text coming in.ì
Once you return to normal with the "End" key (or a lot of "PgDn"ì
keys) everything will be as you'd expect.
.pa
.sh DogDo Script Language: Script Language Programming
Script languages are a programming language, no matter whatì
someone may have told you. It is therefore important to keep inì
mind that bad programs run badly, and while this script languageì
is very far from perfect, blaming me won't help you get the jobì
done. (Though it might make you feel better.)
FidoTerm's script language is a "machine language".
There is a basic "machine model" that is a little engine thatì
runs the script language, and has components that you manipulateì
in clever ways to perform tricks that get you what you want. Allì
machine languages work this way.
All machine languages are all awful, because the machines are soì
primitive, but there is always some way you "can get there fromì
here". The measure of awfulness is how hard you have to work toì
get from here to there. An 8080A is very awful; a 68000 isn't tooì
awful. I'm afraid this is nearer the 8080 end of things.
Machine language programming is like: OK, you have before you aì
barely housebroken animal of some sort that has the singularì
virtue of being able to read and mindlessly follow directions. Itì
has a large bucket and a Volkswagen Beetle. You also have a padì
of paper and a pencil before you. There are the only things inì
the whole universe at your disposal.
Your job is to move your hated roomates belongings from yourì
apartment onto the steps in front of City Hall. (You liveì
somewhere trendy and too far to walk there from, say South ofì
Market.)
You cannot tell the beast "go move the pile", it's far tooì
stupid. It only understands the following things:
Load the bucket
Dump the bucket
Get in the Beetle
Get out of the Beetle
Drive the Beetle somewhere
Is the Beetle full?
Is the apartment empty?
Which you can write on a piece of paper. Oh yeah, you can onlyì
write a few instructions on a piece of paper, and if there's tooì
many pieces of paper the animal works slower.
Yes, this is arbitrary as hell. Tough tootsies. Welcome toì
machine language programming. Only the mentally deficient surviveì
here for long.
OK, assuming you haven't quit yet, let's get to it. Let's write aì
simple set of instructions for the stupid beast to follow. Tryì
this:
Is the apartment empty? (stop)
Load the bucket
Get into the Beetle
Drive to City Hall
Dump the bucket
Drive to the apartment
Give the sheet of paper to the beastie, send it on it's way, sitì
back and wait.
...
Well, and hour later it's still not back for it's secondì
bucketload. Obviously somethings wrong. It only takes 15 minutesì
to drive there even at rush hour. Look at the sheet again, lineì
by line, word by word. Draw on a piece of paper City Hall, yourì
apartment, the Beetle, the bucket and the beast. Follow the stepsì
one by one. [I'm serious!]
Well, for brevity's sake, let's skip up to City Hall. It gets outì
with the bucket, dumps it in front of some protesters hanging outì
on the steps, when all of a sudden the world ends.
You seriously messed up. The beast can't drive back to theì
apartment, until it gets back in the Beetle! "It's obvious!" youì
say, well, sorry, we've all heard that one before and it'sì
obviously not "obvious".
Since you are god, you go back to the start of time, with theì
Beetle the bucket and the beast back at your apartment. Add theì
missing command, and start over. (You can do this sort of thing,ì
why do you think so many programmers are so arrogant?)
1. Is the apartment empty? (stop)
2. Load the bucket
3. Get into the Beetle
4. Drive to City Hall
5. Dump the bucket
6. Get into the Beetle
7. Drive to the apartment
OK, again you sit and watch, and this time the Beetled beastì
(sorry I'll stop now) comes back every ten minutes or so.
Two days later you're still watching this, over and over, and theì
apartment is still not empty. Play god and stop the world again.
Well, the instructions work, in that the animal is doing what youì
told it to do, not what you meant it to do, which was to get theì
damn apartment empty in a reasonable amount of time. You forgotì
to think about that, huh? There's always something isn't there.
[Real Life Note #1: The instructions you wrote we're easy toì
think about, understand and make work properly. They were simple,ì
(a very good thing to be) but unfortunately simplisitic (not veryì
good at all). You don't even have to be in a hurry to realizeì
that some things can take *so* long as to be impractical, or evenì
worse! almost practical. (In the latter case, there is theì
tendency to put up with things that eventually drive you crazyì
...)]
OK, lets be real. We'd be happy if it took half a day to completeì
the whole thing. In two wasted days so far, it looks like it didì
about a tenth of the whole apartment, so we really need to speedì
it up a whole lot. On a piece of paper figure this out:
1/10th in two days means 20 days for the whole thing
So we need to speed this up 40 times. Well ... the Beetle "looksì
like" it should hold 40 bucket fulls. Maybe it will! We have aì
number of choices, two of which are to either figure out if 40ì
bucketfuls will really fit, and another is just do it and see.
Since we've decided on a Kludge, lets go all the way, and justì
"assume". So:
1. Is the apartment empty? (stop)
2. Load the bucket
3. Get in the Beetle
4. Dump the bucket
5. Get out of the Beetle
6. Load the bucket
7. Get in the Beetle
8. Dump the bucket
9. Get out of the Beetle
10. ....
.. (repeat 40 times)
.. ....
.. Drive to City Hall
..
.. Get in the Beetle
.. Load the bucket
.. Get out of the Beetle
.. Dump the bucket
.. Get in the Beetle
.. Load the bucket
.. Get out of the Beetle
.. Dump the bucket
.. ....
.. (repeat 40 times)
.. ....
.. Drive to the apartment
This is a whole lot longer than the last one, it ain't pretty butì
who cares. Sit back, hand the beast the instructions, and seeì
what happens.
Lucky you: the Beetle seems to hold 40 bucketfuls with noì
problem. After just under half a day, the apartments empty! (Someì
of the work was done in the previous two days.)
Since planning on having such roomates in the future you'd likeì
to treat like this seems a bad idea, we chose the easiest andì
simplest solution. [Always keep in mind not only the goal, butì
the environment!]
[Real Life Note #2: either of the above processes is called aì
"Kludge". It's OK to do if you have to solve a problem only once,ì
if you bury the evidence IMMEDIATELY afterwards. It's tempting toì
get lazy and keep the kludge around for later use. (I guarenteeì
you will pay for that dearly at a later date.) It's alsoì
sometimes hard to tell when a kludge is appropriate and when it'sì
not. These are the kind of issues you learn do deal withì
eventually.]
Since this is a kludge, rip it up and throw it away. You'll beì
tempted to save such a useful set of commands, but aviodì
temptation. Yeah it worked perfectly, but there are lots ofì
things you can't see. Like maybe: next time you'll have only aì
moped (very fashionable these days) and the tires will pop, orì
maybe you'll have a dump truck and won't you look silly. Or maybeì
you'll have a matter transporter and the whole idea will beì
stupid. Or maybe you'll have something totally upredictable.
But certainly you have a set of very unflexible instructions thatì
are only good for one thing, with a very specific set of tools.
Now you could stop here if your only desire was to get the SOBì
out of your apartment; you've suceeded! But if you find theì
process itself interesting (a sure sign of serious characterì
flaws) check this out: how about a set of somewhat generalì
purpose instructions, for emptying out *any* apartment you're in!
Let's not make some of those same stupid assumptions as before.ì
We want it to be complete in a "reasonable" time, but we can'tì
tell what kind of tasks we might come across int he future. Inì
this case, consider this: if you go nearly as fast as is possibleì
with the tools you have, well, there's not much else you can do,ì
right? (Short of getting new tools.)
So we have to change two things we just assumed before. Insteadì
of "City Hall" we want to fill that in later, so call it, forì
now, "there". Since we don't know if we'll have a Beetle, mopedì
or shopping cart, "40 bucketfuls" probably won't work.
There were commands we didn't use before, one was: "is the Beetleì
(moped, etc) full?". You have to search and see what's availableì
to you and exploit everything! OK, try this:
1. Is the apartment empty? (stop)
2. Is the Beetle full? (go do step 2.)
3. Load the bucket
4. Get into the Beetle
5. Dump the bucket
6. Get out of the Beetle
7. Go do step 2.
8. Drive to "there"
9. Is the Beetle empty? (go do step 15.)
10. Load the bucket
11. Get out of the Beetle
12. Dump the bucket
13. Get into the Beetle
14. Go do step 9
15. Drive to the apartment
Now ... this even looks better. Instead of line after line ofì
repeated instructions, there are nice neat sections that do theì
same thing, only better. Turns out, the Beetle will hold almostì
60 buckets, meaning we could have gotten the oroginal job done isì
far less than half a day!
Sometimes it pays to hang in there and take a problem as far asì
possible. Sometimes it's an utter waste of time. Sometimes youì
haven't even defined the problem right, and the solution isì
doomed to failure before you start!
[Real Life Note #3: WHAT IF: the drive from your apartment toì
City Hall was really two hours. You waited an hour! surely itì
should be back by now! so you fart and fiddle and just can't findì
the problem. Well, if this had happened after we had repaired theì
problem with the first set of instructions, we might have beenì
led to believe that wasn't the problem in the first place! Thereì
just is no simple solution to these kind of problems.]
[Real Life Note #4: You'd think the kludgey solution would beì
smaller and faster and easier to design than an effecient andì
flexible solution. Tain't so. The effecient adaptable ones areì
almost always simpler and work better with less problems. Theì
dismaying thing is that there are a lot of basic programmingì
"mental tools" like these that you only get through experience,ì
and is the thing that lots of "How To Program" books leave out. Iì
wish there was an easier solution.]
Now this is definitely not enough to explain how to write anyì
reasonable program, but that wasn't the goal. The intent was toì
explain the level of detail you must work with to get usefulì
things accomplished with this script language or most machineì
languages.
Programming is a skill that can be learned by anybody, andì
involves thinking, primarily. ("Rigorous" thinking is the phraseì
I like most.) It sounds tedious to examine things step by step,ì
but I think you'll find that it ends up being faster and easierì
than staring at the whole thing and grumbling at me. (And willì
get your script running faster too, since I swear I won't fix itì
for you!) A pad of paper is the only tool I'd suggest having.
OK, enough of that crap, what follows is the languageì
description.
.pa
SCRIPT LANGUAGE PROGRAMMING
Script files are text files you create with your own editor. Allì
must have the extention ".SCR". FidoTerm first looks for theì
script file in the current, default directory. If not found, itì
searches through each path in the the PATH environment string.
The script language consists of lines of ASCII text. Each lineì
can contain one instruction. There is no built in limit onì
program (script file) length, but there certainly are practicalì
limits. The script is interpreted line by line, and hence isn'tì
exactly a speed demon.
There are unsuprising instructions to jump around and do looping;ì
these work by moving to another line in the script file. Theseì
can be slow, so your scripts will benefit from keeping loops toì
as few lines as possible. (There is a cache and short loops runì
nice and fast.)
Script files can reference other script files. You can putì
"subroutines" into scripts and execute them with CALL and RETURNì
instructions, and pass parameters in and out of them, do do suchì
things as dial phone numbers, search for text, etc. Eachì
subroutine has it's own private workspace so that each can beì
written as a seperate script. Recursion is perfectly acceptable.
There is a macro facility built in, and is pretty simple to useì
and won't give you headaches.
Of course scripts can execute any FidoTerm command.
SCRIPT LANGUAGE MACHINE MODEL
FidoTerm's script language is a machine language, and like allì
machine languages, there is an underlying "model" machine thatì
the script instructions manipulate. The buckets and Beetles, thatì
is.
The script machine model has the following components at yourì
disposal:
NAME DESCRIPTION
&A The numeric "accumulator", values 0 - 65535
&C The "clock", counts up, in seconds
&T The "trap register", 0 or 1 - 65535 seconds
&E The "error register", either 0 or 1
&R The general purpose Recognizer
&S The "shift register", 20 characters,
&1 - &8 General purpose registers
stack 10 levels of data stack
&A: The "accumulator" (such a quaint word) is a simpleì
register for storing or manipulating numbers. It can be set toì
any value from 0 to 65535. It can be stored into any otherì
register. There are instructions to test when the accumulator isì
zero.
&T: The "trap register" is part of a mechanism to breakì
endless loops; the "TRAP" instruction is used to set a failsafeì
if a script or part of a script takes too long to execute.
&E: The "error register" can be either 0 or 1, with 1ì
generally indicating an error condition. There are instructionsì
to set and test the error register.
&R: The Recognizer can be used to store text or numbers.
&1 - &8: These are general purpose registers, and can holdì
numbers or text. They are used to pass parameters to subroutines.ì
Each subroutine level has it's own set of these registers. When aì
subroutine is called, the initial values are those of the callingì
routine.
&S: The "shift register" is a special register that containsì
the last 20 characters received from the modem, and is whatì
patterns are matched against. Characters are shifted in from theì
right, and the left most character "falls off" the end. You canì
also store text in &S and use the "IF" instruction to do stringì
comparisons.
&1 through &8 are "local variables"; they are not shared amongstì
all subroutine levels. When a CALL is executed, the called scriptì
"inherits" the calling scripts initial values for theseì
registers, but any changes made are lost upon RETURN.
The stack is a general purpose "push down" stack; you PUSH itemsì
onto the stack, and POP them off. Items can only be accessed fromì
the top of the stack. There is room for up to ten items on theì
stack. If there are (for instance) five items on the stack, toì
get at the first one pushed (the "bottom" of the stack) you mustì
first pop off the four on "top" of it.
.pa
INSTRUCTION SYNTAX
All instructions are of the form:
INSTRUCTION OPERAND OPERAND
Blank lines or lines beginning with a semicolon are ignored.ì
Lines beginning with a colon (label statements) are ignored whenì
processing instructions.
Operands are usually text strings, and all strings should beì
quoted.
INSTRUCTION PROCESSING
The script processor is basically a text processor. The macroì
language applies to all commands at all times. Anything to theì
right of the instruction itself is expanded by the macroì
processor.
Macros are expanded from left to right, once. There are twoì
special tokens the macro processor understands:
&(one letter register name)
\(special text character)
The language chosen allows just about every disgusting trickì
possible with machine language; self-modifying code, computerì
GOTOs, etc. I'll dispense with the formality, and show someì
generalized examples and leave it at that:
Message "This is a string"
The MESSAGE command merely displays what it's given on theì
command status line. It makes for a simple example. In this case,ì
centered in the status line you'd see:
This is a string
If the recognizer (&R) contained the string "HELLO DUDE" theì
instruction:
Message "The recognizer contains &R"
Would display:
The recognizer contains HELLO DUDE
To display the same thing, but with quotes surrounding theì
contents of the recognizer, you would use:
Message "The recognizer contains \"&R\""
Displayed as:
The recognizer contains "HELLO DUDE"
Note the \ before the quote character merely quotes what follows.ì
There are some convenient exceptions:
\r carriage return, 13 decimal
\n line feed, 10 decimal
\e escape, 27 decimal
\b backspace, 8 decimal
\c etx (Control-C), 3 decimal
\1 SOH character, decimal 1
\127 DEL character, decimal 127
... ...
If you don't like that, ("C" programmers will like it though) youì
can enter control characters like so:
^A 1 decimal, ASCII SOH
^M carriage return, 13 decimal
^J linefeed, 10 decimal
... ...
The ADD instruction adds a value to the accumulator. For example:
ADD 27
Would add 27 to the accumulator; if it had contained 3, it wouldì
now contain 30. If the &2 register contained "34", the following:
ADD &2
Would add the numeric value 34 to &A. If &2 contained "ABRACADAB"ì
then it would add zero to &A.
Here are some further examples. Assume first:
&A contains 20
&R contains "Text"
&1 contains "764-1629"
&2 contains 300
INSTRUCTION OPERAND EXPANDED
message "sample text" sample text
message &R 20
message "pattern is &r, OK?" pattern is 20, OK?
message "&A&R&A" 20Text20
message "Dialing &1 at &2 baud" Dialing 764-1629 at 300 baud
You can take this to absurd extremes. The instruction JMP <label>ì
passes execution to the line following the line containingì
:<label>. You can take advantage of this by using a "computedì
goto". The command:
jmp "&R"
Would attempt to jump to a line:
:TEXT
.pa
.sh Pattern Matching
PATTERN MATCHING
The main purpose of FidoTerm's script language is patternì
matching; looking for particular strings of characters receivedì
from the modem. All of the script language instructions areì
intended to work together to do this.
The single most important component of the script machine is theì
Shift Register. The shift register contains the last 20ì
characters received from the modem, and works like this:
Assume that with your modem and FidoTerm, you just called intoì
and connected with some bulletin board system, and are about toì
be asked to log in.
As characters are received they are put into the right hand endì
of the shift register; the character on the left edge of theì
shift register is lost. For example, if the bulletin board signonì
message you'd see on your screen was:
WELCOME TO THE ACME HOG THROWERS BBS
AT THE PROMPT ENTER YOUR NAME AND PASSWORD:
Lots of times a simple "wait until the word XYZ" will do exactlyì
what you want. This sort of thing is easy to write scripts for,ì
and even in complex scripts is a very useful function.
The problems start when you need to base different actions on aì
number of possible patterns, not just one. A simple "MATCH"ì
instruction just won't do it, and brute force techniques ofì
searching through a screenful of text ("rummaging") has seriousì
limitations.
In FidoTerm the technique used involves a 20 character arrayì
called the "shift register", referred to as "&S" in the scriptì
language.
The shift register changes after each character received from theì
modem; in the example above, W, E, L, C, O, M, E, etc. Part wayì
through the above message being displayed, the shift registerì
would look like:
....
&S " WEL"
&S " WELC"
&S " WELCO"
&S " WELCOM"
....
&S "LCOME TO THE HOG THRO"
....
FidoTerm compares patterns you specify against the right hand endì
of the shift register; this means that for each characterì
received (therefore a new string each time) you can look for anyì
reasonable number of possible patterns. ("Reasonable" will beì
discussed later ...)
In this example, to do an automatic login, once we see the wordì
"PASSWORD:", we can output thename and password. This is a commonì
and simple case. The instruction "MATCH" will do the job.
"MATCH" compares text you specify against the contents of theì
shift register. For this example we'd use "WORD:". A string matchì
is used, so you only need to use enough characters to make itì
unique; the string "WORD:" does not appear anywhere else in theì
initial signon message. (Actually, ":" will work fine here, butì
it's a good idea to use at least a couple of characters; "RD:"ì
would be even better.)
MATCH "WORD:"
To continue the example above, as characters come in from theì
modem they shift through the shift register. FidoTerm isì
executing the "MATCH" instruction above, and the shift registerì
looks like:
....
match WORD:
&S= "OUR NAME AND PASSWOR"
match WORD:
&S= "UR NAME AND PASSWORD"
match WORD:
&S= "R NAME AND PASSWORD:"
For each character received, the "MATCH" instruction is comparingì
it's pattern ("WORD:") against the contents of the shiftì
register. When the patterns match, the next line of the scriptì
file is executed, which in this case could be an instruction toì
output your name and password.
.pa
COMPLEX PATTERN MATCHING
You don't need to understand the how and whys of the shiftì
register to use the "MATCH" command, and for most casual scriptì
writers that will be all you need.
A good example of the limitations of such a simple system is aì
script that dials phone numbers with a Hayes modem using "AT"ì
commands, and responding to the many possible "result codes".ì
(This example assumes a basic understanding of Hayes modemì
commands.)
The dialing part is easy; you just issue the ATDT command and theì
phone number. The problem arises when you try to interpret theì
results of that command, such as busy, no answer, connecting atì
various baud rates, errors, etc. A simple "MATCH" instructionì
just won't work.
For example the US Robotics Courier HST has about a dozenì
possible responses to a simple dial command; any script you writeì
must be able to handle them all. That's what we'll do here.
Dialing a US Robotics Courier HST
The command we'll use, for simplicity, is:
"AT DT 764 1629\r"
("\r" means "carriage return, CR, decimal 13)
The modem can respond with any of the following result words:
CONNECT (300 baud)
RING (incoming call)
NO CARRIER (failed to connect)
ERROR (bad command given)
CONNECT 1200
NO DIAL TONE
BUSY
NO ANSWER
CONNECT 2400
RINGING
VOICE
CONNECT 9600
This is where you take advantage of the shift register. Theì
script fragment below handles the problem at hand and isì
explained below. You will be using this SAMPLE ... IF ... GOTOì
loop to do most complex string compares.
&T= 60
&C= 0
TRAP dial-failed
output "ATDT 764-1629\r"
:get-result
sample
if "NO" dial-failed
if "ERR" dial-failed
if "12" conn-1200
if "24" conn-2400
if "96" conn-9600
if "ECT\r" conn-300
if "BU" redial
if "VO" dial-failed
if "RING\r" dial-failed
goto getresult
:dial-failed
&A= 0
return 1
:conn-300
&A= 300
goto connect
:conn-1200
&A= 1200
goto connect
:conn-2400
&A= 2400
goto connect
:conn-9600
&A= 9600
:connect
$$ "b &A\r"
message "connected at &a baud"
return 0
"SAMPLE" is a special instruction for use in SAMPLE/IF/JMP loops,ì
and causes one character to shift into the shift register. (Theì
"MATCH" instruction and most others do this automatically, butì
"IF" doesn't.) You should have one, and only one, "SAMPLE"ì
instruction before each set of "IF" instructions; if you haveì
none, the shift register will not ever change, and if you haveì
more than one you will miss patterns.
"IF" compares the given pattern against the current contents ofì
the shift register, and branches to the specified label if aì
match is made.
The patterns searched for by the "IF" instructions need to beì
mentioned. You could search for the entire modem responseì
("CONNECT 1200" instead of just "12") but the script will runì
faster is short strings are used. Use as few as possible is theì
general rule. The "NO" pattern will match any of the following,ì
which all mean no connection: NO CARRIER, NO DIAL TONE, NOì
ANSWER. The 300 baud connection result code is "CONNECT", hard toì
distinguish from "CONNECT 1200" because the "IF" will matchì
"CONNECT" without waiting for the "1200" or whatever follows. Theì
"ECT\r" means that it will only match that word at the end of aì
line, that is, followed by a CR character.
A loop of this length will run pretty slowly. It really shouldì
have a "timeout" check, using the &C clock, to limit the dialingì
attempt to a minute or so, and this will slow it further.
To accomodate this, FidoTerm has rather huge buffers, and usingì
the explicit "SAMPLE" instruction means that characters won'tì
speed through the shift register faster than you can test them.
With a loop of approximately this size, it would take a fewì
thousand characters at continuous 9600 baud to cause characterì
loss. In the example above, speed is not a problem; the modemì
issues very little text.
SAMPLE/IF/JMP loops should be as tight as possible. This isì
interpreted, so keep that in mind; keep comments out of loops,ì
keep labels and operands short. Use as few "IF"s as possible.
If you need to do such a series of compares through a largeì
amount of text at high speed, it is best to cut down the search,ì
for example by issuing commands to reach some intermediate pointì
from which you can do your multiple compares.
.pa
FURTHER NOTES ON PATTERN MATCHING
The strings you provide to the "MATCH" and "IF" instructions haveì
some characteristics that make for easier comparisons.
All searches are case IN-sensitive. "ANC" matches "anc", etc. Youì
can specify it in your script in either way.
"?" is a wildcard character; it mean match any character.ì
"CONNECT ??00" will match "CONNECT 1200", "CONNECT 2400", etc.
Control characters are treated just as any other character. "Endì
of line" characters will vary with the bulletin board program orì
whatever it is you call; Fido for instance is like most BBSs, andì
uses a CR/LF sequence (decimal 13, decimal 10). You can searchì
for "\r" or "\13" or for "\r\n" or "\13\10", but keep in mindì
that other systems could use LF/CR, or other combination.
HINT: You can store strings directly in to the Shift Register andì
then test it with the "IF" command. For instance, user input fromì
the "INPUT" command copied into &S could be tested for aì
particular value.
.pa
.sh Register and Arithmetic Instructions
These are the most basic instructions to change the contents ofì
the various registers. Please note that the space after the "="ì
is signifigant.
&S= text
&1= text or number
&2= text or number
&3= text or number
...
&8= text or number
Set the specified register. Numbers are really textì
strings, but you can treat them either way. The string must beì
under 20 characters.
&A= value
Set the accumulator to the specified value. Theì
accumulator is numeric only.
&B= value
Set the baud rate register to the specified value; if theì
value is not a valid baud rate then the &B register will notì
change.
&C= value
Set the free-running clock to an initial value. The clockì
counts up continuously every second.
&T= value
Set the trap register to the specified value. Setting itì
to zero disables the trap.
ADD value
SUB value
Add or subtract the value to the accumulator.
PUSH text
Puts the text onto the top of data stack. There are onlyì
10 levels so watch out. Anything can be pushed onto the stack.
POP register
Take the top item off the stack and place it in theì
specified register. If you try to put non-numeric text into aì
numeric register it becomes "0". You cannot POP items not PUSHed.
.pa
.sh Flow Control Instructions
TRAP label
This instruction is used to set a time limit on scriptì
execution, usually loops searching for a pattern. The trap usesì
the &C clock.
The &T trap register is set to the specified number of seconds,ì
and the &C clock is reset. Before each script instruction isì
executed, the clock is compared against the trap time; if theì
time limit is exceeded, the script branches to the specifiedì
label in the script file that initially set the trap; thereforeì
the trap can even abort scripts running many subroutine callsì
deep. Setting the &T trap register to zero disables the trap.
&T= 0
&C= 0
TRAP label
....
If at any time during script execution the &C clockì
reaches or exceeds the &T trap register, script executionì
proceeds from the specified label in the current script file.
JMP label
Branch to the specified label unconditionally.
JZ label
JNZ label
Branch to the specified label in the current script fileì
if the accumulator is zero (JZ) or not zero (JNZ). This is usedì
to test previous arithmetic instructions.
DJNZ label
A basic looping instruction: "Decrement and Jump if Notì
Zero". Subtracts 1 from &A, and if the result is not zero,ì
branches to the specified label.
JERROR label
Branches if the &E error register is not zero. &E isì
generally set by the MATCH instruction failing, the RETURN (fromì
subroutine) instruction.
CALL scriptfile parameters ...
Execute the script file as a subroutine. The filename isì
"scriptfile.SCR". The called script file can in turn call otherì
scripts, and each executes until the end of the script file or aì
RETURN instruction is executed.
Each subroutine has it's own set of registers, &1 to &8.ì
Parameters can be passed to the called routine, which set theì
initial value of the local registers. The contents of the localì
registers are lost when the subroutine returns.
RETURN value
Return to the calling subroutine (if any) and optionallyì
set the error register to the specified value.
.pa
.sh String Comparison Instructions
MATCH pattern limit
Wait until the pattern is found in the incoming characterì
stream before executing the next instruction in the script. Theì
pattern can contain "?" wildcard characters. There is an implicitì
limit of 60 seconds; if a match is not found with the time limitì
the error register is set and the next instruction executed.ì
(Presumably a JERROR ... instruction.) Optionally a time limit,ì
in seconds can be specified.
SAMPLE
Shifts one character into the shift register; to be usedì
in SAMPLE/IF/GOTO loops.
IF pattern label
Compares the pattern against the contents of the shift register, and branches to the specified label if it matches. The pattern can contain "?" wildcard characters.
.pa
.sh Character Output Instructions
OUTPUT string
Queue the string for output to the modem, simulatingì
manual keyboard entry. The speed with which characters are output
is determined by the THROTTLE setting.
COPY string
Output the string directly to the modem at maximum speed.
THROTTLE n (0 - 500)
This controls the maximum speed that FidoTerm will outputì
characters queued up by the OUTPUT command. The speed isì
specified in a minimum wait between characters, in milliseconds.ì
The default is 20 milliseconds.
.pa
.sh File I/O Instructions
FidoTerm's file system is very simple; there can only be one fileì
open at a time. It is not a cooincidence that the file format isì
compatible with most BASICs; each record in a FidoTerm fileì
contains 8 fields, each field is a quoted string seperated byì
commas. Each record is delimited with a CR/LF. There is noì
Control-Z or other end of file terminator.
FOPEN filename
Opens a file for reading or writing. The script isì
aborted if the file cannot be found, or if "UNATTENDED" is set,ì
then the error register &E is set. The file must be FCLOSEd whenì
not needed.
FNEW filename
Creates a new file of the specified name. The script isì
aborted if the file cannot be created. The file will be emptyì
after creation.
FREAD
Reads one record from the file, and deposits the contentsì
of the record into the eight registers &1 to &8. Each record canì
contain any number of items, but only the first 8 will be used.ì
Each should be an argument as described elsewhere, preferablyì
quoted.
Lines are read from the file one per FREAD instruction,ì
starting with the first line in the file, until the last line isì
read; all FREADs after the last line will leave all registersì
empty and set the error register &E.
FWRITE
A new record is added to the end of the open file, thatì
contains the contents of the eight registers &1 to &8. Each isì
"quoted". The script is aborted if the disk becomes full, or ifì
"UNATTENDED" is set, then the error register &E is set.
th
FCLOSE
This closes the current file and allows the FOPENing ofì
another file. If any FWRITEs were done, they are written out toì
disk at this time.
.pa
.sh User Input Instructions
KEYBD char
Temporarily suspend script file operation until the userì
types the specified key; CR if none specified. All characters theì
user types, including the terminating one, are outout to theì
modem. This allows the user to manually enter something such asì
password.
INPUT prompt
The prompt is displayed and the user enters a line ofì
text, which is parsed into variables &1 through &8. Any extraì
text is ignored.
ASK question
The question is displayed and Y or N is input as aì
response, with &E set true if the answer is Y.
PAUSE prompt
The prompt is displayed and the user must hit any key toì
continue.
MESSAGE message
Output the message to the command status line.
.pa
.sh Special Instructions
These instructions generally take one operand and perform someì
hopefully useful instruction. They are generally high levelì
functions to perform common functions.
IOPORT n (1 - 2)
Select the serial port to do business with; the defaultì
is the first port, on a pclone COM1.
CD-BIT (1,2,4,8,16,32,64,128)
Set the Carrier Detect (CD) mask bit for proper operationì
of the on-screen "ONLINE/OFFLINE" display.
TIME hh:mm (00:00 - 23:59)
Wait until the specified time of day before executing theì
next line in the script file.
FILES filespec
Sets &A to the number of files matching the fileì
specification.
DELAY milliseconds (1 - 65000)
Delay execution of the script until time elapsed.
QUIET milliseconds (1 - 65000)
Wait for no input from the modem for the specified time.
DTR
Lowers the modem control line Data Terminal Ready (DTR)ì