4]-------------------------------------------------
3]FILE FACTORY: Good Old-Fashioned Basic Workhorses
3]By Brian Kent
4]-------------------------------------------------

     (JUMPDISK NOTE: These Basic programs will not work on the Amiga 3000,
which is neither supplied with AmigaBasic nor currently compatible with it.)

    Though I find C language best for stand-alone, immutable programming,
I'll never abandon old-fashioned AmigaBasic for those quick and
not-so-dirty jobs to be done on text files.
     With a bit of Basic knowledge, you can create short programs that do
some interesting jobs. Snip here and add there, and you find the same
fundamental program begins to work in different ways. Because Basic is not
compiled, you can easily call up a program, make changes and run it again.
     I'm not going to try to teach you Basic. I will try to explain a few of
the workhorse commands you can master to make file manipulation easier.
     All the brief examples in this article are Basic programs within this
drawer. On JUMPDISK, you need AmigaBasic resident on a disk literally named:
EXTRAS. If you have any doubt about how to do this, double-click the icon
ABOUTBASIC in the main J window and read what that file says.
     Double-click the icon to run a program. After the program runs, type:

SYSTEM

. . . and press Return, to return to the Workbench screen.

3]THE WHOLE IDEA
     -- Create a text file using Ed or any other text processor.
     -- Write a program that accesses that text file and does something with
or to it.
     The two sentences above are the nutshell of the entire idea of this
article.
     I must assume you know how to create a text file. Using ED, from the
CLI or Shell, you can type the command:

ed mydisk:myfile   (press Return)

. . . and a new file named MYFILE on a disk presumably named MYDISK will be
created. You can type within it and save the result by pressing the ESC key
and at the asterisk prompt that appears at bottom left of screen, typing X
and pressing the Return key. See your machine's documentation on how to use
ED more fully. Or use any text editor with which you're comfortable.

3]PROGRAM 1 - SCREENREAD
     I have written a text file named JOKE. It's within this drawer. The
small program ahead opens that file and displays it on the screen.

REM - SCREENREAD
3]'           Remark line identifying program. Doesn't show up.
CLS
3]'           Clears screen
CLEAR,25000
3]'           Clears 25000 bytes memory for program
OPEN "J:FileFactory/Joke" FOR INPUT AS 1
3]'           Opens JOKE file for input as file identifies as 1
AGAIN:
3]'           Returns here as long as more lines of input file remain
LINE INPUT #1,A$
3]'           Gets line from file and gives it value of A$, a string value
PRINT A$
3]'           Prints the line on the screen
IF EOF(1) THEN END ELSE AGAIN

     That last line requires a bit of explanation. If the final line of the
file identified by the number one has been input -- EOF(1) -- then the
program ends, else the program returns to the   AGAIN:  line to bring in the
next line.
     All that happens with this program is that every line of a specified
text file is INPUT and printed on the screen.

3]PRINTSEND
     With one addition and a small changes, the same program can be made to
INPUT the text material and send it to your printer. If you don't have a
printer, of course you can't use this program. Here's the listing. With
previous REMarks lines omitted, you'll see how small it is:

REM - PRINTSEND
CLS
LPRINT WIDTH 80
3]'          Line above sets printer maximum width for 80 characters
CLEAR,25000
OPEN "J:FileFactory/Joke" FOR INPUT AS 1
AGAIN:
LINE INPUT #1,A$
LPRINT A$
3]'          `LPRINT' refers to printing on paper
IF EOF(1) THEN END ELSE AGAIN

3]SAYFILE
     With a few more small changes, deleting the LPRINT WIDTH statement and
substituting     SAY TRANSLATE$(A$)   for   LPRINT A$
. . . you can use the Amiga voice to speak the entire file, line by line.

REM - SAYFILE
CLS
CLEAR,25000
SAY TRANSLATE$(" ")
3]'          Initiates Amiga voice, though nothing said here
OPEN "J:FileFactory/Joke" FOR INPUT AS 1
AGAIN:
LINE INPUT #1,A$
PRINT A$
3]'          Put this back for screen printing of line being read
SAY TRANSLATE$(A$)
3]'          Speaks the line -- A$ -- using the Amiga voice.
IF EOF(1) THEN END ELSE AGAIN

     In the listing above, the first SAY command: SAY TRANSLATE$(" ")
has the Amiga voice speak a blank. While nothing obvious happens, it makes
an important library call from Workbench and on one-drive systems avoids
having to insert the Workbench at a later, awkward point of the program.
     The SAY TRANSLATE$ command can be used to speak any text. Some
examples:
SAY TRANSLATE$("Look, ma, I am talking")       ' a literal
SAY TRANSLATE$(B$)                             ' a string variable

