LnSOS BOOT 1.1 SOS.KERNEL SOS KRNLI/O ERRORFILE 'SOS.KERNEL' NOT FOUND%INVALID KERNEL FILE: xةw,@  ȱlmi8#)!) PASCAL UTILITIES FOR APPLICATIONS DEVELOPMENT )g.g%SEG.T jg3Ÿ/ -READ.ME.FIRSTgOHELLO.TEXTJg/gMENU.MAKERg/g/III.BLM.18u' *PLUTIL.LST@|g*+PLUTIL.CODEH0g*%+PLUTIL.TEXTaCg+&' -PLUTIL.MANUAL3cg+g-TESTUTIL.TEXT7lg,DISKNAME.DAT >dLԡm#i㰼m#iЕOLԡȱfg hi !dLԡ憦  Ljmkm l y`2 Lԡ8(Je稽)ʈ@L ALLAN M. BLOOM, PhD CDP 2303 San Marcos Street, Blacksburg, Virginia 24060   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEF is discussed, in its turn, in the following paragraphs. We'll be looking at not only _h_o_w to use them, but why. Some are self-evident. Some are less so. Examples of use are also given. The accompanying Pascal prOne other (TRANSLIT) is derived from from Kernighan and Plauger ( _S_o_f_t_w_a_r_e___T_o_o_l_s___i_n___P_a_s_c_a_l_, Addison-Wesley: Reading MA, 1981, 51-57). Each of the above modules to look at a sixteen-bit word. 16. X_TO_Y Take a long integer X to its Yth (integer) power. Two modules (HEX4 and BASE_TEN) owe much to Jeppson ( _S_o_f_t_a_l_k_, September 1982, 73-86). CHAR variable's alphabetic value to upper case. 13. UPPERSTR Change a string's alphabetic characters to upper case. 14. UPPER1 Translate a string variable to mixed case. 15. VARIANT Eight different ways Open a file given an English title and default pathname. Give the user a chance to correct any I/O errors. 11. TRANSLIT Transliterate specified characters in a string. 12. UPPERCHR Change a N Change the length of a string variable, padding with blanks if the new length is longer than the old. 9. NIBBLEX Two-character hexadecimal representation of a CHAR field. 10. OPEN IOERROR The name of an input/output error, given its error code. 7. LNAME Extract a "last name" from a name ordered by first-name, middle-name or initial, last-name, and suffix. 8. NEWLEg blanks from a string. 3. HEX4 Hexadecimal representation of an integer. 4. INC Increment an integer counter variable. 5. INTSTR Integer representation of a numeric string. 6. ends PASCAL even more usefully. The library unit, PLUTIL, consists of the following members: 1. BASE_TEN Integer representation of a hex string. 2. BLANK1 Strip multiple, leading, and trailinproduct may agree that it is at once a bit more and a bit less than is needed for good software engineering in the Apple /// PASCAL environment. This article presents an additional PASCAL utility library, one that ext have library units that extend the language is an example of that power. Apple Computer, Inc. offers one such set of extensions under the name "Apple /// Pascal Utility Library," product C3S0001. Those having that program _I_n_t_r_o_d_u_c_t_i_o_n PASCAL is a powerful microcomputer programming language. Its ability to Office: (703) 961-7921 Home: (703) 951-2025 ogram TESTUTIL displays these examples and offers you a chance to exercise the modules with your own. PLUTIL October 31, 1984 Page 1 Bloom Pascal Utilities BASE_TEN is a function taking a single argument, a string of characters representing up to four (4) hexadecimal digits ("0" thro inc (array_pointer); {Returns "array_pointer" as 4661 } B: array_pointer := -4660; inc (array_pointer); {Returns "array_pointer" as -4559 } an integer variable. It allows you to write "inc (integer_variable);" instead of the wordier "integer_variable := integer_variable + 1;" Example: A: array_pointer := 4660; L October 31, 1984 Page 2 Bloom Pascal Utilities INC is a procedure that increments g) {Returns "strg" = 7FFF } Note that in both BASE_10 and HEX4 the hexadecimal representations are displayed in the "normal" way, with the least significant byte last. PLUTI A: hex4 (4660, strg); {Returns "strg" = 1234 } B: hex4 (-1, strg) {Returns "strg" = FFFF } C: hex4 (32767, str HEX4 is the inverse of BASE_10. Feed it an integer, or any fullword equivalent to an integer, and it returns a string of four hexadecimal digits ("0" through "F"). Examples: if (strg = "N") or (strg = "n") then exit (program); Example "B" is an example of "user friendly" programming. The program will correctly interpret " no ", "N", and "Not on your life!" } B: writeln ('Continue? ("Y" - default or "N"'); readln (strg); blank1 (strg); strg := copy (strg, 1, 1); ing has no leading or trailing blanks, and it has no consecutive blanks within it. Examples: A: blank1 (' John Q. Public '); {Returns "strg" as 'John Q. Public' reserved for negative numbers. They go from $8000 (-32768) to $FFFF (-1). BLANK1 is a procedure that removes redundant blanks from a string variable. The returned strase_ten('XYZ') = 0 {Not hexadecimal } E: base_ten ('12345')= 0 {Longer than four characters} Note that half the available values of an integer variable are 0 B: base_ten ('FFFF') = 65535 = -1 {Integer over 32767 negative} C: base_ten ('7FFF') = 32767 {Maximum positive integer } D: bcal and SOS, a lot of values are more easily expressed in hex. You might wish to tell a program the number in hex and let the computer do the conversion. Examples: A: base_ten ('1234') = 466ugh "F"). It returns its decimal equivalent as an integer. The routine returns zero (0) if a non-hex character is found in the string or if the string is longer than four characters. At the nuts and bolts level of Pas It is good programming practice to have meaningful (long, Englishlike) data names, and INC just takes some of the bother out of using them. INTSTR is a function taking a single argument, a string of characters representing an integer value. It returns the string's decimal equivalent as an integer. The string may have leading or trailing blanks, and it may have a leading sign ("-" or "out_name" as "Mac Donald, John" <--- RIGHT} {Returns "last_name" as "Mac Donald" <--- RIGHT} E: lname ('Mr. T', out_name, last_name); {Retur_name" as "Passos, John Dos" <--- WRONG} {Returns "last_name" as "Passos" <--- WRONG} D: lname ('John Mac Donald', out_name, last_name); {Returnsout_name" as "Snodgrass, Gladys P., PhD"} {Returns "last_name" as "Snodgrass" } C: lname ('John Dos Passos', out_name, last_name); {Returns "out {Returns "out_name" as "Public, John Q."} {Returns "last_name" as "Public" } B: lname ('Gladys P. Snodgrass Phd', out_name, last_name); {Returns " and returns both the person's "last-name" and the name resequenced as a "last-name first" string. Examples: A: lname (' John Q. Public ', out_name, last_name); Page 3 Bloom Pascal Utilities LNAME is a procedure that takes a normal "first-name first" name This procedure contains all 128 Pascal and SOS I/O errors (from 0 through 127) as listed in Apple Tech Notes Number 6150.014, issued September 8, 1982. PLUTIL October 31, 1984 _name); {Returns "io_err_name" as "(SOS) Directory full"} C: ioerror (246, io_err_name); {Returns "io_err_name" as "Invalid error code"} , rather than letting a program crash. Examples: A: ioerror (10, io_err_name); {Returns "io_err_name" as "No such file"} B: ioerror (73, io_erre to an integer variable. IOERROR is a procedure that returns the English meaning of an input or output error. This is useful when you are trapping the errors yourselfwhen the user klutzes, the program can read a string, analyze it, and ask the user for correct input if the string is non-integer. Note that while -32768 is supposed to be legal, I have been unable to assign that valutr ('7FFF') = 0 {Non decimal characters } D: intstr(' -123 ')= -123 {Forgives lead/trail blanks } This routine is useful for keyboard entry. Instead of getting a crash if the string fails any test. Examples: A: intstr ('1234') = 1234 B: intstr ('65535') = 0 {Integer over 32767 } C: ints "+"). The remainder of the string may not be longer than five characters, it may contain no non-numeric character, and its numeric value must be in the integer range of -32767 through 32767. The routine returns zero ns "out_name" as ", Mr. T" <--- WRONG} {Returns "last_name" as "" <--- WRONG} F: lname ('Mr. T,', out_name, last_name); {Returns "out_name" as "T, Mr." <--- RIGHT} {Returns "last_name" as "T" <--- RIGHT} This procedure does a pretty good job of finding a last name, but it is not perfect. l" order, high nibble first. Do you get the feeling that this procedure is a crutch for byte-oriented programmers who can't handle low-nibble-first representations? Examples: A: var wk_convenient to think in terms of bytes than in words. If we say that a block of data takes up 512 bytes, why shouldn't we look at that block as a PACKED ARRAY [1..512] OF CHAR? NIBBLEX also returns the nibbles in "normate) into its two component hexadecimal nibbles. The author has found this of most use in "dumping" files in character and hexadecimal, to look at their innards. HEX4 could be used, but it can be more css here lies in saving a few lines of text and -- more important -- in having the courtesy to pad lengthened strings with spaces. NIBBLEX is a procedure that expands a character (byohn Q.' } B: strg := ''; newlen (strg, 4); {Returns "strg" as ' ' } NEWLEN will not accept a string longer than 80 characters. Its usefulnee right. As examples: A: var strg: string; strg := ' John Q. Public '; newlen (strg, 13); {Returns "strg" as ' Jes the length of a string variable. If the new length is shorter than its original length, the string is truncated to the right. If the new length is longer that the original one, spaces are added to th PLUTIL October 31, 1984 Page 4 Bloom Pascal Utilities NEWLEN is a procedure that chang them. For example, the last name "Dos Passos" is returned as "Passos." This problem can be avoided by either entering the name as "DosPassos" or by replacing the blank with a non_printing character. problem. Another problem is "two-word" last names. The program recognizes a very few last-name prefixes (e.g. Von, Van, de, la, Di, Mac) from a specified list. It doesn't handle all ofleft terminates with a period, so it is taken as an abbreviation (the routine can handle any number of suffixes). The result could annoy a gentleman with whom it is not nice to mess. Placing a comma after the name fixes the s suffix. A judiciously placed comma can handle awkward cases. In the case of "Mr. T," the routine's rules of thumb get in the way. The last substring contains no vowels, so it is classed as a suffix. The next to the for perfection. The routine recognizes many suffixes, by either rule-of-thumb or from a specified list. Also, the routine takes anything after the first occurrence of a comma as the name'In common with most such routines, it could have trouble recognizing a name's suffix (Jr, III, PhD, MD, etc), a two-word last name (Dos Passos), or a non-standard last name (T). The variety of human names is a smidge too great har: char; outhex: string; wk_char := 'A'; nibblex (wk_char, outhex); {Returns "outhex" as '41'} B: wk_char := '0'; nibblex (wk_char, outhex); {Returns "outhex" as '30'} NIBBLEX will take either a packed or an unpacked character and return the same hexadecimal or "QUIT" for no file or "ABORT" to terminate this program In "no display" mode, the messages are preceded by a line containing the pathname that caused the errowed by RETURN) indicates that there is no file. An I/O error yields the following messages: ERROR: error-description Enter RETURN to retry appear, and the .PRINTER would be opened without user intervention. The user may press RETURN to accept the default or key in another printer's name, such as SILENTYPE or QUME. A blank entry (one or more blanks follo Default = .PRINTER Response --> [] If the default pathname had been a null string (''), the second line would not appear. If the default pathname had been '**.printer,' the message would notcessing for no file }; During the procedure call, the user would see the following prompt on the console screen: Enter the pathname of the printer you are using: A: display_name := 'printer you are using'; pathname := '.printer'; open (prtfile, display_name, 'rewrite', pathname); if pathname = '' then {Pro display_name: string; io_method: string; {Either RESET or REWRITE } pathname: string; {Null string gets no prompt} ns a null string as the pathname. A default pathname prefixed with "**" (double asterisk) indicates the "no display" mode. As an example: var prtfile: text; without the ".TEXT" suffix. When a valid pathname is entered, or if the default is selected, the file is opened and the pathname is returned to the calling program. If there is no file to be opened, the routine returtober 31, 1984 Page 5 Bloom Pascal Utilities If an existing textfile is to be opened, the routine permits an entry user to supply a valid pathname for the file. You may also use PLUTIL's error-trapping features in "no display" mode, not bothering the user unless an I/O error occurs. PLUTIL Oc of file. It also specifies an English language DISPLAY_NAME for the file and the way the file is to be opened, either RESET or REWRITE. It may optionally also specify a default PATHNAME for the file. OPEN prompts the opening of a specified file in a standard way with extensive error trapping. The program supplies the internal filename and its associated FILETYPE. The default FILETYPE is TEXT, which works for almost all typesrepresentation of its constituent nibbles. For an unpacked character, it looks only to the two low-order nibbles. OPEN is a general-purpose file opener. It leads a user through the r. The error-description comes from the IOERROR procedure. If the user mis-typed the file's pathname, or accepted an invalid default pathname, or didn't have the right disk in the right drive, pressing RETURN gives him or her another chance. The "QUIT" option returns a null pathname to calling program. "ABORT" stops everything and exits the program. If you leave nine screen lines for OPEN, the error message and re-ent readln (input, wk_char); upperchr (wk_char); if wk_char = 'N' then exit (program); B: write ('Enter the pathname of the output filriables, and UPPERSTR operates on strings. Each changes any lower-case alphabetic character to its upper-case equivalent. Examples: A: write ('Continue? (Y - Default | N) --> '); hed much more efficiently by other means (see UPPERSTR). It may come in handy sometime. UPPER-CHR/STR are a pair of procedures that uppercase. UPPERCHR operates on CHAR va {Returns "wk_string" as 'AAAAA AAAA AAA AAAA AAAA' } TRANSLIT is one of those routines that seems like a good idea, but may not actually be too useful. Uppercasing a string can be accomplis B: translit (wk_string, 'a-z', 'A-Z'); {Returns "wk_string" as 'EVERY GOOD BOY DOES FINE' } C: translit (wk_string, 'a-z', 'A'); A: wk_string := 'Every good boy does fine'; translit (wk_string, 'aeiou', '12345'); {Returns "wk_string" as 'Ev2ry g44d b4y d42s f3n2' } o the same length as the source string -- by lopping "excess" characters or padding with the repeated occurrences of the last destination-string character. A repeated source-string character is ignored. Examples: ordinality. For example, "a-z" is equivalent to writing all 26 characters from "a" through "z." TRANSLIT expands any "ranges" in the source and destination strings before processing. It then forces the destination string t same position of the "destination" string. In TRANSLIT a dash (-) may be used in either the source or the destination strings as shorthand for a range of character values of increasing multiple translations. A string transliterated from "aeiou" to "AEIOU" will have all its vowels capitalized. All characters in a string that match a character in the "source" string are changed to the character in the TRANSLIT is a procedure that transliterates specified characters in a string to other specified characters. For example, you may ask TRANSLIT to change every occurrence of "a" in a string to "1." TRANSLIT can also perform after the call. PLUTIL October 31, 1984 Page 6 Bloom Pascal Utilities OPEN re-displays the prompt at its original screen position. Note that OPEN can return a null pathname, indicating that there is no such file. The calling program must test for that conditionry cycle will not cause the screen to scroll. When an invalid entry is detected, the routine uses six lines to display the problem and the user options. Afterwards, OPEN blanks all messages. If "retry" was requested, e --> '); readln (input, wk_string); upperstr (wk_string); if wk_string = '.PRINTER' then {whatever} UPPERCHR saves a little programming bother, but UPPERSTR can save a lot. Imagine how many different ways that someone can enter the device name ".PRINTER." That is how many different tests you save by capitalizing. PLUTIL al word, however, things read right-to-left. PLUTIL October 31, 1984 Page 8 Bloom Pascal Uple's P-code interpreter excepted) think that the "high order anything" belongs on the left. You, I, and almost everyone else outside the Orient read things left-to-right. When you get _w_i_t_h_i_n an Apple Pasc boolean = FALSE octals = 4 6 0 1 1 The first thing that you had best notice is that everything is "backwards." You, I, and almost everyone else (Ap0100 1000 char = 4 pkd chrs= 4 DC2 bytes = 52 18 nibbles = 4 3 2 1 bits. Examples: var v: variant; A: v.int := 4660; {Put 4660 into "v" as an integer variable} bits = 0010 1100 f 0..255 bytes, four 0..15 nibbles, or five 0..7 octals. This is a bit more than another toy for the bit-fiddling types among us. It can be educational actually seeing how many different ways Pascal can view the same ight different ways. Once you have declared a particular word of memory as type VARIANT, you may reference it as an integer, a character, a pair of packed characters, a boolean, a packed array of 16 booleans, a pair oy alphabetic character that is preceded by a letter. VARIANT is neither a procedure nor a function. It, is rather, a data type that defines a single word of memory e Note in example "B" that UPPER1 is not a panacea. The "phd" should be written "PhD" as the proper abbreviation. UPPER1 capitalizes the first alphabetic character in a sequence of alphabetic characters and lowercases anadys P. Snodgrass, Phd'} C: wk_string := 'John Dos PASSOS'; upperstr (wk_string); {Returns "wk_string" as 'John Dos Passos' } {Returns "wk_string" as ' John Q. Public ' } B: wk_string := 'gladys p. snodgrass, phd'; upperstr (wk_string); {Returns "wk_string" as 'GlLAN M. BLOOM," UPPER1 will change the string to "Allan M. Bloom." Examples: A: wk_string := ' JOHN Q. PUBLIC '; upperstr (wk_string); se," with the first letter of a group capitalized and the rest in lower case. This is most useful in displaying data. No matter whether a record field is in your data base as "allan m. bloom" or as "AL October 31, 1984 Page 7 Bloom Pascal Utilities UPPER1 takes a string and turns it into "mixed catilities Noting that you must read right-to-left, the above entries for bits, nibbles, and bytes should make sense to the mathematicians among you. The "char" value of "4" proves that Pascal pays no attention to the high-order byte of a CHAR variable. When you define the word as a pair of packed CHAR variables, however, it _d_o_e_s look to the word's high byte, the "18" in this case.  PLUTIL e, then return to the main menu to exercise another module or to exit the program. PLUTIL October 31, 1984 Page 9 ESTUTIL menu has an entry for each of PLUTIL's modules. When you select a module, TESTUTIL displays several examples of use, then asks if you would like to try the module yourself. You may practice as often as you lik the computer-directing Pascal text shows exactly what is happening. To try out PLUTIL, you must first add the program's code file to your SYSTEM.LIBRARY. Next, execute the TESTUTIL program. The T what I am doing with this documentation. The next move is yours. I recommend listing all 15 pages of the PLUTIL unit's text file and studying the modules of interest. Some of _m_y text may have been fuzzy, butither "0" or "1," so the author didn't mess with it. The procedure will handle either positive or negative bases. ENDIT is not a PLUTIL procedure, function, or data type. ENDIT is 125 } A "designed flaw" of X_TO_Y causes the procedure to return a value of "1" if the exponent is less than "1," as is shown in "B" above. The integer result of such an exponentiation will always be e B: x := 4; y := -2; x_to_y (x, y, result); {Returns "result" as 1 } C: x := -5; y := 3; x_to_y (x, y, result); {Returns "result" as - integer; result: integer [12]; A: x := 4; y := 2; x_to_y (x, y, result); {Returns "result" as 16 } that particular arithmetic operation can come in handy. Pascal 1.1 provides this capability in its SANE library unit. Examples: var x: integer [12]; y: aises a long integer "X" to its integer Yth power, returning a long integer result. The long integers must be of "length" 12 (INTEGER [12]) each. Pascal does not provide for integer exponentiation, and three-bit numbers comfortably. The high bit is left over and is ignored. The set of octals would be the same whether the rightmost bit were "0" or "1." X_TO_Y is a procedure that r The boolean equivalent of integer 4660 is FALSE. Since the leftmost (lowest order) bit is "0," the whole word is evaluated as FALSE. The "octal" representation shouldn't work. A sixteen-bit word does not hold a set of GIJKLMNOPQRSTUVWXYZ[\]^_ procedure X_TO_Y (x: long_12; y: integer; var result: long_12); 3{Returns X to the Yth Power }  procedure OPEN (var FILENAME: FILETYPE; {FILENAME: Internal name of file} N{FILETYPE:User-defined data TYPE} N{ } procedure UPPERSTR (var str: string); 3{Change string variable to upper case }  procedure UPPER1 (var str: string); 3{Change string to mixed case } rs, or range of chars } 4 dest: string); {Dest chars, or range of chars } * {Transliterate chars in string } procedure UPPERCHR (var ch1: char); 3{Change char variable to upper case anks if lengthened } procedure NIBBLEX (inchar: char; var outhex: string); 3{Returns 2-nibble representation of char field } ( procedure TRANSLIT (var xstring: string; {String to be transliterated } 8source: string; {Source cha* procedure NEWLEN (var STR: string; {I/O string whose lgth is to be changed} 4LGTH: integer);{New string length. } 3{Change length of a string, pad with blt MI Last, Suffix format. } 4var out_name: string; {Last, First MI, Suffix format. } 4var out_last: string); {Last name. } 3{"First I Last, Suff" name to "LFIS" & "Last Name" } teger; 3{Integer from a numeric string }  procedure IOERROR (IO_ERR_NUM: integer; var IO_ERR_NAME: string); 3{Return the name of an I/O Error from its number } procedure LNAME (in_name: string; {FirsX4 (value : integer; var str : string); 3{Return hex representation of fullword } procedure INC (var counter: integer); 3{Increment a counter }  function INTSTR (strg: string): in3{End Include VARIANT} 3 function BASE_TEN (strg: string): integer; 3{Base-10 representation of a hexadecimal string }  procedure BLANK1 (var strg: string); 3{Strip double/lead/trail blanks from string }  procedure HEPUT 8$maKEYBOARDN$ FALSE 2TRUE H&NIL bMAXINT * BYTESTRELWORDSTREd@\ 3{  ival }  :'')PBBINTEGER xppREAL : CHAR  BOOLEAN v{ STRING 0 TEXT :$ INTERACT* INPUT &$inOUT] of 0..255); <3: (nybl: packed array [0..3] of 0..15); <4: (bit: packed array [0..15] of boolean); <5: (bool: boolean); <6: (octl: packed array [0..4] of 0..7); <7: (word: char); <8: (ch: packed array [0..1] of char); Fצ,PōצInvalid error codePT ɡI@ɡ#--(SOS)-U-P!--צ(SOS)-U-Pצ(SOS) צError not in tableP  ////.2/.P2צInvalid sys buffer parmPئDuplicate volume errorתPئNot a block deviceתPئ Invalid levelתPצInvalid bit map addressPf@Z6jV@,t`E6&n[zǀɄצSystem call errorP Pj V ead after endfileתPئFile position out of rangeתPئIllegal accessתPئUser buffer too smallתPצ File busyPئVolume not SOS or Apple-2תPצInvalid length in parm listPئOut of memory for sys bufferתPئBuffer table fullתPצles openתPצInvalid file reference noPئPath not foundתPئVolume not foundתPئFile not foundתPئDuplicate file nameתPצOverrun on volumePئDirectory fullתPئIncompatible file formatתPئUnsupported storage typeתPئRdPצInvalid byte countPtצInvalid block noP\צ Disk switchedPG .!gO9/@Ʉצ Device errorP PL v@ڹצInvalid pathname syntaxPئToo many char files openתPئToo many block fi+ t^G P1  ?ڹצInvalid request codePצInvalid status or control codePצInvalid control parm listPئDevice not openתPצDevice not availablePצResource not availablePצDevice write protecteal pathnameתPئNo room on disketteתPצUnit not onlinePئ No such fileתPئDuplicate pathnameתPئFile already openתPצ File closedP~ئBad input formatתPfئWrong disk formatתPMצDiskette write-protectedP-"ybF /qs  ڹצNo errorPצNo filename storage spacePئBad unit numberתPצIllegal operationPئIllegal directory specתPئUnit no longer onlineתPצFile no longer in directoryPئIlleg/-7-7ȡ38-8צ 12345678903 3  3//3-$--.///   /  š áK `צ0123456789ABCDEFPئ0000תP..ȡڕ(X ZڪP.á-á.77P+á77PšڪP/-0š-Ʉ11צ0123456789ABCDEF..á(11צ0123456789abcdef..á/-.--/ צ šצ š á for the file. } 4DISPLAY_NAME: string; {English title of for display } 4IO_METHOD: string; {Either RESET or REWRITE. } 4var PATHNAME: string); {In: Default PATHNAME or null} N{Out: Actual PATHNAME if OK. } -.-ȡ!2---2IIIׯ2צII2esqׯ2Esqׯ2ESQׯ2INCׯ2Incׯ2ATCׯ2DEDׯ2DEdׯ2EDDׯ2EdDׯ6[2P Q[ǡP/.צ á&g/JڪPƀ " " ÍPō٦תPئתP[צP š  11צ.š. 00/1ˡ1/0ˡ/á2"̀ʀáWPʀˡʀ  invalid̀ʀƀERROR: ƀצPress RETURN to retryצEnter "QUIT" for no file' or "ABORT" to terminate this programWתPWPW ʀƀʀ ƀ̀ʀ̀ʀ̀ʀʀġʀʀ̀WצQUITצP̀WצABORT ʀá j:P < Tn 6 Fbv<W"̀ʀáWPʀˡʀ  invalid̀ʀƀERROR: ƀצPress RETURN to retryצEnter "QUIT" for no file' or "ABORT" to terminate this programʀ ƀ̀ʀXצEnter pathname of the .: N.. צ#̀צNo file}צREWRITE"̀_"̀ʀŦ.TEXTÄ;ẀƀPƀ.TEXTUƀPצI/O method passed = "צ".צ Fix the calling program, please.צEXIT triggered by subroutine.̀ƀƀƀƀ ?̀ƀƀצ** ̀ʀƀ</)š =/|P<< =0 /<<{ E02460H.ڪP٪P צREWRITEצRESETצ,Procedure OPEN error: Invalid IO_METHOD parm=ܛܛ|?06á9á =%/ܛܛ|>0;á//<š =<<0:á7ɡ =<<>Z0809ÍB/< !0 ڦתP< 05˄0/2<á = P<<ܛ0O<š<<AAPA QAPܛ0ɡ? =07áR<š ==/)<Ų3 P</ NšNɡš ɡقPšPٕ1113335678Lj:Ǖ; @> ?=9ڪP0ڡ ٛٛ hš ġؼ# T11 []<Mš @3  & ȡ,ٛ ٛٛ 4 D   ȡaٛړ ٛٛ ,ٛƀ/WW...ƀƀ., -٪PتP-VƀVƀš5ƀ́XƁXƀƁXƀƁƀƁƁX́ẂXʁWʁXȡ7ƁYʁWƁYV́VʁVšʁWƀʁVʁẂWB9ABCDEFPئ00תPTR ٪P-*..W.W.ȡW-WWɄOW,W/,/ȡ*-,000-0,,)///ƀW0/ 0/š0////.ƀ/.ƀP/.צ š̀ƀPƀ, RƀǢƀP[צ)̀ƀPƀ, Rƀ[ǢƀPrPō ؿɡ ڕ 0 צ012345678WתPWPW ʀƀʀ ƀ̀ʀ̀ʀ̀ʀʀġʀʀ̀WצQUITצP̀WצABORT ʀá j:P < Tn 6 Fbv<T2A T1A T1B T2B o \ BKN^a|* procedure NEWLEN (var STR: string; {I/O string whose lgth is to be changed} 4LGTH: integer);{New string length. } 3{Change length of a string, pad with blt MI Last, Suffix format. } 4var out_name: string; {Last, First MI, Suffix format. } 4var out_last: string); {Last name. } 3{"First I Last, Suff" name to "LFIS" & "Last Name" } teger; 3{Integer from a numeric string }  procedure IOERROR (IO_ERR_NUM: integer; var IO_ERR_NAME: string); 3{Return the name of an I/O Error from its number } procedure LNAME (in_name: string; {FirsX4 (value : integer; var str : string); 3{Return hex representation of fullword } procedure INC (var counter: integer); 3{Increment a counter }  function INTSTR (strg: string): in3{End Include VARIANT} 3 function BASE_TEN (strg: string): integer; 3{Base-10 representation of a hexadecimal string }  procedure BLANK1 (var strg: string); 3{Strip double/lead/trail blanks from string }  procedure HEof 0..255); <3: (nybl: packed array [0..3] of 0..15); <4: (bit: packed array [0..15] of boolean); <5: (bool: boolean); <6: (octl: packed array [0..4] of 0..7); <7: (word: char); <8: (ch: packed array [0..1] of char);  0) do begin 9delete (strg, double, 1); 9double := pos (' ', strg); 3end; {while} 3if (length(strg) > 0) then if (strg [1] =' ') 7then delete (strg, 1, 1); 3if (length(strg) > 0) then if (strg [length(strg)] =' ') 7then delet3{ } 3{var strg: string } 3{ } * *var double: integer; 8 *begin double := pos (' ', st (base_ten) ?else v.nybl [count] := p - 1; 6delete (strg, length (strg), 1); 6count := count + 1; 3end;{while} 3base_ten := v.int; end; {BASE_TEN}   procedure BLANK1; {Strip double/lead/trail blanks from string AMB 12/21/82} true; 3base_ten := 0; 3if length (strg) > 4 then exit (base_ten); 3while ((length (strg) > 0) and (count < 4)) do begin 6p := pos (copy (strg, length (strg), 1), h1); 6if p = 0 then p := pos (copy (strg, length(strg), 1), h2); 6if p = 0 then exi } 3 *const h1 = '0123456789ABCDEF'; 3h2 = '0123456789abcdef'; * *var p, count : integer; 3v : variant; 3valid : boolean; 3 *begin v.int := 0; 3count := 0; 3valid :=3{returns 0 if not hex number or if > 4 char} 3{ integer equivalent otherwise } 3{ } 3{Uses member VARIANT } 3{ 06/15/82} 3{ } 3{strg: string hexadecimal string, max 4 char } 3{ } N{ Null String if QUIT from proc } 3{Open a supplied filename } & IMPLEMENTATION  function BASE_TEN;{Base-10 representation of hex string AMB 03/14/83} 3{From Jeppson, DISASM.DATA: HEXUNIT.TEXT for the file. } 4DISPLAY_NAME: string; {English title of for display } 4IO_METHOD: string; {Either RESET or REWRITE. } 4var PATHNAME: string); {In: Default PATHNAME or null} N{Out: Actual PATHNAME if OK. }  procedure X_TO_Y (x: long_12; y: integer; var result: long_12); 3{Returns X to the Yth Power }  procedure OPEN (var FILENAME: FILETYPE; {FILENAME: Internal name of file} N{FILETYPE:User-defined data TYPE} N{ } procedure UPPERSTR (var str: string); 3{Change string variable to upper case }  procedure UPPER1 (var str: string); 3{Change string to mixed case } a counter AMB 01-08-83} 3{ } 3{var counter: integer } 3{ } 3 *begin counter := counter + 1;  end; {INC} $ function INTSTR; {Integer representation of numeric string AMB 03/14/83} 3{ } 3{strg: numeric string, max length 5 digits, } 3{ 8end {begin} 4end {case} *end;{sos_dev_error} * *procedure sos_file_error (io_no:integer; var io_name:string); % *var i: 64..127; ' *begin i := io_no; 4case i of 864: io_name := 'Invalid pathname syntax'; 865: io_name := 'Toome := 'Device write protected'; 844: io_name := 'Invalid byte count'; 845: io_name := 'Invalid block no'; 846: io_name := 'Disk switched'; 4otherwise begin 8if (io_no > 47) and (io_no < 64)  -32768) and (wk_num < 32768) 7then intstr:= trunc(wk_num); end; {INTSTR} procedure IOERROR; {Return title associated with IORESULT error. AMB v.10/83} 4{ 8wk_num := 0; 8for i := 1 to length (strg) do begin  5 6then exit (intstr) 6else begin 3 *const digit = '1234567890'; 3 *var i: integer; 3negative: boolean; 3wk_num: integer [12]; 3wk_pwr: integer [12]; 3 *begin negative := false; 3blank1 (strg); 3intstr := 0; 3if length (strg) = 0 then exit (intstr); 33{ } 3{Maintenance 10/05/83 AMB: Correct propensity to make } 3{ number > 32767 negative. } 3{ } optional leading minus sign. } 3{ } 3{returns: 0 if non-numeric or length > 5 characters } 3{ after stripping leading minus. } many char files open'; 866: io_name := 'Too many block files open'; 867: io_name := 'Invalid file reference no'; 868: io_name := 'Path not found'; 869: io_name := 'Volume not found'; 870: io_name := 'File not found'; 871: io_name := 'Duplicate file name'; 872: io_name := 'Overrun on volume'; 873: io_name := 'Directory full'; 874: io_name := 'Incompatible file format'; 875: io_name := 'Unsupported storage type'; 876: io_name := 'Read after endfile'; 877: io_name := 'File position out of range'; 7if suffix_found = false then begin :suffix_found := true; :for k := 1 to j do >if wk_strg[k] in vowels Athen suffix_found := false; :{end for k} :if suffix_found = false then =if (wk_strg = 'III') =or (wk_strg = 'II') =or (wk_strg = 'esq') =o- i; 7wk_strg := copy (in_name, i+1, j); 7k := pos ('.', wk_strg); 7if k = length (wk_strg) then begin :wk_suff := concat (wk_suff, ' ', wk_strg); :delete (in_name, i, j+1); :suffix_found := true; :end; 7{endif} ; 7in_name := copy (in_name, 1, i-1); 7end 4else if pos (' ', in_name) = 0 then begin 7end 4else repeat 7suffix_found := false; 7i := scan (-length (in_name), =' ',  0 then begin 7wk_suff := copy (in_name, i+1, length(in_name) - i)7or (wk_strg = 'Los') 7or (wk_strg = 'de') 7or (wk_strg = 'di') 7or (wk_strg = 'la') 7or (wk_strg = 'los') 7or (wk_strg = 'della') 7then begin :prefix_found := true; :out_last := concat (wk_strg, ' ', out_last); :delete (in_name, i, j+1); :end; i := length (in_name) + i; 7j := length (in_name) - i; 7wk_strg := copy (in_name, i+1, j); 7if (wk_strg = 'Von') 7or (wk_strg = 'Van') 7or (wk_strg = 'Mac') 7or (wk_strg = 'Mc') 7or (wk_strg = 'De') 7or (wk_strg = 'Di') 7or (wk_strg = 'La') _suff: string; 4vowels: set of char; 4prefix_found: boolean; 4suffix_found: boolean; 4 *procedure find_prefix; *begin 4repeat 7prefix_found := false; 7i := scan (-length (in_name), =' ',  "LFIS" & "Last": AMB 10/11/83} * 4{ in_name: string First MI Last, Suffix format.} 4{var out_name: string Last, Fi_NUM,IO_ERR_NAME); 7IO_ERR_NAME := concat('(SOS)',IO_ERR_NAME) 7end; 4{endcase} 4if (IO_ERR_NAME = '(SOS)') or (IO_ERR_NAME = ' ') 8then IO_ERR_NAME := 'Error not in table'; 4{endif} end; {IOERROR} valid error code' 4else if IO_ERR_NUM < 32 then 7pascal_error (IO_ERR_NUM,IO_ERR_NAME) 4else if IO_ERR_NUM < 64 then begin 7sos_dev_error (IO_ERR_NUM,IO_ERR_NAME); 7IO_ERR_NAME := concat('(SOS)',IO_ERR_NAME) 7end 4else begin 7sos_file_error (IO_ERRgin 8if (io_no >122) and (io_no <128)  127) then 7IO_ERR_NAME := 'In885: io_name := 'Buffer table full'; 886: io_name := 'Invalid sys buffer parm'; 887: io_name := 'Duplicate volume error'; 888: io_name := 'Not a block device'; 889: io_name := 'Invalid level'; 890: io_name := 'Invalid bit map address'; 4otherwise be878: io_name := 'Illegal access'; 879: io_name := 'User buffer too small'; 880: io_name := 'File busy'; 881: io_name := 'Volume not SOS or Apple-2'; 883: io_name := 'Invalid length in parm list'; 884: io_name := 'Out of memory for sys buffer'; r (wk_strg = 'Esq') =or (wk_strg = 'ESQ') =or (wk_strg = 'INC') =or (wk_strg = 'Inc') =or (wk_strg = 'ATC') =or (wk_strg = 'DED') =or (wk_strg = 'DEd') =or (wk_strg = 'EDD') =or (wk_strg = 'EdD') =then suffix_found := true; :if suffix_found = true then begin =wk_suff := concat (wk_strg,' ',wk_suff); =delete (in_name, i, j+1); =end :{endif} :end;{then} 7{endif} 7if pos (' ', in_name) = 0 then suffix_found := false; 7until (suffix_found = false); 4{endif} *end;{find_suffix} * *begin 4{ translit ('fred', 'a-z', 'A') returns "AAAA" } 4{ translit ('fred', 'fred','dfer') returns "dfer" } 4{ translit ('fred', 'f', 'A-Z') returns "Ared" } 4{ translit ('fred', 'ffdd','ABCD') returns "AreC" } * character '-'} 4 4{If a character is duplicated in SOURCE, only the first one} 4{counts. All duplicates are ignored. } 4 4{EX: translit ('fred', 'a-z', 'A-Z') returns "FRED" } (a-d = abcd),} 4{DEST string is padded to same length as SOURCE, as needed,} 4{with the last character in DEST. } 4 4{A dash not surrounded by a pair of characters of } 4{increasing ordinality is treated just as the f chars } 3 4{A dash "-" may be used in SOURCE or DEST to show a range } 4{of character values of increasing ordinality. } 4{Ex: A-Z = all 26 uppercase letters; a-d = abcd. } . 4{After expansion of any SOURCE or DEST rangesprocedure TRANSLIT; {Transliterate characters in a string: AMB 12/31/82} 4{var xstring: string String to be transliterated } 4{ source: string Source chars, or range of chars } 4{ dest: string Dest chars, or range o string; 4 *begin hex := '0123456789ABCDEF'; 4xlate.word := inchar; 4outhex := '00'; 4outhex [1] := hex [xlate.nybl [1] + 1]; 4outhex [2] := hex [xlate.nybl [0] + 1]; end; {NIBBLEX} } 4{var outhex: string } 4 4{OUTHEX is a length-2 string, high-order nibble first } - 4{Uses member VARIANT } , *var xlate: variant; 4hex: d_lgth < length (STR) then 7fillchar (STR [old_lgth + 1], (LGTH - old_lgth), ' '); 4{endif}  end; (* NEWLEN *) $ procedure NIBBLEX; {Returns 2-nibble representation of char field } ( 4{ inchar: char 4{If LGTH > LENGTH(STR), STR is padded out with blanks } * *var old_lgth: integer; 0 *begin if (LGTH < 0) or (LGTH > 80) then exit (NEWLEN); 4old_lgth := length (STR); 4{$rangecheck-} 4STR [0] := chr (LGTH); 4{$rangecheck+} 4if ola string AMB 12/31/82} * 4{var str: string } 4{ lgth: integer New string length. } 4 4{If LGTH > zero or > 80, STR is not changed. } 4 n_name, i, j+1); 4if pos (' ', in_name) > 0 then find_prefix; 4out_name := concat (out_last, ', ', in_name); 4if wk_suff > '' 7then out_name := concat (out_name, ', ', wk_suff); 4blank1 (out_name); end; {LNAME} procedure NEWLEN; {Change length of th (in_name)]); 7end 4else i2 := 0; 4i := 0; 4if i1 <> 0 then i := i1; 4if i2 <> 0 then 7if i = 0 then i := i2 7else if i2 > i then i := i2; 4i := length (in_name) + i; 4j := length (in_name) - i; 4out_last := copy (in_name, i+1, j); 4delete (i4wk_suff := ''; 4find_suffix; 4if pos (' ', in_name) > 0 then begin 7i1 := scan (-length (in_name), =' ',  0 then begin 7i2 := scan (-length (in_name), ='.',  80) then begin 7out_name := ''; 7out_last := ''; 7exit (LNAME); 7end; 4{endif} *type longstr = string [255]; . *var wk_source: longstr; 4wk_dest: longstr; 4i,j: integer; 4 *procedure expand (str: string; var xstr: longstr); % *var wk_char: char; 4st_1: string [1]; 4 *begin st_1 := '*'; 4xstr := copy (str, 1, 1); 4for i := 2 to (length (str) - 1) do begin 8if (str [i] = '-') and ;(ord (str [i-1]) < ord (str [i+1])) then begin  0 7then result := x 7else result := 1; 4{endif} 4for i := (y-1) downto 1 do result := result * x; end;{X_TO_Y}  procedure OPEN; {Open a supplied filenameend; {UPPER1} $ procedure X_TO_Y; {Returns X to the Yth Power AMB 12/22/82} 4 4{ x: long_12 } 4{ y: integer } 4{var result: long_12 r[i]:= chr(ord(str[i]) - 32); ;prev_letter := true ;end 8else if (str[i] in ['A'..'Z']) then begin ;if (prev_letter) then str[i]:= chr(ord(str[i]) + 32); ;prev_letter := true ;end 8else prev_letter := false; 8{endcase} 4end; {for i} in ['a'..'z'] then str[1]:= chr(ord(str[1]) - 32); 4if str[1] in ['A'..'Z'] 7then prev_letter := true 7else prev_letter := false; 4{endif} 4for i := 2 to length (str) do begin 8if (str[i] in ['a'..'z']) then begin ;if (not prev_letter) >then st } 4{var str: string } 4{ } 4 *var i: integer; 4prev_letter: boolean; % *begin if str[1] *begin for i := 1 to length (str) do 8if ord(str[i]) in [97..122] ;then str[i]:= chr(ord(str[i]) - 32); 8{endif} 4{end for i} end; {UPPERSTR} $ procedure UPPER1; {Change string to mixed case AMB 12/31/82} 4{ 12/31/82} 4{ } 4{var str: string } 4{ } 4 *var i: integer; } 4{ } 4 *begin if ord(ch1) in [97..122] 7then ch1:= chr(ord(ch1) - 32); 4{endif} end; {UPPERCHR} procedure UPPERSTR; {Change string to upper case AMB > 0 then xstring [i] := wk_dest [j]; 4end;{for i} end; {TRANSLIT} ( procedure UPPERCHR; {Change character to upper case AMB 12/17/82} 4{ } 4{var ch1: char 4expand (dest, wk_dest); 4while (length (wk_source) > length(wk_dest)) do 7wk_dest := concat (wk_dest, Bcopy (wk_dest,length(wk_dest),1)); 4{end while} 4for i := 1 to length (xstring) do begin 8j := pos (copy (xstring, i, 1), wk_source); 8if j t (xstr, st_1)  77 then write (up); -uw_2 [1] := ord (wk_now + line_strt); -unitwrite (1, uw_2, 3,,12); *end; {display} *procedure init; *begin -strg := default; -lgth := length (strg); -wk_now := 1; -i_mode := false; *end; {init} * *begin *if max_lgth > 78 then max_lgth := 78; *if max_lgth < 1 then max_lgth := 1; *while length (strg) > max_lgth do 4requestcode.channel := 1; 4requestcode.request_num := 16; 4requestcode.stat_or_ctrl := 0; 4requestcode.reserved := 0; 4user := true; 4if copy (PATHNAME, 1, 2) = '**' then begin 7delete (PATHNAME, 1, 2); 7user := false; 7end; 4{endif} 4repeat  IO_METHOD parm'); 7writeln ('I/O method passed = "',IO_METHOD,'".'); 7writeln ('Fix the calling program, please.'); 7writeln ('EXIT triggered by subroutine.'); 7exit (program) 7end; 4{endif} 4{$iocheck-} 4unitnumber := 1; -end; *{endif} *end;{GET_STRG} *begin upperstr (IO_METHOD); 4upperstr (PATHNAME ); 4blank1 (IO_METHOD); 4blank1 (PATHNAME ); 4if (IO_METHOD = 'REWRITE') or (IO_METHOD = 'RESET') 7then 4else begin 7writeln ('Procedure OPEN error: Invalid'|', strg, wk_now); 6lgth := lgth + 1; 6display; 6end 0else write (beep); 0read (keyboard, wk_char); -end; {do while not eoln and not esc} *until (eoln (keyboard)); *if i_mode then begin -delete (strg, wk_now, 1); -lgth := lgth - 1; -display; 0else if ((wk_char=open_i) or (wk_char=open_ii)) then 3if i_mode then begin 6delete (strg, wk_now, 1); 6lgth := lgth - 1; 6i_mode := false; 6display; 6end 3else if wk_now > max_lgth-2 6then write (beep) 3else begin 6i_mode := true; 6insert (else if wk_char = open_l then begin 3i := wk_now - 1; 3if i < 1 then write (beep) 3else begin 6delete (strg, i, 1); 6lgth := lgth - 1; 6wk_now := wk_now - 1; 6write (left); 6display; 6end; 3end wk_now] := '|'; 9display; 9end; 6write (left); 6end 0else if wk_char = open_r then begin 3i := wk_now; 3if i_mode then i := i + 1; 3if i > lgth then write (beep) 3else begin 6delete (strg, i, 1); 6lgth := lgth - 1; 6display; 6end; 3end 0:= strg [wk_now]; 9strg [wk_now] := '|'; 9display; 9end; 6write (right); 6end 0else if wk_char = l_arrow then 3if wk_now = 1 then write (beep) 3else begin 6wk_now := wk_now - 1; 6if i_mode then begin 9strg [wk_now+1] := strg [wk_now]; 9strg [6else write (beep); 6end 0else if wk_char = r_arrow then 3if wk_now > lgth then write (beep) 3else begin 6wk_now := wk_now + 1; 6if i_mode then if wk_now > lgth then begin 9write (beep); 9wk_now := wk_now - 1; 9end 6else begin 9strg [wk_now-1] ow + 1; 9display; 9end 3else begin 6if wk_now > lgth then begin 9lgth := lgth + 1; 9strg := concat (strg,' '); 9end; 6strg [wk_now] := wk_char; 6display; 6if wk_now < max_lgth then begin 9write (right); 9wk_now := wk_now + 1; 9end ((not eoln (keyboard)) and (wk_char <> esc)) do begin - if wk_char in [' '..'~'] then 3if i_mode then 6if lgth = max_lgth 9then write (beep) 6else begin 9insert (' ', strg, wk_now); 9lgth := lgth + 1; 9strg [wk_now] := wk_char; 9wk_now := wk_nght := chr ( 9); *beep := chr ( 7); open_ii := chr (201); *default := strg; *repeat -init; -display; -read (keyboard, wk_char); -if not eoln (keyboard) then if wk_char in [' '..'~'] then begin 0strg := ''; 0lgth := 0; 0end; -while *uw_2 [0] := 24; uw_2 [1] := 0; uw_2 [2] := 5; *esc := chr ( 27); l_arrow := chr ( 8); r_arrow := chr ( 21); *open_i := chr (233); open_l := chr (136); open_r := chr (149); *up := chr ( 11); left := chr ( 8); ridelete (strg, length (strg), 1); *if line_strt < 0 then line_strt := 0; *if line_strt + max_lgth + 2 > 80 -then line_strt := 80 - max_lgth - 2; *uw_1 [0] := 6; uw_1 [1] := 24; uw_1 [2] := 0; 7unitstatus (unitnumber, statuslist, requestcode); 7y_1 := ord (statuslist [2]); 7if user then begin :writeln; :write ('Enter pathname of the ', DISPLAY_NAME, ': '); :get_strg (PATHNAME, =78 - 24 - length (display_name), =24 + length (display_name)); :writeln; :upperstr (PATHNAME); :blank1 (PATHNAME); :end; 7{endif} 7if PATHNAME = '' then begin :error_num := 0; :writeln; :writeln ('No file'); :end 7else if IO_METHOD = 'REWRITE' then begin :rewrite (FILENAME, PATHNAME); :error_num := iunter variable. 5. INTSTR Integer representation of a numeric string. 6. IOERROR The name of an input/output error, given its error code. 7. LNAME Extract a "last name" from a name ordered by first-name, middle-name orhe following members: 1. BASE TEN Integer representation of a hex string. 2. BLANK1 Strip multiple, leading, and trailing blanks from a string. 3. HEX4 Hexadecimal representation of an integer. 4. INC Increment an integer coonce a bit more and a bit less than is needed for good software engineering in the Apple /// PASCAL environment. This article presents an additional PASCAL utility library, one that extends PASCAL even more usefully. The library unit, PLUTIL, consists of to have library units that extend the language is an example of that power. Apple Computer, Inc. offers one such set of extensions under the name "Apple /// Pascal Utility Library," product C3S0001. Those having that program product may agree that it is at Introduction PASCAL is a powerful microcomputer programming language. Its ability t ALLAN M. BLOOM, PhD CDP 2303 San Marcos Street, Blacksburg, Virginia 24060 Office: (703) 231-7921 Home: (703) 951-2025 PASCAL UTILITIES FOR APPLICATIONS DEVELOPMENT =end; :{endif} :if response = 'ABORT' then begin =close (FILENAME); =exit (program); =end; :{endif} :end; 4until error_num = 0; 4{$iocheck+} end; {OPEN} BEGIN {PLUTIL Initialization} END. estcode); :y_2 := ord (statuslist [2]); :write (chr (6)); :for i := y_2 downto y_1 do begin >gotoxy (0, i); >write (chr(30)); :end; {for i} :write (chr (5)); :if response = 'QUIT' then begin =PATHNAME := ''; =error_num := 0; =close (FILENAME); _msg); :writeln; :writeln ('Press RETURN to retry'); :writeln ('Enter "QUIT" for no file'); :writeln (' or "ABORT" to terminate this program'); :response := ''; :readln (response); :upperstr (response); :unitstatus (unitnumber, statuslist, requ>if error_num = 0 then PATHNAME := response; >end; :{endif} :end; 7{endcase} 7if error_num <> 0 then begin :if user = false then writeln (PATHNAME, ' invalid'); :user := true; :writeln; :ioerror (error_num, error_msg); :writeln ('ERROR: ', errororesult; :end 7else begin :reset (FILENAME, PATHNAME); :error_num := ioresult; :if (error_num > 0) :and (pos ('.TEXT', PATHNAME) = 0) then begin >response := concat (PATHNAME, '.TEXT'); >reset (filename, response); >error_num := ioresult; initial, last-name, and suffix. 8. NEWLEN Change the length of a string variable, padding with blanks if the new length is longer than the old. 9. NIBBLEX Two-character hexadecimal representation of a CHAR field. 10. OPEN Open a file given an English title and default pathname. Give the user a chance to correct any I/O errors. 11. TRANSLIT Transliterate specified characters in a string. 12. UPPERCHR Change a CHAR variable's alphabetic value to PLUTIL October 31, 1984 Page 2 Bloom Pascal Utilities INC is a procedure that increments an integer variable. It a {Returns "strg" = FFFF } C: hex4 (32767, strg) {Returns "strg" = 7FFF } Note that in both BASE 10 and HEX4 the hexadecimal representations are displayed in the "normal" way, with the least significant byte last. any fullword equivalent to an integer, and it returns a string of four hexadecimal digits ("0" through "F"). Examples: A: hex4 (4660, strg); {Returns "strg" = 1234 } B: hex4 (-1, strg) if (strg = "N") or (strg = "n") then exit (program); Example "B" is an example of "user friendly" programming. The program will correctly interpret " no ", "N", and "Not on your life!" HEX4 is the inverse of BASE 10. Feed it an integer, or Public '); {Returns "strg" as 'John Q. Public' } B: writeln ('Continue? ("Y" - default or "N"'); readln (strg); blank1 (strg); strg := copy (strg, 1, 1); F (-1). BLANK1 is a procedure that removes redundant blanks from a string variable. The returned string has no leading or trailing blanks, and it has no consecutive blanks within it. Examples: A: blank1 (' John Q. = 0 {Not hexadecimal } E: base ten ('12345')= 0 {Longer than four characters} Note that half the available values of an integer variable are reserved for negative numbers. They go from $8000 (-32768) to $FFFe conversion. Examples: A: base ten ('1234') = 4660 B: base ten ('FFFF') = 65535 = -1 {Integer over 32767 negative} C: base ten ('7FFF') = 32767 {Maximum positive integer } D: base ten('XYZ')character is found in the string or if the string is longer than four characters. At the nuts and bolts level of Pascal and SOS, a lot of values are more easily expressed in hex. You might wish to tell a program the number in hex and let the computer do thties BASE TEN is a function taking a single argument, a string of characters representing up to four (4) hexadecimal digits ("0" through "F"). It returns its decimal equivalent as an integer. The routine returns zero (0) if a non-hex ys these examples and offers you a chance to exercise the modules with your own. PLUTIL October 31, 1984 Page 1 Bloom Pascal Utiliach of the above modules is discussed, in its turn, in the following paragraphs. We'll be looking at not only how to use them, but why. Some are self-evident. Some are less so. Examples of use are also given. The accompanying Pascal program TESTUTIL displats Yth (integer) power. Two modules (HEX4 and BASE TEN) owe much to Jeppson ( Softalk, September 1982, 73-86). One other (TRANSLIT) is derived from from Kernighan and Plauger ( Software Tools in Pascal, Addison-Wesley: Reading MA, 1981, 51-57). Eupper case. 13. UPPERSTR Change a string's alphabetic characters to upper case. 14. UPPER1 Translate a string variable to mixed case. 15. VARIANT Eight different ways to look at a sixteen-bit word. 16. X TO Y Take a long integer X to illows you to write "inc (integer variable);" instead of the wordier "integer variable := integer variable + 1;" Example: A: array pointer := 4660; inc (array pointer); {Returns "array pointer" as 4661 } B: array pointer := -4660; inc (array pointer); {Returns "array pointer" as -4559 } It is good programming practice to have meaningful (long, Englishlike) data names, and INC just takes some of the bother out of using them. <--- RIGHT} {Returns "last name" as "T" <--- RIGHT} This procedure does a pretty good job of finding a last name, but it is not perfect. In common with most such routines, it could have trouble recognizing a name's suffix {Returns "out name" as ", Mr. T" <--- WRONG} {Returns "last name" as "" <--- WRONG} F: lname ('Mr. T,', out name, last name); {Returns "out name" as "T, Mr." name ('John Mac Donald', out name, last name); {Returns "out name" as "Mac Donald, John" <--- RIGHT} {Returns "last name" as "Mac Donald" <--- RIGHT} E: lname ('Mr. T', out name, last name); "Snodgrass" } C: lname ('John Dos Passos', out name, last name); {Returns "out name" as "Passos, John Dos" <--- WRONG} {Returns "last name" as "Passos" <--- WRONG} D: llic, John Q."} {Returns "last name" as "Public" } B: lname ('Gladys P. Snodgrass Phd', out name, last name); {Returns "out name" as "Snodgrass, Gladys P., PhD"} {Returns "last name" asfirst" name and returns both the person's "last-name" and the name resequenced as a "last-name first" string. Examples: A: lname (' John Q. Public ', out name, last name); {Returns "out name" as "Pubr 8, 1982. PLUTIL October 31, 1984 Page 3 Bloom Pascal Utilities LNAME is a procedure that takes a normal "first-name ll"} C: ioerror (246, io err name); {Returns "io err name" as "Invalid error code"} This procedure contains all 128 Pascal and SOS I/O errors (from 0 through 127) as listed in Apple Tech Notes Number 6150.014, issued September than letting a program crash. Examples: A: ioerror (10, io err name); {Returns "io err name" as "No such file"} B: ioerror (73, io err name); {Returns "io err name" as "(SOS) Directory fupposed to be legal, I have been unable to assign that value to an integer variable. IOERROR is a procedure that returns the English meaning of an input or output error. This is useful when you are trapping the errors yourself, rathegives lead/trail blanks } This routine is useful for keyboard entry. Instead of getting a crash when the user klutzes, the program can read a string, analyze it, and ask the user for correct input if the string is non-integer. Note that while -32768 is su Examples: A: intstr ('1234') = 1234 B: intstr ('65535') = 0 {Integer over 32767 } C: intstr ('7FFF') = 0 {Non decimal characters } D: intstr(' -123 ')= -123 {Forgn ("-" or "+"). The remainder of the string may not be longer than five characters, it may contain no non-numeric character, and its numeric value must be in the integer range of -32767 through 32767. The routine returns zero if the string fails any test.INTSTR is a function taking a single argument, a string of characters representing an integer value. It returns the string's decimal equivalent as an integer. The string may have leading or trailing blanks, and it may have a leading si(Jr, III, PhD, MD, etc), a two-word last name (Dos Passos), or a non-standard last name (T). The variety of human names is a smidge too great for perfection. The routine recognizes many suffixes, by either rule-of-thumb or from a specified list. Also, the routine takes anything after the first occurrence of a comma as the name's suffix. A judiciously placed comma can handle awkward cases. In the case of "Mr. T," the routine's rules of thumb get in the way. The last substring contains no vowels, so itprompts the user to supply a valid pathname for the file. You may also use PLUTIL's error-trapping features in "no display" mode, not bothering the user unless an I/O error occurs. PLUTIL October 31, 1984 FILETYPE is TEXT, which works for almost all types of file. It also specifies an English language DISPLAY NAME for the file and the way the file is to be opened, either RESET or REWRITE. It may optionally also specify a default PATHNAME for the file. OPEN OPEN is a general-purpose file opener. It leads a user through the opening of a specified file in a standard way with extensive error trapping. The program supplies the internal filename and its associated FILETYPE. The default (wk char, outhex); {Returns "outhex" as '30'} NIBBLEX will take either a packed or an unpacked character and return the same hexadecimal representation of its constituent nibbles. For an unpacked character, it looks only to the two low-order nibbles. A: var wk char: char; outhex: string; wk char := 'A'; nibblex (wk char, outhex); {Returns "outhex" as '41'} B: wk char := '0'; nibblex ARRAY [1..512] OF CHAR? NIBBLEX also returns the nibbles in "normal" order, high nibble first. Do you get the feeling that this procedure is a crutch for byte-oriented programmers who can't handle low-nibble-first representations? Examples: ng" files in character and hexadecimal, to look at their innards. HEX4 could be used, but it can be more convenient to think in terms of bytes than in words. If we say that a block of data takes up 512 bytes, why shouldn't we look at that block as a PACKED -- more important -- in having the courtesy to pad lengthened strings with spaces. NIBBLEX is a procedure that expands a character (byte) into its two component hexadecimal nibbles. The author has found this of most use in "dumpirns "strg" as ' John Q.' } B: strg := ''; newlen (strg, 4); {Returns "strg" as ' ' } NEWLEN will not accept a string longer than 80 characters. Its usefulness here lies in saving a few lines of text andthe right. If the new length is longer that the original one, spaces are added to the right. As examples: A: var strg: string; strg := ' John Q. Public '; newlen (strg, 13); {Retu Bloom Pascal Utilities NEWLEN is a procedure that changes the length of a string variable. If the new length is shorter than its original length, the string is truncated to returned as "Passos." This problem can be avoided by either entering the name as "DosPassos" or by replacing the blank with a non printing character. PLUTIL October 31, 1984 Page 4 ixes the problem. Another problem is "two-word" last names. The program recognizes a very few last-name prefixes (e.g. Von, Van, de, la, Di, Mac) from a specified list. It doesn't handle all of them. For example, the last name "Dos Passos" is is classed as a suffix. The next to the left terminates with a period, so it is taken as an abbreviation (the routine can handle any number of suffixes). The result could annoy a gentleman with whom it is not nice to mess. Placing a comma after the name f Page 5 Bloom Pascal Utilities If an existing textfile is to be opened, the routine permits an entry without the ".TEXT" suffix. When a valid pathname is entered, or if the default is selected, the file is opened and the pathname is returned to the calling program. If there is no file to be opened, the routine returns a null string as the pathname. A default pathname prefixed with "**" (double asterisk) indicates the "no dissource and destination strings before processing. It then forces the destination string to the same length as the source string -- by lopping "excess" characters or padding with the repeated occurrences of the last destination-string character. A repeated (-) may be used in either the source or the destination strings as shorthand for a range of character values of increasing ordinality. For example, "a-z" is equivalent to writing all 26 characters from "a" through "z." TRANSLIT expands any "ranges" in the literated from "aeiou" to "AEIOU" will have all its vowels capitalized. All characters in a string that match a character in the "source" string are changed to the character in the same position of the "destination" string. In TRANSLIT a dash is a procedure that transliterates specified characters in a string to other specified characters. For example, you may ask TRANSLIT to change every occurrence of "a" in a string to "1." TRANSLIT can also perform multiple translations. A string transe calling program must test for that condition after the call. PLUTIL October 31, 1984 Page 6 Bloom Pascal Utilities TRANSLIT the problem and the user options. Afterwards, OPEN blanks all messages. If "retry" was requested, OPEN re-displays the prompt at its original screen position. Note that OPEN can return a null pathname, indicating that there is no such file. Thogram. "ABORT" stops everything and exits the program. If you leave nine screen lines for OPEN, the error message and re-entry cycle will not cause the screen to scroll. When an invalid entry is detected, the routine uses six lines to display OERROR procedure. If the user mis-typed the file's pathname, or accepted an invalid default pathname, or didn't have the right disk in the right drive, pressing RETURN gives him or her another chance. The "QUIT" option returns a null pathname to calling pr to retry or "QUIT" for no file or "ABORT" to terminate this program In "no display" mode, the messages are preceded by a line containing the pathname that caused the error. The error-description comes from the Inother printer's name, such as SILENTYPE or QUME. A blank entry (one or more blanks followed by RETURN) indicates that there is no file. An I/O error yields the following messages: ERROR: error-description Enter RETURN been a null string (''), the second line would not appear. If the default pathname had been '**.printer,' the message would not appear, and the .PRINTER would be opened without user intervention. The user may press RETURN to accept the default or key in a no file }; During the procedure call, the user would see the following prompt on the console screen: Enter the pathname of the printer you are using: Default = .PRINTER Response --> [] If the default pathname hadtring gets no prompt} A: display name := 'printer you are using'; pathname := '.printer'; open (prtfile, display name, 'rewrite', pathname); if pathname = '' then {Processing forplay" mode. As an example: var prtfile: text; display name: string; io method: string; {Either RESET or REWRITE } pathname: string; {Null ssource-string character is ignored. Examples: A: wk string := 'Every good boy does fine'; translit (wk string, 'aeiou', '12345'); {Returns "wk string" as 'Ev2ry g44d b4y d42s f3n2' } B: translit (wk string, 'a-z', 'A-Z'); {Returns "wk string" as 'EVERY GOOD BOY DOES FINE' } C: translit (wk string, 'a-z', 'A'); {Returns "wk string" as 'AAAAA AAAA AAA AAAA AAAA' } TRANSLIT is nibbles = 4 3 2 1 boolean = FALSE octals = 4 6 0 1 1 The first thing that you had best notice is that everything is "backwards." You, I, and almost everyone else (Apple's P-code interpreter e4660; {Put 4660 into "v" as an integer variable} bits = 0010 1100 0100 1000 char = 4 pkd chrs= 4 DC2 bytes = 52 18 octals. This is a bit more than another toy for the bit-fiddling types among us. It can be educational actually seeing how many different ways Pascal can view the same bits. Examples: var v: variant; A: v.int := erent ways. Once you have declared a particular word of memory as type VARIANT, you may reference it as an integer, a character, a pair of packed characters, a boolean, a packed array of 16 booleans, a pair of 0..255 bytes, four 0..15 nibbles, or five 0..7in a sequence of alphabetic characters and lowercases any alphabetic character that is preceded by a letter. VARIANT is neither a procedure nor a function. It, is rather, a data type that defines a single word of memory eight diffupperstr (wk string); {Returns "wk string" as 'John Dos Passos' } Note in example "B" that UPPER1 is not a panacea. The "phd" should be written "PhD" as the proper abbreviation. UPPER1 capitalizes the first alphabetic character ublic ' } B: wk string := 'gladys p. snodgrass, phd'; upperstr (wk string); {Returns "wk string" as 'Gladys P. Snodgrass, Phd'} C: wk string := 'John Dos PASSOS'; n m. bloom" or as "ALLAN M. BLOOM," UPPER1 will change the string to "Allan M. Bloom." Examples: A: wk string := ' JOHN Q. PUBLIC '; upperstr (wk string); {Returns "wk string" as ' John Q. P UPPER1 takes a string and turns it into "mixed case," with the first letter of a group capitalized and the rest in lower case. This is most useful in displaying data. No matter whether a record field is in your data base as "allaame ".PRINTER." That is how many different tests you save by capitalizing. PLUTIL October 31, 1984 Page 7 Bloom Pascal Utilities wk string); upperstr (wk string); if wk string = '.PRINTER' then {whatever} UPPERCHR saves a little programming bother, but UPPERSTR can save a lot. Imagine how many different ways that someone can enter the device n; readln (input, wk char); upperchr (wk char); if wk char = 'N' then exit (program); B: write ('Enter the pathname of the output file --> '); readln (input,hat uppercase. UPPERCHR operates on CHAR variables, and UPPERSTR operates on strings. Each changes any lower-case alphabetic character to its upper-case equivalent. Examples: A: write ('Continue? (Y - Default | N) --> ')one of those routines that seems like a good idea, but may not actually be too useful. Uppercasing a string can be accomplished much more efficiently by other means (see UPPERSTR). It may come in handy sometime. UPPER-CHR/STR are a pair of procedures txcepted) think that the "high order anything" belongs on the left. You, I, and almost everyone else outside the Orient read things left-to-right. When you get within an Apple Pascal word, however, things read right-to-left. PLUTIL October 31, 1984 Page 8 Bloom Pascal Utilities Noting that you must read right-to-left, the above entries for bits, nibbles, and bytes should ma string; 8end; ( procedure init_menu; var i: integer; (sub_title: array [1..3] of string; ( (procedure title; (var fill1: string; 2fill2: string; (begin 0fill1 := ''; 0fill2 := ''; 0with m_menu do char; (m_menu: record 8m_number: array [1..18] of string; 8m_display: array [1..18] of string; 8m_text: array [1..18] of string; 8m_max: integer; 8m_choice: integer; 8m_start: integer; 8m_title: {$list} program testutil; {Test PLUTIL procedures and functions AMB 09-28-83} uses plutil; var wk_integer: integer; (wk_string: string; (wk2_strg: string; (wk3_strg: string; (wk4_strg: string; (wk_char:  M0 M1 G-G-O^Krary unit. Examples: var x: integer [12]; y: integer; result: integer [12]; A: x := 4; y := 2; x to y (x, y, result); {Returns "result" as turning a long integer result. The long integers must be of "length" 12 (INTEGER [12]) each. Pascal does not provide for integer exponentiation, and that particular arithmetic operation can come in handy. Pascal 1.1 provides this capability in its SANE libe-bit numbers comfortably. The high bit is left over and is ignored. The set of octals would be the same whether the rightmost bit were "0" or "1." X TO Y is a procedure that raises a long integer "X" to its integer Yth power, ree "18" in this case. The boolean equivalent of integer 4660 is FALSE. Since the leftmost (lowest order) bit is "0," the whole word is evaluated as FALSE. The "octal" representation shouldn't work. A sixteen-bit word does not hold a set of threke sense to the mathematicians among you. The "char" value of "4" proves that Pascal pays no attention to the high-order byte of a CHAR variable. When you define the word as a pair of packed CHAR variables, however, it does look to the word's high byte, thbegin 0sub_title [1] := 'TESTUTIL: TEST Program for PLUTIL Routines'; 0sub_title [2] := 'AMB'; 0sub_title [3] := 'v.10/83'; 0m_title := sub_title [1]; 0i := length (m_title) + length (sub_title [2]) - 80; 0if i > 0 then newlen (sub_title [2], 80 - i); 0i := length (m_title) + length (sub_title [2]) 3+ length (sub_title [3]) - 80; 0if i > 0 then newlen (sub_title [3], 80 - i); 0m_title := concat (sub_title[1],sub_title[2],sub_title[3]); 0if length (m_); -repeat 0read (keyboard, wk_char); 0if eoln (keyboard) then begin 5wk_char := chr (13); 5end 0else if wk_char = chr(27) then begin 5end 0else if wk_char in [chr(10),chr(11)] then begin 5wk_strg := ''; 5gotoxy (10, wk_now + m_start - 1); 5wriif m_choice < 1 then m_choice := 1; *if m_choice > m_max then m_choice := m_max; *repeat -gotoxy (10, m_choice + m_start - 1); -write (chr (18), m_display [m_choice], chr (17)); -wk_now := m_choice; -wk_next := 0; -wk_strg := ''; -unitclear (21write (m_number [i]: 7, m_display [i]: 19, m_text [i]: 52); .{endif} *end;{for i} *gotoxy (0, 21); *for i := 1 to 79 do write ('_'); *gotoxy (0, 23); *write ('Select a menu item by number or up/down ', .'arrow. ESCAPE corrects. "Q" quits.'); *6)); {cursor off} *with m_menu do begin *gotoxy (0,0); *write (chr (29)); *write (m_title); *gotoxy (0,1); *for i := 1 to 79 do write ('_'); *gotoxy (0, m_start); *for i := 1 to 18 do begin .gotoxy (0, i + m_start - 1); .if i <= m_max then 6); ,newlen (m_text [i], 50); (end;{for i} (end;{with m_menu} end;{init_menu} ( procedure menu (var m_choice: integer); var i: integer; *wk_now: integer; *wk_next: integer; *wk_strg: string; begin *write (chr(0splay [ 8]:= 'NEWLEN'; (m_text [ 8]:= 'Change the length of a string variable.'; (m_display [ 9]:= 'NIBBLEX'; (m_text [ 9]:= 'Expand a CHAR variable into its hex nibbles.'; (load_next_nine; (for i := 1 to m_max do begin ,newlen (m_display[i], 1(m_text [ 5]:= 'Integer from a numeric string.'; (m_display [ 6]:= 'IOERROR'; (m_text [ 6]:= 'Name of an input/output error from error number.'; (m_display [ 7]:= 'LNAME'; (m_text [ 7]:= 'Last name and sort name from a name string.'; (m_dil blanks from a string.'; (m_display [ 3]:= 'HEX4'; (m_text [ 3]:= 'Hexadecimal string representation of an integer.'; (m_display [ 4]:= 'INC'; (m_text [ 4]:= 'Increment an integer counter.'; (m_display [ 5]:= 'INTSTR'; ', m_number [i]); ,m_number [i] := concat ('[', m_number [i], ']'); (end;{for i} (m_display [ 1]:= 'BASE_TEN'; (m_text [ 1]:= 'Integer representation of a hexadecimal string.'; (m_display [ 2]:= 'BLANK1'; (m_text [ 2]:= 'Strip double/lead/traiger X to the Yth power.'; (end;{with m_menu} end;{load next nine} ( begin (with m_menu do begin (m_start := 4; (m_max := 16; (m_choice := 1; (title; (for i := 1 to m_max do begin ,str (i, m_number [i]); ,if i < 10 then m_number [i] := concat (' (m_display [14]:= 'UPPER1'; (m_text [14]:= 'Change a string variable to mixed case.'; (m_display [15]:= 'VARIANT'; (m_text [15]:= 'Eight different ways to view a sixteen bit word.'; (m_display [16]:= 'X_TO_Y'; (m_text [16]:= 'Raise long inteliterate characters in a string variable.'; (m_display [12]:= 'UPPERCHR'; (m_text [12]:= 'Change a CHAR variable to upper case.'; (m_display [13]:= 'UPPERSTR'; (m_text [13]:= 'Change a string variable to upper case.'; endif} 0end;{with m_menu} (end;{title} ( (procedure load_next_nine; (begin (with m_menu do begin (m_display [10]:= 'OPEN'; (m_text [10]:= 'Open a file, prompting with title and pathname.'; (m_display [11]:= 'TRANSLIT'; (m_text [11]:= 'Transtitle) < 79 then begin 3i := 79 - length (m_title); 3newlen (fill1, i div 2); 3newlen (fill2, i div 2); 3if (2 * (i div 2) <> i) then newlen (fill1, i div 2 + 1); 3m_title := concat (sub_title[1], fill1, 6sub_title[2], fill2, subtitle[3]); 3end; 0{te (m_display [wk_now]); 5if wk_char = chr (11) 8then wk_next := wk_now - 1 8else wk_next := wk_now + 1; 5{endif} 5if wk_next > m_max then wk_next := 1; 5if wk_next < 1 then wk_next := m_max; 5gotoxy (10, wk_next + m_start - 1); 5wk_now := wk_next; 5write (chr (18), m_display [wk_now], chr (17)); 5end 0else if wk_char in ['0'..'9'] then begin 5newlen (wk_strg, length (wk_strg) + 1); 5wk_strg [length (wk_strg)] := wk_char; 5wk_next := intstr (wk_strg); 5while (wk_next > m_to hexadecimal --> '); .readln (wk_string); .wk_integer := intstr (wk_string); .writeln; .if (wk_integer = 0) and (wk_string <> '0') then begin 1writeln ('Naughty. I said an integer'); 1writeln ('Entry ''',wk_string,''' is not a valid integer'); 1wrger := 32767; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the integer to convert (writeln ('HEX4 (', wk_integer, ', wk_string); wk_string = ''', 0wk_string, ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing HEX4'); (writeln; (wk_integer := 4660; (test; (wk_integer := -1; (test; (wk_inte .readln (wk_string); .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_blank1} ( procedure test_hex4; (procedure test; (begin; (hex4 (wk_integer, wk_string); '; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the string to be deblanked --> ');rite ('BLANK1 (''', wk_string, ''') = '); (blank1 (wk_string); (writeln ('''',wk_string,''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing BLANK1'); (writeln; (wk_string := ' John Q. Public .write ('Enter the hexadecimal string to convert --> '); .readln (wk_string); .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_base_ten} ( procedure test_blank1; (procedure test; (begin; (writeln; (wYZ'; (test; (wk_string := '12345'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; (''', wk_string, ''') = ', wk_integer); (writeln; (end; begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing BASE_TEN'); (writeln; (wk_string := '1234'; (test; (wk_string := 'FFFF'; (test; (wk_string := '7FFF'; (test; (wk_string := 'X.unitclear (2); .read (keyboard, wk_char); .writeln; .if (wk_char = 'y') or (wk_char = 'Y') 1then 1else wk_char := 'n'; .{endif} end;  procedure test_base_ten; (procedure test; (begin (wk_integer := base_ten (wk_string); (writeln ('BASE_TEN -m_choice := 0; -end *else if wk_next > 0 then begin -m_choice := wk_next; -end; *{endif} *end;{with m_menu} *unitclear (2); *write (chr (5)); {cursor on} end;{menu} ( procedure check_n; begin .Write ('Another one? < Y or N - Default> --> '); hr (13), chr (27), 'Q']); -if wk_char = chr (27) then begin 0gotoxy (10, wk_now + m_start - 1); 0write (m_display [wk_now]); 0unitclear (2); 0end; -{endif} *until ((wk_char = 'Q') or (wk_char = chr (13))); *if wk_char = 'Q' then begin ]); 5wk_now := wk_next; 5gotoxy (10, wk_now + m_start - 1); 5write (chr (18), m_display [wk_now], chr (17)); 5end 0else if wk_char in ['q','Q'] then begin 5wk_char := 'Q'; 5end 0else begin 5write (chr (7)); 5end; 0{endif} -until (wk_char in [cmax) do begin 8if length (wk_strg) > 0 then delete (wk_strg, 1, 1); 8wk_next := intstr (wk_strg); 5end; 5if wk_next < 1 then begin 8write (chr (7)); 8wk_next := wk_now; 8end; 5{endif} 5gotoxy (10, wk_now + m_start - 1); 5write (m_display [wk_nowiteln; 1end .else begin 1test; 1end; .{endif} .check_n; +until (wk_char = 'n'); +end; ({endif} (unitclear (2); end;{test_hex4} procedure test_inc; (procedure test; (begin (write ('INC (', wk_integer, ') = '); (inc (wk_integer); (writeln (wk_integer); (writeln; (end;  begin; (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing INC'); (writeln; (wk_integer := 4660; (test; (wk_integer := -4660; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Deedure test_newlen; (procedure test; (begin; (writeln ('NEWLEN (''', wk_string, ''', ', wk_integer, ');'); (newlen (wk_string, wk_integer); (writeln ('String = ''', wk_string, ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); ar); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the name --> '); .readln (wk_string); .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_lname} ( proc(wk_string := 'John Dos Passos'; (test; (wk_string := 'Mr. T'; (test; (wk_string := 'Mr. T,'; (test; (wk_string := 'John Mac Donald'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_ch Last Name = ''',wk3_strg,''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing LNAME'); (writeln; (wk_string := ' John Q. Public '; (test; (wk_string := 'Gladys P. Snodgrass PhD'; (test; (writeln; (unitclear (2); end;{test_ioerror} procedure test_lname; (procedure test; (begin; (writeln ('LNAME (''', wk_string, ''', sort_name, last_name) '); (lname (wk_string, wk2_strg, wk3_strg); (writeln ('Sort Name = ''',wk2_strg,'''', ( ' eger = 0) and (wk_string <> '0') then begin 1writeln ('Naughty. I said an integer'); 1writeln ('Entry ''',wk_string,''' is not a valid integer'); 1writeln; 1end .else begin 1test; 1end; .{endif} .check_n; +until (wk_char = 'n'); +end; ({endif} (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the integer I/0 error code (0 thru 127 --> '); .readln (wk_string); .wk_integer := intstr (wk_string); .writeln; .if (wk_int begin; (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing IOERROR'); (writeln; (wk_integer := 10; (test; (wk_integer := 73; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_intstr}  procedure test_ioerror; (procedure test; (begin (write ('IOERROR (', wk_integer, ', io_err_name) = '); (ioerror (wk_integer, wk_string); (writeln (wk_string); (writeln; (end; < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the integer string to convert --> '); .readln (wk_string); .test; .check_n; +until (wk_char = (writeln ('Testing INTSTR'); (writeln; (wk_string := '1234'; (test; (wk_string := '65535'; (test; (wk_string := '7FFF'; (test; (wk_string := ' -123 '; (test; (wk_string := '123456'; (test; (unitclear (2); (Write ('Care to try one yourself? } (writeln; (unitclear (2); end;{test_inc} procedure test_intstr; (procedure test; (begin (wk_integer := intstr (wk_string); (writeln ('INTSTR (''', wk_string, ''') = ', wk_integer); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); nteger = 0) and (wk_string <> '0') then begin 1writeln ('Naughty. I said an integer'); 1writeln ('Entry ''',wk_string,''' is not a valid integer'); 1writeln; 1end .else begin 1test; 1end; .{endif} .check_n; +until (wk_char = 'n'); +end; ({endiffault> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the integer to increment --> '); .readln (wk_string); .wk_integer := intstr (wk_string); .writeln; .if (wk_i(writeln ('Testing NEWLEN'); (writeln; (wk_string := ' John Q. Public '; (wk_integer:= 10; (test; (wk_string := ''; (wk_integer:= 10; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the string --> '); .readln (wk_string); .write ('Enter its new length --> '); .readln (wk2_strg); .wk_integer := intstr (wk2g := 'a-z'; (wk3_strg := 'A-Z'; (test; (wk_string := 'fred'; (wk2_strg := 'a-z'; (wk3_strg := 'A'; (test; (wk_string := 'fred'; (wk2_strg := 'fred'; (wk3_strg := 'dfer'; (test; (wk_string := 'fred'; (wk2_strg := 'f'; (wk3_strg := 'A-Z''', V wk3_strg, ''');'); (translit (wk_string, wk2_strg, wk3_strg); (writeln ('Xstring = ''', wk_string, ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing TRANSLIT'); (writeln; (wk_string := 'fred'; (wk2_str.readln (wk4_strg); .writeln; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_open} procedure test_translit; (procedure test; (begin; (writeln ('TRANSLIT (''', wk_string, ''', ''', wk2_strg, ''', ' --> '); .unitclear (1); .readln (wk2_strg); .write ('Open the file "RESET" or "REWRITE"? --> '); .unitclear (1); .readln (wk3_strg); .upperstr (wk3_strg); .write ('Enter the file''s default pathname --> '); .unitclear (1); char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Is this an "INPUT" or and "OUTPUT" file? --> '); .unitclear (1); .readln (wk_string); .upperstr (wk_string); .write ('Enter the file''s display name eln ('Testing OPEN'); (writeln; (wk_string := 'OUTFILE'; (wk2_strg := 'Printer File'; (wk3_strg := 'REWRITE'; (wk4_strg := '.printer'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_(if wk_string = 'INPUT' then begin +if wk4_strg > ' ' then close ( infile); +end (else begin +if wk4_strg > ' ' then close (outfile); +end; ({endif} (gotoxy (0, 0); (writeln (chr (29)); (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writen ( infile, wk2_strg, wk3_strg, wk4_strg); +end (else begin +open (outfile, wk2_strg, wk3_strg, wk4_strg); +end; ({endif} (unitclear (2); (gotoxy (0, 23); (write ('Press any key to continue'); (read (keyboard, wk_char);  (procedure test; (begin; (if wk_string = 'INPUT' +then write ('OPEN (INFILE, ') +else write ('OPEN (OUTFILE, '); ({endif} (writeln ('''', wk2_strg, ''', ''', 7wk3_strg, ''', ''', 7wk4_strg, ''');'); (if wk_string = 'INPUT' then begin +optclear (1); .read (wk_char); .if eoln (input) then wk_char := chr (13); .writeln; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_nibblex} procedure test_open; var infile, outfile: file; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the character to expand --> '); .uni ( ''', nibbles);'); (nibblex (wk_char, wk_string); (writeln (' = ''', wk_string, ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing NIBBLEX'); (writeln; (wk_char := 'A'; (test; (wk_char := '0'; har = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_newlen} procedure test_nibblex; (procedure test; (begin; (write ('NIBBLEX ('''); (if wk_char < ' ' +then write ('chr(', ord (wk_char), ')') +else write (wk_char); ({endif} (write_strg); .writeln; .if (wk_integer = 0) and (wk2_strg <> '0') then begin 1writeln ('Naughty. I said an integer'); 1writeln ('Entry ''',wk2_strg,''' is not a valid integer'); 1writeln; 1end .else begin 1test; 1end; .{endif} .check_n; +until (wk_c; (test; (wk_string := 'fred'; (wk2_strg := 'ffdd'; (wk3_strg := 'ABCD'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the string to be transliterated --> '); .unitclear (1); .readln (wk_string); .write ('Enter the string of source characters --> '); .unitclear (1); .readln (wk2_st (wk_string, 2); +for i := 1 to 2 do v.byte [i-1] := ord (wk_string [i]); +end; (writeln; (writeln (' Integer: ', v.int); (writeln; (writeln (' Word: ', v.word); (writeln; (write (' Boolean: '); (if v.bool = true +then writeln ('en begin +v.int := intstr (wk_string); +end (else if base_type = 'CHAR' then begin +v.word := wk_char; +end (else if base_type = 'BOOLEAN' then begin +if wk_string = 'TRUE' + then v.bool := true .else v.bool := false; +end (else begin +newlen(unitclear (2); end;{test_up1} procedure test_variant; var base_type: string; (v: variant; (i: integer; ( (procedure test; (begin; (writeln ('VARIANTs of ', wk_string, ' treated as a ', base_type); (if base_type = 'INTEGER' thrd, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the string --> '); .unitclear (1); .readln (wk_string); .writeln; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; 1'); (writeln; (wk_string := ' JOHN Q. PUBLIC '; (test; (wk_string := 'gladys p. snodgrass phd'; (test; (wk_string := 'John Dos PASSOS'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboa_upstr} procedure test_up1; (procedure test; (begin; (write ('UPPER1 (''', wk_string, ''');'); (upper1 (wk_string); (writeln (' = ''', wk_string, ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing UPPER(if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the string --> '); .unitclear (1); .readln (wk_string); .writeln; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{testest; (wk_string := 'Gladys P. Snodgrass PhD'; (test; (wk_string := 'John Dos Passos'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; ('UPPERSTR (''', wk_string, ''');'); (upperstr (wk_string); (writeln (' = ''', wk_string, ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing UPPERSTR'); (writeln; (wk_string := ' John Q. Public '; (t); .read (wk_char); .if eoln (input) then wk_char := chr (13); .writeln; .writeln; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_upchr} procedure test_upstr; (procedure test; (begin; (write (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin +repeat .writeln; .write ('Enter the character --> '); .unitclear (1hen write ('chr(', ord (wk_char), ')') +else write (wk_char); ({endif} (writeln ( ''''); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing UPPERCHR'); (writeln; (wk_char := 'a'; (test; (wk_char := '0'; les: string; (procedure test; (begin; (write ('UPPERCHR ('''); (if wk_char < ' ' +then write ('chr(', ord (wk_char), ')') +else write (wk_char); ({endif} (write ( ''');'); (upperchr (wk_char); (write (' = '''); (if wk_char < ' ' +trg); .write ('Enter the string of X-late characters --> '); .unitclear (1); .readln (wk3_strg); .writeln; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (writeln; (unitclear (2); end;{test_translit} procedure test_upchr; var nibbTRUE') +else writeln ('FALSE'); ({endif} (writeln; (writeln; (write (' Characters: '); (for i := 0 to 1 do begin ,if v.ch [i] < ' ' /then write ('chr(', ord (v.ch [i]), ') ') /else write (v.ch [i], ' '); ,{endif} (end;{for i} (writeln; (writeln; (write (' Bytes: '); (for i := 0 to 1 do begin ,str (ord (v.byte [i]), wk_string); ,write (wk_string:3, ' '); (end; (writeln; (writeln; (write (' Nibbles: '); (for i := 0 to 3 do begin ,str (ord (v.nybl [i]), wk_string); (wk_string <> '0') then begin 4writeln ('Naughty. I said an integer'); 4writeln ('Entry ''',wk_string,''' is not a valid integer'); 4writeln; 4end 1else begin 4y := wk_integer; 4test; 4end 1{endif} 1end; .{endif} .check_n; +until (wk_char = 'nry ''',wk_string,''' is not a valid integer'); 1writeln; 1end .else begin 1x := wk_integer; 1writeln; 1write ('Enter the exponent integer "Y" --> '); 1readln (wk_string); 1wk_integer := intstr (wk_string); 1writeln; 1if (wk_integer = 0) and +repeat .writeln; .write ('Enter the base integer "X" --> '); .readln (wk_string); .wk_integer := intstr (wk_string); .writeln; .if (wk_integer = 0) and (wk_string <> '0') then begin 1writeln ('Naughty. I said an integer'); 1writeln ('Ent(y := -2; (test; (x := 16; (y := 3; (test; (x := -5; (y := 3; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Y') then begin (begin; (write ('X_TO_Y (', x, ', ', y, ', result);'); (x_to_y (x,y,result); (writeln (' = ', result); (writeln; (end;  begin (gotoxy (0, 0); (writeln (chr (29)); (writeln ('Testing X_TO_Y'); (writeln; (x := 4; (y := 2; (test; (x := 4;  --> '); 1readln (wk_string); 1newlen (wk_string, 2); 1end; .test; .check_n; +until (wk_char = 'n'); +end; ({endif} (unitclear (2); end;{test_variant} procedure test_xtoy; var x, result: long_12; (y: integer; ( (procedure test; .else if wk_string [1] = 'I' then begin 1base_type := 'INTEGER'; 1write ('Enter the integer --> '); 1readln (wk_string); 1end .else begin 1base_type := 'Two Characters'; 1writeln ('Enter the two-character string end .else if wk_string [1] = 'C' then begin 1base_type := 'CHAR'; 1write ('Enter the character (No RETURN afterward) --> '); 1read (input, wk_char); 1writeln; 1if eoln (input) then wk_char := chr (13); 1end g [1] = 'B' then begin 1base_type := 'BOOLEAN'; 1write ('Enter the boolean (TRUE - Default | FALSE) --> '); 1readln (wk_string); 1newlen (wk_string, 1); 1upperstr (wk_string); 1wk_string := 'TRUE'; 1if wk_string = 'F' then wk_string := 'FALSE'; 1') then begin +repeat .writeln; .writeln ('Enter the variable''s base type '); .write ('oolean, har, nteger, or ther --> '); .readln (wk_string); .newlen (wk_string, 1); .upperstr (wk_string); .writeln; .if wk_strin(base_type := 'BOOLEAN'; (test; (wk_string := 'AB'; (base_type := 'Two Characters'; (test; (unitclear (2); (Write ('Care to try one yourself? < Y or N - Default> --> '); (read (keyboard, wk_char); (writeln; (if (wk_char = 'y') or (wk_char = 'Yteln (chr (29)); (writeln ('Testing VARIANT'); (writeln; (wk_string := '4660'; (base_type := 'INTEGER'; (test; (wk_string := '-4660'; (base_type := 'INTEGER'; (test; (wk_char := 'A'; (base_type := 'CHAR'; (test; (wk_string := 'FALSE'; o if v.bit [i] = true ,then write ('1 ') ,else write ('0 '); (writeln; (gotoxy (0, 23); (unitclear (2); (Write ('Press any key to continue. '); (read (keyboard, wk_char); (gotoxy (0, 0); (writeln (chr (29)); (end;  begin (gotoxy (0, 0); (wri,write (wk_string:2, ' '); (end; (writeln; (writeln; (write (' Octals: '); (for i := 0 to 4 do begin ,str (ord (v.octl [i]), wk_string); ,write (wk_string, ' '); (end; (writeln; (writeln; (write (' Bits: '); (for i := 0 to 15 d'); +end; ({endif} (unitclear (2); end;{test_x_to_y} begin; (init_menu; (repeat +menu (m_menu.m_choice); +case m_menu.m_choice of ,1: test_base_ten; + 2: test_blank1; + 3: test_hex4; + 4: test_inc; + 5: test_intstr; + 6: test_ioerror; + 7: test_lname; ,8: test_newlen; ,9: test_nibblex; +10: test_open; +11: test_translit; +12: test_upchr; +13: test_upstr; +14: test_up1; +15: test_variant; +16: test_xtoy; +otherwise; +end; (until (m_menu.m_choice = 0); (gotoxy (0, 0); (write. 14. UPPER1 Translate a string variable to mixed case. 15. VARIANT Eight different ways to look at a sixteen-bit word. 16. X_TO_Y Take a long integer X to its Yth (integer) power. the user a chance to correct any I/O errors. 11. TRANSLIT Transliterate specified characters in a string. 12. UPPERCHR Change a CHAR variable's alphabetic value to upper case. 13. UPPERSTR Change a string's alphabetic characters to upper cas, padding with blanks if the new length is longer than the old. 9. NIBBLEX Two-character hexadecimal representation of a CHAR field. 10. OPEN Open a file given an English title and default pathname. Give input/output error, given its error code. 7. LNAME Extract a "last name" from a name ordered by first-name, middle-name or initial, last-name, and suffix. 8. NEWLEN Change the length of a string variableing blanks from a string. 3. HEX4 Hexadecimal representation of an integer. 4. INC Increment an integer counter variable. 5. INTSTR Integer representation of a numeric string. 6. IOERROR The name of an  79C";"PRESS ANY KEY TO HALT LISTING"::202 1020#2,B$(I),16,B)ž#242:::1160Z=1#2;A$:"78A";A$Z=Z+1:Z>1842:::Z=1980*:=23:=0::"79C";"CONTINUE...?":1C$:C$<>"Y"C$<>"y"C$<>"N"C$<>"n"10 MENU.MAKER TEXT MODULESEG=0"MENU.MAKER"890&*X=11000: TEXT SLOW-DOWN LOOP ,X.1,180,22:2,280,21:2,2380,23:z:A$="LISTING "+B$(I),16,B)$=01:=0::"80C";A$;::12)>=23:=0::"PLUTIL - Pascal Utility Library by Bloom eln (chr (29)); end. {testutil} 30C$="N"C$="n"1160;:=23:=0::"79C";"PRESS ANY KEY TO HALT LISTING": $1020.202 8::Z=1B::=23:=0::"79C";"WOULD YOU LIKE A PRINTED COPY?":1C$:C$<>"Y"C$<>"y"C$<>"N"C$<>"n"1170*C$="N"C$="n"ibrary," product C3S0001. Those having that program product may agree that it is at once a bit more and a bit less than is needed for good software engineering in the Apple /// PASCAL environment. This disk presents an additional PASCAL utility library, on TABLE?: Bootable-Side Two PASCAL is a powerful programming language. Its ability to have library units that extend the language is an example of that power. Apple Computer, Inc. offers one such set of extensions under the name "Apple /// Pascal Utility L WAP /// SIG PUBLIC DOMAIN LIBRARY 12022 Parklawn Drive Rockville, MD. 20852 (301)-984-0300 PDS NAME: PLUTIL By Bloom DISK ID#: 3BLM-18 BOOo the main menu to exercise another module or to exit the program. PLUTIL October 31, 1984 Page 9 age 9 TESTUTIL program. The TESTUTIL menu has an entry for each of PLUTIL's modules. When you select a module, TESTUTIL displays several examples of use, then asks if you would like to try the module yourself. You may practice as often as you like, then return ttudying the modules of interest. Some of my text may have been fuzzy, but the computer-directing Pascal text shows exactly what is happening. To try out PLUTIL, you must first add the program's code file to your SYSTEM.LIBRARY. Next, execute the positive or negative bases. ENDIT is not a PLUTIL procedure, function, or data type. ENDIT is what I am doing with this documentation. The next move is yours. I recommend listing all 15 pages of the PLUTIL unit's text file and s Y causes the procedure to return a value of "1" if the exponent is less than "1," as is shown in "B" above. The integer result of such an exponentiation will always be either "0" or "1," so the author didn't mess with it. The procedure will handle either 16 } B: x := 4; y := -2; x to y (x, y, result); {Returns "result" as 1 } C: x := -5; y := 3; x to y (x, y, result); {Returns "result" as -125 } A "designed flaw" of X TOEAD PASCAL TEXT FILES."04=10:"78C";"ANY KEY RETURNS TO THE MENU."!>G$:::".D1/MENU.MAKER",320R",220(204::"79A";""; 2D=1:F=1 <#4;a$ FD=D+1 P#5;a$ZD=60#5;12)dD=60D=1nF=F+1::d$;::Y=1100:Y x13402  CATCH PASCAL TEXT FILES 202 :F*=08:"78C";"SORRY BUT MENU.MAKER CAN'T R".D1/MENU.MAKER",220 d$="" A$="PRINTING "+B$(I),16,B)=01:=0::"80C";A$;:#3,B$(I),16,B)Z=1#3;b$:"78A";b$Z=Z+1:Z=18:1290 1260 #4,B$(I),16,B)#5,".PRINTER"+ž#4#5;12):::".D1/MENU.MAKEe that extends PASCAL even more usefully. SIDE ONE: Documentation and Source Code Files SIDE TWO: The library unit, PLUTIL, consisting of: 1. BASE_TEN Integer representation of a hex string. 2. BLANK1 Strip multiple, leading, and trail