Engine Room - V1N3



Major Weenie tends to get a little cranky when he's been up half the night with Mr. Worf sampling various Klingon delicacies like gahk. It's not the fact that your dinner's trying to crawl off the plate while you're trying to eat it, it's the washing it down with prune juice that gets to me. So, given the Major's weakened condition today, we'll have just a short simple lesson. Last time, I believe we left off our discussion of REXX with a couple of rather simple examples. So, let's tune our resonators a little finer and examine file handling. Now, most files that you manipulate with REXX are not going to be binary data files-- understand, you could write a database application in REXX, but you shouldn't. Remember, as far as the Major is concerned, REXX is best suited to relatively simple, systems management types of jobs. If you want a database, the Major recommends DB2/2 from IBM, Approach from Lotus Development, or, get an Indelible Blue catalog and check out the other choices there. So, what types of files are you most likely to use REXX on? Come on, quit fiddling with the replicator and take a stab at it. Right, text files. What's one text file found on every Warped system, even if the Major set it up? Correct, README. Now, one feature that README has in common with almost every other plain text file that floats in from any given corner of the quadrant, is that it's not paginated. And usually, by paginated, what we're really talking about is the presence of an ASCII character number 12 which is nothing more than a page eject. Wouldn't it be nice to know how many pages printing README, or some other plain text file, was going to consume? Trees just don't grow on trees, you know.

So, here's a way to figure that out with a simple REXX file. Don't forget that every REXX file has to begin with a comment (and the comment is everything found between a matched brace of /* and */). So, after we've gotten the comment out of the way, how do we get our program to actually open and manipulate README or some other file? Well, one simple way is to capture the file name at the time that the program is started. This is done with the ARG command. Boy, that's the way my stomach feels after all that gahk... Actually ARG is the command to issue in your REXX program to capture whatever the user has typed in on the command line. If your program is called "countwords.cmd", then the way for countwords to know what file it's supposed to operate on is with this line:

ARG filename "filename" becomes, for the purposes of the program, the file that you're operating on, that is, ARG retrieves what you entered on the command line and puts it into whatever variable name you have added after ARG. In this example, if you entered "countwords readme" on the command line, then, "readme" would be assigned to the variable "filename". So, you capture filename, then what? Well, first, I'd put down that disrupter or certainly not point it at my head like that... anyway, at this point, the smart thing to do is what?

Right, tell the user they goofed if they haven't entered any input. You can do that like this: '''If filename = "" then Do Say 'You must enter an input file name when you start COUNTWORDS.' Say 'Please try again. . .' Exit End /* do */'''

Ok, hold it right there. Two problems that are beyond Major Weenie's control. First is trying to get this laid out right for this low tech Internet. Don't look for the Major to have all the tabs and stuff laid out correctly. Second, REXX isn't C or C++, so, don't look for me to stick to classic stuff like only one exit point in a program. So, that said, now what? Now, you have to open the file. The simplest way to manipulate a file in REXX, in the Major's opinion, by using a simple LINEIN command. It looks like this:

rc = LineIn(Filename,,0) In this case "rc" is where REXX puts the return code. In this example, if the file is successfully opened, RC should be a zero. If you check the REXX online book, you'll discover that the LineIn format is LineIn(name, line, count). Notice, I omitted "line". Since the file wasn't open, the LineIn began at the top and "count" is how many lines I wanted read. In this case, I didn't read any lines, all I did was open the file. Aye laddie, check the manual! What else do I need? Right! Somewhere to keep track of how many words, and lines, have been read. And as long as we're at it, might as well keep track of the longest line we find. (Why? So we'll know to anticipate line wraps). We'll keep three counters, Counter, Allwords, and Longline and set them all to zero. You can do that like this: Counter = 0; Allwords = 0; Longline = 0 The semicolons seperate three operations, setting the variables to zero. So, to summarize, what we do is:
 * Read in a line
 * Count the number of words in the line
 * Determine the length of the line and remember its length if it's the longest found so far

And it looks like this... '''Do While Lines(Filename) <> 0  /* 'Lines' function operates until none remain */ Inp = Linein(Filename)              /* Inp contains the contents of the line */ Y = Words(Inp)              /* 'Words' counts the words in the line */ Z = Length(Inp)             /* 'Length' determines how long the line is */ if Z > Longline then LongLine = Z   /* you can figure this out... :-) */  Counter = Counter + 1                /* increment Counter and         */   Allwords = Allwords + Y      /* keep track of the number of words in the line */   End /* do */ Well, display it with the SAY command. Right, you read my mind: check the manual about using the SAY command. A couple of pointers on the SAY command: Things you want displayed on the screen must be enclosed by single (') or double (") quote marks, except defined variables. So, if you issue these commands in your program:  One = "Welcome to"  Two = "my"  Three = "Nightmare"  Say One Two Three What prints out on the screen is: Welcome to my Nightmare If you haven't defined One, Two, or Three, what you get is:  ONE TWO THREE If you did this: One = 1 Two = 2 Three = 3 Say One + Two + Three''' Your program would display... nah, that would take all the fun out of it.

So, here's how I choose to use this. First, you have to figure out how many pages there are by dividing the number of lines by 66. Sixty-six is completely arbitrary, and is a number that dates back to the prehistory of pin printers that could usually put 66 lines on a page. So, I define and calculate "Page" this way: Pages = Trunc((Counter/66),1); If Pages = 0 Then Pages = Trunc((Counter/66),2) The "Trunc" command truncates the answer down to a manageable number of digits. Truncing it down to two digits when there's less than a page of data is overkill, but then, the Major prefers firepower... Having determined this, I issue the commands: '''Say Filename 'contains 'Counter' lines which equals 'Pages' pages of 66 lines each.' Say 'The longest line in the file is 'LongLine' characters long. There are' Say AllWords' words in the file.''' Of course, you'll want to close the file you've had open, so, I'll give you a little assignment you can try instead of drawing down ship's power in the holodeck when you're off duty. (And we found that program by the way...) Check out the STREAM command. If you've followed me this far, and run CountWords on the Warp README, you ought to get a result that looks like this: '''README contains 851 lines which equals 12.8 pages of 66 lines each. The longest line in the file is 74 characters long. There are 3984 words in the file.''' Uh oh, that's the Captain, you'll have to pardon me. You probably heard his fish jumped out of the aquarium and short circuited his replicator so that when he asks for Earl Grey, he gets something more like Duke of Earl. Until next time, I remain,

Major Weenie

''Major Weenie is Kent Rebman, a Technical Specialist with IBM. -ed''