3]OUTPUTTING -- UPPERCASE
     You can open a file for INPUT, and you can open another file for
OUTPUT. The most reasonable assumption is that you wish to make some sort of
change in the first file and save the change to the new file. We'll use our
old friend, the JOKE file and save a new version of it -- all in upper case
letters. It will be sent to a file called RAM:JOKE, should you wish to open
that file and look at it. We'll print it on the screen, also.

REM - UPPERCASE
CLS
CLEAR,25000
OPEN "J:FileFactory/Joke" FOR INPUT AS 1
OPEN "RAM:JOKE" FOR OUTPUT AS 2
3]'          In naming files, use different numbers, as 1 and 2
AGAIN:
LINE INPUT #1,A$
A$=UCASE$(A$)
3]'         UCASE(A$) turns entire line into upper case type.
PRINT #2,A$
3]'         The line is sent to the RAM:JOKE file - the # 2 file
PRINT A$
IF EOF(1) THEN END ELSE AGAIN

3]FINDERS KEEPERS
     You have a text file that is 100,000 bytes long. You're really
interested in the topic of carrots. So you write a program that inputs the
file and prints and numbers every line with the word you choose. I've
written a brief file called VEGETABLES for use by this program.
     I know this is a reach, but work with me here. It's technique!
     The UCASE$ trick of the previous listing comes in handy here. By making
the entire line upper case, it will find all occurrences, both upper and
lower case.

REM FINDERS KEEPERS
CLS
CLEAR, 25000
PRINT "At the ? prompt, type either CARROT or LETTUCE or SUSHI"
INPUT "Name of vegetable name to find";VEG$
3]'         This lets you choose the name to be sought.
VEG$=UCASE$(VEG$)
3]'         Makes sure your choice is in uppercase
OPEN "J:FileFactory/Vegetables" FOR INPUT AS 1
AGAIN:
LINE INPUT #1,A$
B$=UCASE$(A$)
3]'         Makes B$ variable uppercase version of the input line
X=X+1
Q=INSTR(B$,VEG$)
IF Q>0 THEN PRINT X"-"A$
3]         See explanation below of above three lines
IF EOF(1) THEN END ELSE AGAIN

     Here are full explanations of the new program lines:

X=X+1     Increments values of X by one every time a new line is input.
          Allows for printing the line number where an occurrence is found.

Q=INSTR(B$,VEG$)  INSTR stands for INSTRING and tests whether one string
                  exists within another. B$ is the uppercase version of the
                  input line of A$. VEG$ is the string you typed earlier,
                  either LETTUCE, CARROTS or SUSHI. If VEG$ exists within
                  B$, then Q is given a number value equal to the line
                  position of the first letter of VEG$ within the A$ string.

IF Q>0 THEN PRINT X"-"A$     If Q equals zero, nothing is printed. But if it
                             equals more than zero, the sought string has
                             been found, so the line is printed along with
                             line number a dash and the line itself.

     Consider how you might use what you've learned so far to create new
files containing excerpted material. Let's say you open an INPUT file named
EVERYTHING and an OUTPUT file name SOMETHINGS. You use INSTR to search for
specific string references and send only those lines to the SOMETHINGS file.

3]PROFIT-LOSS -- A Very Simple Way 
     In this drawer is a text file called MONEY, sketching the rise and fall
of an insider trader. The program PROFIT-LOSS prints a running account of
that trader's expenditures and income. The INPUT file named MONEY is very
simple. Each line is a separate transaction. The number at the left of the
line can either be a minus or positive amount. For minus, begin it with a
minus sign. For positive, just write the number. In the listing ahead, the
key line is:

total=total+VAL(a$)

     VAL refers to giving a numeric value to the string A$. In truth, VAL
only reads the numbers and not the text, so a true value is given, though
there is text to the right of the number. The variable    total   is a
running total of profit. In each pass to get a new line, that line is given
numeric value and is added to the total. Minus amounts "added" result in
subtractions from the total.
     You might keep simple income-outgo figures in a text file modeled on
MONEY. You could name successive files OCT90, NOV90, DEC90, JAN91 . . . and
insert an file INPUT requester to get the month you want, as in:
INPUT "Month to be checked";F$
. . . while remembering to: OPEN F$ FOR INPUT AS 1
     Here is the PROFIT-LOSS listing.

REM PROFIT-LOSS
CLS
CLEAR, 25000
OPEN "J:FileFactory/Money" FOR INPUT AS 1
again:
LINE INPUT #1,a$
total=total+VAL(a$)
PRINT  a$
COLOR 3
PRINT  total
COLOR 1
IF EOF(1) THEN END ELSE again

3]MONEY CATEGORY - A Neater Version
     We can make a slightly neater version of this profit-loss statement by
going through the MONEY file twice, once to print and total the income,
again to do the expenditures.
     I won't comment much on this program except to point the way. Note
there are two almost identical program modules: again1 and again2. Both open
the MONEY file, which is CLOSED at the end of work in each. The again1
module adds and prints income. The again2 module does expenditures.
     Since minus amounts are typed with minus signs in the MONEY file, they
are again "added" to the total to reflect their subtraction.
     Here's the listing:

REM Money Category
CLS
CLEAR,25000
OPEN "J:FileFactory/Money" FOR INPUT AS 1
PRINT "INCOME:"
again1:
LINE INPUT #1,a$
a=VAL(a$)
IF a>0 THEN PRINT a$: totea=totea+a
IF EOF(1) THEN skipahead ELSE again1
skipahead:
CLOSE 1
PRINT  "----------"
PRINT "TOTAL:"totea
PRINT
PRINT "EXPENDITURES:
OPEN "J:FileFactory/Money" FOR INPUT AS 1
again2:
LINE INPUT #1,a$
b=VAL(a$)
IF b<0 THEN PRINT a$: toteb=toteb+b
IF EOF(1) THEN ender ELSE again2
ender:
CLOSE 1
PRINT "----------"
PRINT "TOTAL:"toteb
PRINT 
PRINT "Profit/Loss:"totea+toteb
END

3]INVERTNAME: Last-First to First-Last
     It's usual to store names in a file with last name first. That's a
handy way to sort them alphabetically. They look better when displayed in
first name-last name order. The program INVERTNAME opens a file called NAMES
in which the following is held:

Jones*Lucy L.
Wranger*Jeffrey
Smith III*John Louis
Plant*Arturo M.
Claxton Jr.*Mr. and Mrs. Harmon
Cantare*Pete

     The asterisks are central to the inversion process. In the easy listing
ahead, this new material does the work:
q=instr(a$,"*")   - Finds position of asterisk.
b$=MID$(a$,q+1)+" "+LEFT$(a$,q-1)
- Having found the asterisk's character position in a line, the program
makes b$ equal to the RIGHT side of the line AFTER the asterisk plus the
LEFT side of the line BEFORE the asterisk. It inserts a space between the
two. You might refer to your AmigaBASIC manual for more information on MID$,
LEFT$ and RIGHT$ -- all very useful.
     The program prints the INPUT version along with the inverted version.
     Here's the listing.

REM INVERT NAME
CLS
CLEAR, 25000
OPEN "J:FileFactory/Names" FOR INPUT AS 1
again:
LINE INPUT #1,a$
q=INSTR(a$,"*")
b$=MID$(a$,q+1)+" "+LEFT$(a$,q-1)
PRINT  a$"     "b$
IF EOF(1) THEN END ELSE again

3]LABELER: THE FINAL AND USEFUL PROGRAM
     I warned you I wouldn't be teaching you much BASIC, and I have been
true to my word. Instead, my aim was to suggest and demonstrate some ways
Basic can be used to manipulate text files.
     This final entry may even be of some use to you. It presumes you're
willing to write an ADDRESS file with each name/address on a separate line
in this format, again using asterisks for dividers:

LastName*FirstName*Address*CITY STATE ZIP

     Whether you're in the U.S., Canada with its provinces and postal codes,
and other countries with other address forms, I want you to write your
address files in the suggested format. What you're after is a three-line
address -- no more, no less.
     The program ADDRESSPRINT will INPUT from the ADDRESS file, invert
first and last names, print a three-line address, then space three lines.
This will print addresses for you on a standard one-wide 15/16th-inch
address label.
     I won't go into the whys and wherefores of this final listing. A
beginner can puzzle it out from what has been covered in this article. And
whether you care to understand it or not, you can use it if you're willing
to create an ADDRESS file using the correct format.
     The article ends with the listing ahead, so now is my final chance to
ask you to let JUMPDISK know if you find these little utilities useful and
want more. If so, I'd be happy to go into more depth on these techniques. 

REM ADDRESS LABELER
DEFSTR f-h
DIM g(4)
OPEN "J:FileFactory/Address" FOR INPUT AS 1
again:
LINE INPUT #1,h
r=1
FOR t=1 TO LEN(h)
f=MID$(h,t,1):IF f="*" THEN r=r+1: GOTO skip
g(r)=g(r)+f
skip:
NEXT t
LPRINT hv:LPRINT g(2)" "g(1): LPRINT g(3)
LPRINT g(4):FOR t=1 TO 2: LPRINT:NEXT t
FOR u=1 TO 4:g(u)="":NEXT
IF EOF(1) THEN ender ELSE again
ender:
CLOSE
PRINT"All names printed. End.":END

4]END OF TEXT
