home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rexxbok.zip / rexx.INF (.txt)
OS/2 Help File  |  1995-09-28  |  80KB  |  2,608 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Introduction ΓòÉΓòÉΓòÉ
  3.  
  4.                    Learn REXX Programming in 56,479 Easy Steps
  5.  
  6. So you want to learn how to write a REXX program, but you haven't bothered ever 
  7. cracking open any kind of programming textbook?  What's the matter -- you've 
  8. finally gotten so bored with playing Doom that you're desperately searching for 
  9. something else to fruitlessly twiddle away all of your waking hours (and some 
  10. of your sleeping hours too, as many a REXX programmer has had frightening 
  11. nightmares upon starting a REXX programming project)?  Well then, reading this 
  12. book is your first step in that direction. 
  13.  
  14. This book is not intended to touch upon every aspect of REXX programming, but 
  15. rather, simply provide some of the most important concepts, and leave you to 
  16. pull out your own hair figuring out some esoteric technique you need in order 
  17. to complete your REXX script that analyzes your collection of smutty GIFs and 
  18. organizes them by breast size. 
  19.  
  20. This OS/2 Online Book was created by Jeff Glatt, who pilfered a great many 
  21. other sources, but is not afraid of being sued for doing it because he doesn't 
  22. own anything that some lawyer-weasel would want.  It is freely redistributable. 
  23. If you have suggestions, comments, criticisms, and anything else other than 
  24. dollar bills, then send them to someone else because you got it for free, and 
  25. you know what you get for nothing?  But, if you do need to contact the author, 
  26. then either phone some of the more prominent psychiatrict clinics in central 
  27. New York state, or try this: 
  28.  
  29. Jeff Glatt 
  30. 6 Sycamore Drive East 
  31. New Hartford, NY 13413 
  32. (315) 735-5350 
  33.  
  34. Example REXX code in this tutorial in displayed in colored text.  Cheap, 
  35. obnoxious attempts at humor are not highlighted in any particular way, so 
  36. you'll have to be prepared for the worst at all times. 
  37.  
  38.  
  39. ΓòÉΓòÉΓòÉ 2. REXX ΓòÉΓòÉΓòÉ
  40.  
  41. REXX is a computer programming language.  It's interpreted, like BASIC, which 
  42. means that you simply write your program as an ordinary text (ascii) file 
  43. containing instructions to tell the computer what to do, and some interpreter 
  44. software executes that text file directly, performing operations based upon 
  45. your instructions.  There's no need for you to compile and link your source 
  46. code into an executable program.  Your text file is your program.  So, REXX is 
  47. a script language.  But, it has lots of features, including variables, string 
  48. processing, looping, etc. 
  49.  
  50. Note:  From here on, a REXX program is referred to as a script, as opposed to 
  51.        binary executables which are referred to as programs.
  52.  
  53. The REXX interpreter is built into OS/2 (if you elected to install the REXX 
  54. features of OS/2).  That's why you can run a REXX script (ie, text file 
  55. containing REXX instructions) just by typing the name of the script from an 
  56. OS/2 Command Prompt (Window or Screen).  The OS/2 Command Prompt can detect 
  57. that you're telling it to run a REXX script, and will invoke the REXX 
  58. interpreter upon that script. 
  59.  
  60. A REXX script can run any executable (ie, a program written in another 
  61. language), including MS-DOS and Windows programs.  For example, a REXX script 
  62. can run OS/2's DISKCOPY.COM program, and even receive back an error code 
  63. telling whether DISKCOPY performed its operation successfully.  A REXX script 
  64. can also run another REXX script (which causes the interpreter to launch that 
  65. other script too). 
  66.  
  67. OS/2 executables (ie, programs written in other languages) may be written to 
  68. also run REXX scripts, as well as allow REXX scripts to control various 
  69. features of the program, perhaps allowing as much control as an enduser has by 
  70. manually using every aspect of the program's user interface.  The program must 
  71. be specifically written to have its own REXX Environment (or Interface), and 
  72. the REXX script (which controls the program) must "address" its REXX 
  73. instructions to that program's environment.  In fact, the ability of OS/2 
  74. applications to use REXX as a fancy, standardized script language is one of the 
  75. most useful features of REXX which distinguishes it from other languages which 
  76. have no such clearly defined "interface" between the interpreted script and 
  77. applications written in other languages. 
  78.  
  79.  
  80. ΓòÉΓòÉΓòÉ 3. Creating and running a REXX script ΓòÉΓòÉΓòÉ
  81.  
  82. Most programming books begin by showing you a program which displays the 
  83. message Hello world!  I find this approach to be a boring cliche with no 
  84. practical application.  So, here's how to write that script in REXX. 
  85. (Remember, you got this book for free, so just shut up and bear it). 
  86.  
  87.  1. Write a text file called hello.cmd containing the example text below (ie, 2 
  88.     lines).  Use any text editor (the OS/2 System Editor or Enhanced Editor 
  89.     will work) that saves plain (ascii) text without any special formatting 
  90.     characters like what some word processors embed in the file. 
  91.  
  92.     /* This script displays Hello world! */ 
  93.     SAY "Hello world!" 
  94.  
  95.  2. Save the text file to disk as hello.cmd. 
  96.  
  97.  3. Open an OS/2 Command Prompt Window or Screen, and at the prompt, type hello 
  98.     (ie, the name of the script), followed by the ENTER key.  (Make sure that 
  99.     you're in the same directory where the script was saved, or else type the 
  100.     script's full path name). 
  101.  
  102. The above script consists of a comment indicating what the script does, 
  103. followed by an instruction which does just what the comment indicates.  SAY is 
  104. the REXX instruction which sends data to the standard output (ie, defaults to 
  105. displaying that data upon the computer's monitor).  The data that SAY displays 
  106. is whatever has been listed after SAY.  In this example, that's the literal 
  107. string Hello world!.  We would refer to Hello world! as the argument for this 
  108. SAY instruction, since that's what this particular SAY instruction operates 
  109. upon.  We refer to SAY itself as a keyword, as that's the word which indicates 
  110. what the instruction does. 
  111.  
  112. When you run this script, you should see the message Hello world! appear upon 
  113. the screen. 
  114.  
  115. To run a REXX script under OS/2, you just type the script's name at a command 
  116. prompt.  Alternately, you can create a Desktop object for the script by 
  117. dragging a Program Object from the Templates folder, and typing the script's 
  118. full path name into its Setting's Program name field.  Then, you can run the 
  119. script by double-clicking upon its icon. 
  120.  
  121. Note:  OS/2 requires that a REXX script be named with a cmd extension on it, 
  122.        although you don't need to type the extension when you specify this 
  123.        script to be run.
  124.  
  125.  
  126. ΓòÉΓòÉΓòÉ 4. REXX Comment ΓòÉΓòÉΓòÉ
  127.  
  128. An OS/2 REXX script must always start with a comment.  A comment is simply a /* 
  129. followed by a space, and then */.  You can optionally put any desired text 
  130. inbetween the /* and */.  This opening comment must start at the very beginning 
  131. of the text file (ie, column 1 of line 1).  The opening comment is used by OS/2 
  132. to verify that this is indeed a REXX script, and not just some arbitrary text 
  133. file. 
  134.  
  135. A comment can span any number of lines, and have any amount of text inside of 
  136. it.  The OS/2 interpreter simply ignores everything inbetween the /* and */. 
  137. But, you can't have nested comments, so never put a /* or */ inside of another 
  138. comment, or REXX will undoubtably misinterpret part of the comment as if it 
  139. were REXX instructions, and post some sort of error message. 
  140.  
  141. Here's an example of a comment: 
  142.  
  143. /* The interpreter ignores this here text */ 
  144.  
  145.  
  146. ΓòÉΓòÉΓòÉ 5. Literal Strings (and Concatenation) ΓòÉΓòÉΓòÉ
  147.  
  148. A Literal String is any text enclosed within single or double quotation marks 
  149. (ie, ' or ").  It makes no difference whether you use single or double 
  150. quotation marks, as long as the opening quotation mark is the same as the 
  151. ending mark.  The interpreter uses all of the text enclosed within the 
  152. quotation marks exactly as you typed it (ie, upper and lower case, as well as 
  153. blank space, is preserved).  The interpreter doesn't ignore the text like with 
  154. a comment, but neither does the interpreter try to evaluate the text (ie, 
  155. replace it with some "value") like with a variable or mathematical expression. 
  156.  
  157. If you need to use an apostrophe (single quotation mark) or double quotation 
  158. mark within the text itself, use the other quotation mark around the whole 
  159. string.  For example, here we need to use an apostrophe within the word Here's, 
  160. so we use double quotes to enclose the entire string: 
  161.  
  162. "Here's a REXX Literal String." 
  163.  
  164. Here we need to use double quotation marks within the text, so we use single 
  165. quotes to enclose the entire string: 
  166.  
  167. 'He replied "I understand now" as he read this online book.' 
  168.  
  169. You also can use a pair of quotation marks (to represent one mark) when you 
  170. need to utilize the same quotation mark as was used to mark the entire string. 
  171. For example, here we use double quotes to mark the entire string, but we also 
  172. want to use double quotes within the string.  So, we need to use a pair of 
  173. double quotes within the string wherever we'd normally place only one. 
  174.  
  175. "He replied ""I understand now"" as he read this online book." 
  176.  
  177. Literal strings can be concatenated (ie, placed one after the next) with the 
  178. concatenation operator, || (ie, two | characters).  For example, here we place 
  179. the string Jeff after the string My name is.  Note that I leave an extra blank 
  180. space at the end of My name is literal string, so that there will be a blank 
  181. space between the the last word of the first string (ie, is) and the first word 
  182. of the second string (ie, Jeff) after they are combined. 
  183.  
  184. "My name is " || "Jeff" 
  185.  
  186. So if we use the above literal string as an argument for the SAY instruction, 
  187. as so: 
  188.  
  189. SAY "My name is " || "Jeff" 
  190.  
  191. ...then My name is Jeff is displayed upon the screen. 
  192.  
  193. It's also possible to concatenate strings by merely leaving a space inbetween 
  194. each string.  For example: 
  195.  
  196. SAY "My name is" "Jeff" 
  197.  
  198. ...will achieve the same result as using the concatenation operator above.  The 
  199. space inbetween the two strings is retained by the interpreter.  So, the end 
  200. result is that when you append strings by leaving a blank space inbetween them, 
  201. you always end up with a combined string that has that extra blank space there. 
  202. (But, even if you put more than one space character inbetween the strings, the 
  203. interpreter will retain only 1 space character).  On the other hand, the 
  204. concatenation operator allows you to combine two strings without that extra 
  205. blank space inbetween them.  If you wanted to append the string .exe to the 
  206. string program without any blank space inbetween the two strings, then you'd 
  207. need to use the concatenation operator as so: 
  208.  
  209. "program" || ".exe" 
  210.  
  211. Of course, you're wondering, "Why not just specify one literal string 
  212. consisting of 'program.exe'"?  Well, as you'll see in the discussion of 
  213. variables, when you wish to combine the value of a variable and a literal 
  214. string (or the values of two variables) into a single string without spaces 
  215. inbetween the two pieces, then the concatenation operator is essential. 
  216.  
  217. Note:  When using the concatenation operator, you can eliminate all blank space 
  218.        inbetween the strings.  For example, the following two instructions are 
  219.        really the same thing: 
  220.  
  221. SAY "program" || ".exe" 
  222. SAY "program"||".exe" 
  223.  
  224. But, the first one is easier for a human to read.
  225.  
  226.  
  227. ΓòÉΓòÉΓòÉ 6. Variables (and assigning them values) ΓòÉΓòÉΓòÉ
  228.  
  229. A variable is a place to store some data.  You can change the data assigned to 
  230. a variable (ie, change its value).  Variables are therefore very useful for 
  231. keeping track of data that changes during the script's execution. 
  232.  
  233. Each variable must have a unique name, and you access its value by using that 
  234. name.  When you choose a name for a variable, the first character must be one 
  235. of the letters A through Z, a !, a ?, or a _.  The remaining characters of the 
  236. variable's name can be any of the preceding characters as well as 0 to 9 and 
  237. the characters @, #, and $.  The case of letters is unimportant, so that for 
  238. example, Hello, HELLO, and hellO all are the same variable name. 
  239.  
  240. Note:  You can't name a variable the same as any REXX keyword, REXX function 
  241.        name, or subroutine in your script.  Otherwise, the interpreter will 
  242.        misinterpret the variable name as that preceding item.  Also, don't use 
  243.        the names RESULT, RC, or SIGL as these are special variables maintained 
  244.        by the interpreter for your script's use.
  245.  
  246. You can assign a value to a variable simply by writing a REXX instruction that 
  247. consists of the variable name, followed by an equal sign, and then the desired 
  248. value for the variable.  We call this an assignment instruction.  Here we have 
  249. a variable named My_Variable.  We will set it to the value of 5. 
  250.  
  251. My_Variable = 5 
  252.  
  253. Every time that the interpreter encounters what it regards to be a variable 
  254. name in some instruction, the interpreter replaces the variable name with its 
  255. value when carrying out that instruction (except for a variable whose value is 
  256. being set in an assignment instruction).  For example, if you subsequently use 
  257. the above variable name as an argument for the SAY instruction, the interpreter 
  258. will substitute its value. 
  259.  
  260. SAY My_Variable 
  261.  
  262. The above would print out 5 upon the screen.  It would not print out 
  263. My_Variable.  Since My_Variable is not a literal string enclosed in quotes (nor 
  264. a keyword, nor a label, nor a function, nor anything else that the interpreter 
  265. recognizes), then the interpreter regards it as a variable name.  Therefore, 
  266. the interpreter substitutes the value of My_Variable as the real argument here. 
  267. We already told the interpreter that My_Variable's value is 5 with the 
  268. preceding assignment instruction. 
  269.  
  270. A variable can be assigned a value consisting of some literal string.  For 
  271. example, here we set My_Variable to the string This is some text. 
  272.  
  273. My_Variable = 'This is some text' 
  274.  
  275. Now if you subsequently use this variable name as an argument for the SAY 
  276. instruction, the interpreter will substitute its new value.  For example: 
  277.  
  278. SAY My_Variable 
  279.  
  280. ...will print out This is some text upon the screen.  It would not print out 
  281. My_Variable (since My_Variable is not a literal string enclosed in quotes), but 
  282. instead, print the value of My_Variable which happens to be the string This is 
  283. some text. 
  284.  
  285. When assigning a value to a variable, that value can be any mathematical 
  286. expression.  For example: 
  287.  
  288. My_Variable = 5 + 3 
  289.  
  290. ...sets the value of My_Variable to 8 (ie, the addition of 5 and 3).  Since 
  291. quotes weren't placed around 5 + 3, it's not a literal string and the 
  292. interpreter therefore evaluates the mathematical expression 5 + 3 rather than 
  293. literally accepting it as you typed it.  Of course, if you did really want to 
  294. set My_Variable to the string 5 + 3, you'd specify a literal string by 
  295. enclosing in quotes, as so: 
  296.  
  297. My_Variable = '5 + 3' 
  298.  
  299. Furthermore, a variable's value can be set to a concatenation of strings, as 
  300. so: 
  301.  
  302. My_Variable = "My name is " || "Jeff" 
  303.  
  304. If you subsequently use My_Variable above as an argument for the SAY 
  305. instruction, SAY will print the combined string of My name is Jeff, which is 
  306. the current value of My_Variable. 
  307.  
  308. You can set a variable to the value of another variable, as so: 
  309.  
  310. My_Variable = 5 
  311. My_Other_Variable = My_Variable 
  312.  
  313. Above, both variables have the value of 5. 
  314.  
  315. You can set a variable to the value of a mathematical expression where another 
  316. variable is used in the expression, as so: 
  317.  
  318. My_Variable = 5 
  319. My_Other_Variable = My_Variable + 3 
  320.  
  321. Above, My_Other_Variable has the value of 8. 
  322.  
  323. Note:  You can assign a variable a new value by also using its old value in an 
  324.        expression.  For example, here's how to increment a variable by 1. 
  325.  
  326. My_Variable = My_Variable + 1 
  327.  
  328. The value of My_Variable on the right side of the equal sign is the value 
  329. before 1 is added to it, and this new value is now assigned back to My_Variable.
  330.  
  331. You can even set a variable's value to a string that is the combination of 
  332. several literal strings and mathematical expressions. 
  333.  
  334. My_Variable = 5 
  335. My_Answer = "The answer to" My_Variable "+ 3 is" My_Variable + 3 
  336.  
  337. The above results in My_Answer's value being set to the string The answer to 5 
  338. + 3 is 8.  First of all, The answer to is a literal string, so that is retained 
  339. verbatim.  Next, the interpreter regards My_Variable as a variable name (ie, it 
  340. isn't enclosed in quotes, nor is it a keyword, label, function name, etc.), so 
  341. the interpreter substitutes its value there, which is simply 5.  Note that 
  342. because a space was left inbetween the literal string The answer to and 
  343. My_Variable, this space is retained in My_Answer's value.  Next, + 3 is is 
  344. another literal string.  Finally, the interpreter sees another variable name, 
  345. and notes that 3 is being added to it.  Since this is not enclosed within 
  346. quotes (ie, is not a literal string), the interpreter deems this to be a 
  347. mathematical expression, substitutes the variable's value, and evaluates this 
  348. mathematical expression to 8.  Again, leaving a space inbetween + 3 is and that 
  349. mathematical expression results in the space being retained in My_Answer's 
  350. value. 
  351.  
  352. We could have used the concatenation operator to combine the above pieces as 
  353. so: 
  354.  
  355. My_Variable = 5 
  356. My_Answer = "The answer to " || My_Variable || " + 3 is " || My_Variable + 3 
  357.  
  358. Note that I added extra spaces to those literal strings because the 
  359. concatenation operator appends the pieces together without otherwise retaining 
  360. spaces inbetween.  If you run into a situation where you don't want a space 
  361. inbetween a variable's value and a literal string, then you must use the 
  362. concatenation operator.  For example, assume that the variable My_Program is 
  363. already set to a string describing the name of some executable, and you wish to 
  364. append the literal string .exe to it without a space inbetween, and assign this 
  365. final string to the variable Full_Name: 
  366.  
  367. Full_Name = My_Program || ".cmd" 
  368.  
  369. Furthermore, if you wish to combine the values of two variables without a space 
  370. in between, then you must use the concatenation operator. 
  371.  
  372. Full_Name = My_Program || My_Extension 
  373.  
  374. You can even concatenate variables whose values are numeric, as if they were 
  375. strings. 
  376.  
  377. My_Variable = 1 
  378. My_Fraction = '.5' 
  379. My_Result = My_Variable||My_Fraction 
  380. SAY My_Result /* Prints 1.5 */ 
  381.  
  382. If you use a variable in an expression, but that variable has not been 
  383. previously given a value, this does not cause an error (unless "SIGNAL ON 
  384. NOVALUE" is set, explained later).  Instead, the interpreter just uses the 
  385. variable's own name (translated into upper case) as its value. 
  386.  
  387. /* The variable My_Variable has not yet been assigned a value */ 
  388. SAY My_Variable 
  389.  
  390. The above results in the string MY_VARIABLE being displayed. 
  391.  
  392. As you can see, variables can be assigned values that are numeric or strings. 
  393. So, how does the interpreter know whether a variable represents a string or 
  394. numeric value?  The interpreter automatically evaluates the value of a variable 
  395. each time that it is used in an instruction to determine whether it's numeric 
  396. or a string.  For example, if you assign the value 506 to a variable, the 
  397. interpreter figures out that it's a numeric value whenever you use the 
  398. variable.  If you assign Hello to that same variable, the interpreter figures 
  399. out that it's a string value whenever you use the variable.  You can change a 
  400. variable's value from numeric to string while the script executes, and the 
  401. interpreter will follow along.  This is why REXX variables are described as 
  402. untyped -- because you can change their values from numeric to string and back 
  403. "on the fly".  But if a variable's value happens to be a string, then you can't 
  404. use the variable in a mathematical expression (which we'll cover later).  For 
  405. example, you can't multiple the value of the variable with some other numeric 
  406. value.  Math operators only work upon a variable when its value is numeric (ie, 
  407. its value consists only of the characters 0 through 9 -- numeric digits). 
  408.  
  409. Note:  Some REXX documentation refers to variables as "symbols".
  410.  
  411.  
  412. ΓòÉΓòÉΓòÉ 7. Getting input ΓòÉΓòÉΓòÉ
  413.  
  414. The PULL instruction can be used to get input from the person running the 
  415. script, and store that input data in a variable.  You supply the name of the 
  416. variable where you want the data stored after the PULL keyword. 
  417.  
  418. The script stops executing at that point and waits for the user to type in some 
  419. text (within the OS/2 command prompt window).  When the user presses the ENTER 
  420. key, that line of text is stored in the desired variable, and the script 
  421. resumes executing after the PULL instruction.  (PULL therefore retrieves only 
  422. one line of text at a time). 
  423.  
  424. Here we get some input from the user, store it in the variable named 
  425. My_Variable, and then echo whatever the user typed back to the screen. 
  426.  
  427. PULL My_Variable 
  428. SAY My_Variable 
  429.  
  430. If you wish to display a message to the user telling him what to do, you'll use 
  431. a SAY instruction (or other instruction that prints to the screen) to print 
  432. that message before the PULL instruction.  Here we tell the user to type in his 
  433. name. 
  434.  
  435. /* This script asks the user to type his name, and echoes it */ 
  436. SAY "Enter your name" 
  437. PULL My_Variable 
  438. SAY My_Variable 
  439.  
  440. When running the above script, you'll note that the PULL instruction converts 
  441. all letters to upper case.  If you wish to retain the case as typed by the 
  442. user, use PARSE PULL instead. 
  443.  
  444. PARSE PULL My_Variable 
  445.  
  446. For more information about PARSE PULL, see Parsing. 
  447.  
  448.  
  449. ΓòÉΓòÉΓòÉ 8. Math Operations ΓòÉΓòÉΓòÉ
  450.  
  451. With mathematical expressions, you can use whole numbers and decimal fractions. 
  452. A whole number is one which does not contain a decimal part.  A whole number 
  453. can be positive, negative, or zero.  Examples of whole numbers are 3, 569, -30, 
  454. 0.  A decimal fraction is a number containing a decimal point.  Examples of 
  455. decimal fractions are 1.45, 0.6, -40.03333. 
  456.  
  457. REXX has numerous math operators.  There are operators to perform addition, 
  458. subtraction, multiplication, division, raise to a power, etc. 
  459.  
  460. When the interpreter encounters some instruction containing a mathematical 
  461. expression not enclosed within quotes (ie, isn't a literal string), then the 
  462. interpreter evaluates that expression to its resulting value and substitutes 
  463. that value when carrying out the instruction.  In other words, if the 
  464. interpreter sees the following instruction: 
  465.  
  466. SAY 5 + 3 
  467.  
  468. ...it doesn't print 5 + 3, but rather, evaluates this expression as 8, and 
  469. subsequently prints out 8. 
  470.  
  471. Addition 
  472.  
  473. The operator for addition is the plus sign +.  Here's an example of adding the 
  474. two numbers 2 and 14: 
  475.  
  476. 2 + 14 
  477.  
  478. The interpreter evaluates the above to be 16. 
  479.  
  480. Subtraction 
  481.  
  482. The operator for subtraction is the minus sign -.  Here's an example of 
  483. subtracting 8 from 230: 
  484.  
  485. 230 - 8 
  486.  
  487. The interpreter evaluates the above to be 222. 
  488.  
  489. Multiplication 
  490.  
  491. The operator for multiplication is the asterisk *.  Here's an example of 
  492. multiplying two numbers, 2 times 6: 
  493.  
  494. 2 * 6 
  495.  
  496. The interpreter evaluates the above to be 11.999998.  You suddenly realize that 
  497. you have a buggy Intel Pentium chip.  After replacing it, the interpreter 
  498. evaluates the above correctly as 12. 
  499.  
  500. Division 
  501.  
  502. For division, there are several operators you can use, depending upon what kind 
  503. of answer you want.  For a simple division, the operator is a single slash /. 
  504. Here's an example of dividing 7 by 2: 
  505.  
  506. 7 / 2 
  507.  
  508. The interpreter evaluates the above to be 3.5 (ie, 3 and a half).  In other 
  509. words, 2 goes into 7 three times and there's a remainder of one half of 2, or 
  510. 1. 
  511.  
  512. To divide for the purpose of getting only the remainder, the operator is two 
  513. slashes //.  Here's an example of dividing 7 by 2, in order to get the 
  514. remainder: 
  515.  
  516. 7 // 2 
  517.  
  518. The interpreter evaluates the above to be 1 (ie, after 2 goes into 7 three 
  519. times, there is a remainder of 1). 
  520.  
  521. To divide, and return only the whole number portion of an answer and no 
  522. remainder, the operator is the percent sign %. 
  523.  
  524. 7 % 2 
  525.  
  526. The interpreter evaluates the above to be 3 (ie, the decimal portion of the 
  527. answer is discarded, so the answer is rounded down to a whole number). 
  528.  
  529. Note:  To get the reciprocal of a number, divide it into 1 (ie, the reciprocal 
  530.        of 20 is 1 / 20).
  531.  
  532. To raise a number to a power, the operator is two asterisks **.  Here's an 
  533. example of raising 3 to the second power (ie, 3 squared): 
  534.  
  535. 3 ** 2 
  536.  
  537. The interpreter evaluates the above to be 9. 
  538.  
  539. Note:  You don't need to place blank space inbetween numbers and operators. 
  540.        For example, the following 2 expressions are the same. 
  541.  
  542. 2 + 55 
  543. 2+55
  544.  
  545. Variables can be used in any mathematical expression.  The interpreter simply 
  546. substitutes the variable's value, and then performs the math.  The variable's 
  547. value must be numeric (as opposed to being comprised of characters other than 
  548. the digits 0 through 9) or the interpreter will report a "Bad arithmetic 
  549. conversion" error, or some such math related error. 
  550.  
  551. For example, here we multiply two variables and then add 6. 
  552.  
  553. My_Variable * My_Other_Variable + 6 
  554.  
  555.  
  556. ΓòÉΓòÉΓòÉ 8.1. Precedence ΓòÉΓòÉΓòÉ
  557.  
  558. Mathematical expressions are normally evaluated from left to right.  Suppose 
  559. you had this expression: 
  560.  
  561. 9 - 5 + 2 
  562.  
  563. The 9 - 5 would be evaluated first.  The answer, 4, would be added to 2 for a 
  564. final value of 6. 
  565.  
  566. Some math operations are given priority over others.  In general, the rules of 
  567. algebra apply to mathematical expressions.  In the following expression, the 
  568. division is handled before the addition.  So 8 is divided by 2 first, and then 
  569. the result is added to 10, for a final value of 14. 
  570.  
  571. 10 + 8 / 2 
  572.  
  573. If you use parentheses in an expression, the interpreter evaluates what is in 
  574. the parentheses first.  For example, here we put parentheses around the 
  575. addition operation within this same expression.  Therefore, 10 is added to 8 
  576. first, and then the result is divided by 2, for a final value of 9. 
  577.  
  578. (10 + 8) / 2 
  579.  
  580. Here is the order of precedence for math operations (ie, which math operations 
  581. get carried out first if you don't use parentheses to force a different order). 
  582.  
  583. Raise to a power (the highest precedence) 
  584. Multiplication and Division 
  585. Addition and Subtraction (both the lowest precedence) 
  586.  
  587. If in doubt about the order that operations are calculated within an 
  588. expression, then use parentheses to force your desired precedence.  You can use 
  589. as many sets of parentheses as you want, and it's OK to use them even in 
  590. expressions where they're not really necessary.  (But remember that REXX is an 
  591. interpreted language, so try not to do things that aren't necessary). 
  592.  
  593.  
  594. ΓòÉΓòÉΓòÉ 8.2. Math Example ΓòÉΓòÉΓòÉ
  595.  
  596. Here is an example of a script which does math.  Make a file called arith.cmd 
  597. containing the following text. 
  598.  
  599. /* This script inputs a number and does some calculations with it */ 
  600.  
  601. /* Get the original number from the user and put it into the variable named "a" 
  602. */ 
  603. SAY 'Enter a number' 
  604. PULL a 
  605. /* Calculate the square, and put it into a variable named "b". We could also 
  606. have done a**2 */ 
  607. b=a*a 
  608. /* Calculate the reciprocal, and put it into a variable named "c" */ 
  609. c=1/a 
  610. /* Calculate 3 + original number, and put it into a variable named "d" */ 
  611. d=3+a 
  612. /* Calculate two to the power of one less than the number, and put it into a 
  613. variable named "e" */ 
  614. e=2**(a-1) 
  615. /* Display those variables' values */ 
  616. SAY 'Results are:' a b c d e 
  617.  
  618. Run this REXX script.  It will wait for you to type in a positive integer.  Do 
  619. that, and then press ENTER.  Here is a sample run: 
  620.  
  621. Type a number > 
  622. Results are: 5 25 0.2 8 16 
  623.  
  624. The results you see are the original number typed by the user (5), its square 
  625. (25), its reciprocal (0.2), the number plus three (8), and two to the power of 
  626. one less than the number (16). 
  627.  
  628. If you supply the number 6 as input to the script, you should notice that the 
  629. value of 1/6 is given to nine significant figures.  You can easily change this. 
  630. Edit the script and insert the following after the opening comment: 
  631.  
  632. NUMERIC DIGITS 25 
  633.  
  634. This tells the interpreter that you wish any mathematical expressions to be 
  635. calculated out to 25 significant digits.  You can substitute 25 for however 
  636. many significant digits you desire.  In this way, you can calculate numbers to 
  637. whatever accuracy you require, within the limits of the computer. 
  638.  
  639.  
  640. ΓòÉΓòÉΓòÉ 9. Formatting Instructions ΓòÉΓòÉΓòÉ
  641.  
  642. REXX is rather flexible with formatting instructions. 
  643.  
  644. Instructions do not have to begin in a particular column.  You can use as much 
  645. or as little indentation as desired. 
  646.  
  647. Instructions can be typed in uppercase, lowercase, or a combination of both. 
  648. The interpreter always "sees" everything as uppercase anyway when it analyzes 
  649. your instructions, except for anything that you've enclosed in quotes (ie, 
  650. literal string). 
  651.  
  652. The interpreter is rather liberal with blank space.  You can separate the parts 
  653. of an instruction by as many or few blank spaces as desired.  The interpreter 
  654. always regards several, adjacent space characters as just one space anyway, 
  655. except when those spaces are found within a literal string.  When it sees a 
  656. concatenation operator, the interpreter ignores all blank spaces around that 
  657. operator, and sees the two adjacent pieces of the instruction as being directly 
  658. adjacent to each other. 
  659.  
  660. The interpreter ignores blank lines. 
  661.  
  662. Usually, a single REXX instruction is placed upon one line.  But, you can put 
  663. more than one instruction upon a line.  You simply place a semicolon between 
  664. the instructions.  For example, here we put 3 instructions upon the same line: 
  665.  
  666. /* This script inputs your name and prints it out */ 
  667. SAY 'Type your name'; PARSE PULL name; SAY 'Your name is' name 
  668.  
  669. If you want an instruction to span more than one line, you must put a comma (,) 
  670. at the end of the line to indicate that the instruction continues upon the next 
  671. line.  But you can't split a literal string across more than one line.  (You'd 
  672. have to split the string into 2 separate strings joined by a concatenation 
  673. operator followed by a comma). 
  674.  
  675. The instructions in a REXX script are executed in the order that they appear in 
  676. the text file.  (ie, The first instruction, at the top of the file, is executed 
  677. first.  Then, the next instruction below it is executed.  Etc).  Instructions 
  678. do not have to be numbered or otherwise labeled (but they can be labeled for 
  679. the purposes of jumping from one instruction to another via the SIGNAL 
  680. keyword). 
  681.  
  682.  
  683. ΓòÉΓòÉΓòÉ 10. Conditionals (ie, Making a Decision or Comparisons) ΓòÉΓòÉΓòÉ
  684.  
  685. You use a Conditional instruction whenever you want to check if a certain 
  686. condition is true, and then execute other REXX instructions depending upon 
  687. whether that condition is true. 
  688.  
  689. A Conditional instruction consists of a REXX conditional keyword, followed by 
  690. an expression, and then the rest of the conditional (which is usually another 
  691. instruction -- a "sub-instruction" if you will).  The expression must evaluate 
  692. to either true (ie, 1) or false (0).  REXX automatically evaluates the 
  693. expression following any conditional keyword, and if the expression is true, 
  694. then the rest of the conditional is executed.  Otherwise, the rest of the 
  695. conditional is skipped. 
  696.  
  697. An expression often consists of a comparison of two items.  Those items may be 
  698. variables or literal strings or even the returned value of some REXX function 
  699. or subroutine.  For example, the following script checks if the value of a 
  700. variable named My_Variable is greater than 10, and if so, then the literal 
  701. string It's greater than 10 is printed to the screen. 
  702.  
  703. /* Check if My_Variable is greater than 10, and then say so if true */ 
  704. IF My_Variable > 10 THEN SAY "It's greater than 10." 
  705.  
  706. The above instruction uses two REXX conditional keywords which work together; 
  707. IF and THEN.  IF is placed immediately before the expression (which in this 
  708. case is the comparison of My_Variable to 10).  THEN is placed before the 
  709. sub-instruction that you want executed (which in this case is the SAY 
  710. instruction) if the expression is true. 
  711.  
  712. You'll note that I use the comparison operator > to represent "is greater 
  713. than".  There are several operators that you can use when comparing two items, 
  714. as so: 
  715.  
  716. =  "equal to" 
  717. <  "less than" 
  718. >  "greater than" 
  719. <=  "less than or equal to" 
  720. >=  "greater than or equal to" 
  721. <>  "greater than or less than" 
  722. \=  "not equal to" 
  723. \>  "not greater than" 
  724. \<  "not less than" 
  725.  
  726. For example, let's say that I want to check if My_Variable is not equal to 10, 
  727. and SAY "Not equal to 10" if that's true. 
  728.  
  729. /* Check if My_Variable is not equal to 10, and then say so if true */ 
  730. IF My_Variable \= 10 THEN SAY "Not equal to 10." 
  731.  
  732. Here I check whether the value of the variable named My_Variable is greater 
  733. than 5 plus the value of the variable named My_Other_Variable.  If true, then I 
  734. set My_Variable to 10 (ie, I perform an assignment instruction). 
  735.  
  736. /* If My_Variable is greater than My_Other_Variable + 5, then set My_Variable 
  737. to 10 */ 
  738. IF My_Variable > My_Other_Variable + 5 THEN My_Variable = 10 
  739.  
  740. REXX compares strings (including variables that have string values rather than 
  741. numeric values) on a character by character basis.  Consider the following: 
  742.  
  743. /* If My_Variable is greater than "hello", then say "It's true" */ 
  744. My_Variable = "hell" 
  745. IF My_Variable >= "hello" THEN SAY "It's true." 
  746.  
  747. First, REXX compares the first character of the literal string "hello" with the 
  748. first character of the value of My_Variable.  Both characters are the letter 
  749. "h", so the expression is true so far (ie, My_Variable is greater than or equal 
  750. to "hello").  Next, the second characters of both strings are compared.  These 
  751. are both "e".  The expression is still true.  By the time that REXX gets around 
  752. to comparing the "o" in "hello", it has run out of characters in the value of 
  753. My_Variable, so it substitutes a blank space as the next character.  Therefore, 
  754. My_Variable is "less than" the literal string "hello" (ie, a blank space is 
  755. considered to be less than the letter "o"), and the expression is ultimately 
  756. false.  The SAY instruction is not executed. 
  757.  
  758. Let's look at another variation of the above. 
  759.  
  760. /* If My_Variable is greater than "help", then say "It's true" */ 
  761. My_Variable = "hell" 
  762. IF My_Variable >= "help" THEN SAY "It's true." 
  763.  
  764. Again, REXX compares the strings on a character by character basis.  The 
  765. expression is true until REXX compares the "p" in "help" to the second "l" in 
  766. "hell".  It finds that "p" is greater than "l" (ie, "p" is the 16th letter in 
  767. the alphabet whereas "l" is only the 12th letter), and therefore My_Variable is 
  768. "less than" the literal string "help". 
  769.  
  770. Upper case letters are considered to be less than lower case letters (ie, "A" 
  771. is less than "a"), and numeric digits are less than letters (ie, "3" is less 
  772. than "A").  A blank space is less than letters or numeric characters. 
  773.  
  774. In conclusion, the expression in a Conditional instruction can involve 
  775. variables, literal strings, and/or returned values from functions or 
  776. subroutines, but ultimately, REXX will evaluate the expression to be true (or 
  777. false), and execute (or skip) the remainder of the Conditional accordingly. 
  778.  
  779.  
  780. ΓòÉΓòÉΓòÉ 10.1. ELSE keyword ΓòÉΓòÉΓòÉ
  781.  
  782. Besides IF/THEN, there are other REXX keywords used in Conditional 
  783. instructions. 
  784.  
  785. ELSE is used in conjunction with IF/THEN.  After an IF/THEN, you can use an 
  786. ELSE Conditional instruction.  What happens is that, if the expression in the 
  787. IF/THEN instruction is not true (and therefore the remainder of the IF/THEN is 
  788. not executed), then REXX will execute the ELSE instruction instead.  On the 
  789. other hand, if the IF/THEN expression is true (and the remainder of the IF/THEN 
  790. is executed), then REXX will skip any following ELSE instruction.  In other 
  791. words, an ELSE instruction is only executed when the IF/THEN expression is 
  792. false. 
  793.  
  794. /* If My_Variable equals "hello", then say "It's true". Otherwise, say "It's 
  795. not true". */ 
  796. My_Variable = "hello" 
  797. IF My_Variable = "hello" THEN SAY "It's true." 
  798. ELSE SAY "It's not true." 
  799.  
  800. Above, the expression in the IF/THEN is true (ie, My_Variable's value happens 
  801. to be equal to the literal string "hello"), so the SAY instruction after THEN 
  802. is executed (ie, "It's true" is printed to the screen).  The following ELSE 
  803. instruction is skipped. 
  804.  
  805. /* If My_Variable is greater than 10, then say "It's true". Otherwise, say 
  806. "It's not true". */ 
  807. My_Variable = 5 + 2 
  808. IF My_Variable > 10 THEN SAY "It's true." 
  809. ELSE SAY "It's not true." 
  810.  
  811. Above, the expression in the IF/THEN is false (ie, My_Variable's value is not 
  812. greater than 10), so the SAY instruction after THEN is skipped.  The following 
  813. ELSE instrcution is therefore executed (ie, "It's not true" is printed to the 
  814. screen). 
  815.  
  816. Another IF/THEN Conditional instruction could follow an ELSE keyword.  You 
  817. could then follow this with yet another ELSE instruction. 
  818.  
  819. IF My_Variable > 10 THEN SAY "It's greater than 10." 
  820. ELSE IF My_Variable = 10 THEN SAY "It's 10." 
  821. ELSE SAY "It's less than 10." 
  822.  
  823. In the above, only one of the SAY instructions is ever executed for any given 
  824. value of My_Variable. 
  825.  
  826.  
  827. ΓòÉΓòÉΓòÉ 10.2. SELECT keyword ΓòÉΓòÉΓòÉ
  828.  
  829. The SELECT keyword is used when you want to select one of several possible 
  830. Conditional instructions to execute (and skip all other conditional 
  831. instructions within the group).  The keywords WHEN and THEN are used for each 
  832. Conditional instruction much the same way that IF/THEN is used to form a 
  833. Conditional.  In other words, the WHEN goes before the expression to be tested, 
  834. and the THEN goes before the instruction to be executed if the expression is 
  835. true.  The SELECT keyword gets placed before all of the Conditional 
  836. instructions in the group.  An END keyword is placed after the last Conditional 
  837. instruction (ie, it marks the end of the SELECT group). 
  838.  
  839. SELECT is very useful if you wish to check some variable for a large number of 
  840. conditions, and execute instructions for only one of those conditions. 
  841. Consider the following: 
  842.  
  843. /* Check My_Variable for a variety of conditions, but execute instructions for 
  844. only 1 condition. */ 
  845. SAY "Enter a number" 
  846. PULL My_Variable 
  847. SELECT 
  848.   WHEN My_Variable = 10 THEN SAY "It's equal to 10." 
  849.   WHEN My_Variable < 10 THEN SAY "It's less than 10." 
  850.   WHEN My_Variable < 20 THEN SAY "It's less than 20." 
  851. END 
  852.  
  853. Assume that My_Variable's value is 5.  REXX checks the first WHEN's expression 
  854. (ie, Is My_Variable equal to 10?).  This is false, so the remainder of that 
  855. WHEN Conditional instruction is skipped (ie, It's equal to 10 is not printed to 
  856. the screen).  Because the first Conditional was false, REXX proceeds to the 
  857. next Conditional.  It checks if the second WHEN's expression is true (ie, Is 
  858. My_Variable < 10?).  This is true.  Therefore, REXX executes the instruction 
  859. after that WHEN's respective THEN (ie, It's less than 10 is printed to the 
  860. screen).  REXX then immediately jumps to END.  It skips the remaining 
  861. conditional instructions (ie, the third WHEN's expression is never even tested, 
  862. and therefore It's less than 20 is not printed to the screen). 
  863.  
  864. Assume that My_Variable's value is 10.  REXX checks the first WHEN conditional 
  865. expression (ie, Is My_Variable equal to 10?).  This is true.  Therefore, REXX 
  866. executes the instruction after that WHEN's respective THEN (ie, It's equal to 
  867. 10 is printed to the screen).  REXX then immediately jumps to END.  It skips 
  868. the remaining conditional instructions (ie, the second and third WHEN's 
  869. expressions are never even tested). 
  870.  
  871. Assume that My_Variable's value is 25.  REXX checks the first WHEN conditional 
  872. expression (ie, Is My_Variable equal to 10?).  This is false, so the remainder 
  873. of that WHEN conditional is skipped (ie, It's equal to 10 is not printed to the 
  874. screen).  Because the first conditional was false, REXX proceeds to the next 
  875. conditional.  It checks if the second WHEN's expression is true (ie, Is 
  876. My_Variable < 10?).  This is also false.  Therefore, REXX skips the respective 
  877. THEN for that WHEN.  Because the second conditional was false, REXX proceeds to 
  878. the next conditional.  It checks if the third WHEN's expression is true (ie, Is 
  879. My_Variable < 20?).  This is also false.  There are no more conditional 
  880. instructions.  At this point, REXX will terminate the script with a syntax 
  881. error message.  You must always make sure that every time a SELECT group is 
  882. executed, one of its conditionals turns out to be true, otherwise REXX will 
  883. generate a syntax error message.  If you don't want REXX to generate a syntax 
  884. error message for any instances where all of the conditionals turn out to be 
  885. false, you can use the OTHERWISE keyword after the last conditional (ie, before 
  886. the END keyword), and optionally follow it with some REXX instructions.  This 
  887. OTHERWISE and its associated instructions are executed only when all of the 
  888. conditionals in the SELECT turn out to be false. 
  889.  
  890. /* Check My_Variable for a variety of conditions, but execute instructions for 
  891. only 1 condition. */ 
  892. SAY "Enter a number" 
  893. PULL My_Variable 
  894. SELECT 
  895.   WHEN My_Variable = 10 THEN SAY "It's equal to 10." 
  896.   WHEN My_Variable < 10 THEN SAY "It's less than 10." 
  897.   WHEN My_Variable < 20 THEN SAY "It's less than 20." 
  898.   OTHERWISE 
  899.     SAY "It must be > 19." 
  900. END 
  901.  
  902. Now when My_Variable is 25, the above OTHERWISE gets executed (ie, the SAY 
  903. instruction printing It must be 19 is executed).  By contrast, when using 
  904. IF/THEN with ELSE keywords, it's OK if the IF/THEN as well as all of its 
  905. subsequent ELSE instructions turn out to be false. 
  906.  
  907.  
  908. ΓòÉΓòÉΓòÉ 10.3. Multiple instructions within a conditional (ie, DO/END) ΓòÉΓòÉΓòÉ
  909.  
  910. Only one instruction may be placed after a THEN, ELSE, or WHEN keyword, but 
  911. REXX provides a way of bracketing instructions together so that they can be 
  912. treated as a single instruction.  To do this, place the keyword DO before the 
  913. group of instructions, and the keyword END after the instructions. 
  914.  
  915. /* If My_Variable is greater than 10, then say "It's true" and set it to 10. 
  916. Otherwise, say "It's not true" and print My_Variable's value. */ 
  917. My_Variable = 5 + 2 
  918. IF My_Variable > 10 THEN DO 
  919.   SAY "It's true." 
  920.   My_Variable = 10 
  921. END 
  922. ELSE DO 
  923.   SAY "It's not true." 
  924.   SAY 'My_Variable =' My_Variable 
  925. END 
  926.  
  927. Here's an example of using DO/END to enclose multiple instructions inside one 
  928. of the WHEN conditionals in a SELECT group.  Note the DO/END in the second WHEN 
  929. instruction. 
  930.  
  931. /* Check My_Variable for a variety of conditions, but execute instructions for 
  932. only 1 condition. */ 
  933. SELECT 
  934.   WHEN My_Variable = 10 THEN SAY "It's equal to 10." 
  935.   WHEN My_Variable < 10 THEN DO 
  936.     SAY "It's less than 10." 
  937.     My_Variable = My_Variable + 1  /* Increment it */ 
  938.   END 
  939.   WHEN My_Variable < 20 THEN SAY "It's less than 20." 
  940.   OTHERWISE 
  941.     SAY "It must be > 19." 
  942. END 
  943.  
  944. The DO can be placed immediately after the THEN, ELSE, or WHEN, or the DO 
  945. keyword can be placed upon a separate line.  It's your preference which is 
  946. easier to read.  The following two examples are identical.  (Remember that 
  947. indenting is also optional). 
  948.  
  949. /* If My_Variable is greater than 10, then say "It's true" and set it to 10. */ 
  950. IF My_Variable > 10 THEN DO 
  951.   SAY "It's true." 
  952.   My_Variable = 10 
  953. END 
  954.  
  955. /* If My_Variable is greater than 10, then say "It's true" and set it to 10. */ 
  956. IF My_Variable > 10 THEN 
  957.   DO 
  958.    SAY "It's true." 
  959.    My_Variable = 10 
  960.   END 
  961.  
  962.  
  963. ΓòÉΓòÉΓòÉ 10.4. Nested conditionals ΓòÉΓòÉΓòÉ
  964.  
  965. You can put conditionals inside of other conditionals, for example, put an 
  966. IF/THEN instruction inside of another IF/THEN, or put a SELECT inside of an 
  967. IF/THEN which itself is inside of an IF/THEN.  But, you'll need to use DO/END 
  968. to help REXX distinguish nested conditionals (ie, which instructions go with 
  969. which Conditional instruction). 
  970.  
  971. Here we put an IF/THEN inside of another IF/THEN. 
  972.  
  973. IF My_Variable > 10 THEN DO 
  974.   IF My_Other_Variable = 10 THEN SAY "Both are at least 10." 
  975. END 
  976.  
  977. Here we put an IF/THEN inside one of the WHEN/THEN Conditionals within a 
  978. SELECT.  Within this IF/THEN, we also put another IF/THEN. 
  979.  
  980. SELECT 
  981.   WHEN My_Variable = 10 THEN DO 
  982.    SAY "It's equal to 10." 
  983.    IF My_Other_Variable = 10 THEN DO 
  984.      IF print_me = 'YES' THEN SAY "And so is My_Other_Variable." 
  985.    END 
  986.   END 
  987.   WHEN My_Variable < 10 THEN SAY "It's less than 10." 
  988.   WHEN My_Variable < 20 THEN SAY "It's less than 20." 
  989.   OTHERWISE 
  990.     SAY "It must be > 19." 
  991. END 
  992.  
  993.  
  994. ΓòÉΓòÉΓòÉ 10.5. NOP (no operation) keyword ΓòÉΓòÉΓòÉ
  995.  
  996. If you want one of the conditional instructions to do "nothing", then you must 
  997. use the keyword NOP (for "no operation").  Simply placing no instructions after 
  998. a THEN, ELSE, or WHEN will generate an error. 
  999.  
  1000. For example, here we specifically want to do nothing when My_Variable equals 
  1001. 10, and we also don't want to execute the OTHERWISE instructions in that case. 
  1002.  
  1003. /* Check My_Variable for a variety of conditions, but execute instructions for 
  1004. only 1 condition. */ 
  1005. SAY "Enter a number" 
  1006. PULL My_Variable 
  1007. SELECT 
  1008.   WHEN My_Variable = 10 THEN NOP 
  1009.   WHEN My_Variable < 10 THEN SAY "It's less than 10." 
  1010.   WHEN My_Variable < 20 THEN SAY "It's less than 20." 
  1011.   OTHERWISE 
  1012.     SAY "It must be > 19." 
  1013. END 
  1014.  
  1015.  
  1016. ΓòÉΓòÉΓòÉ 10.6. Strict Comparison Operators ΓòÉΓòÉΓòÉ
  1017.  
  1018. When comparing variables whose values are strings (ie, not numeric values), 
  1019. leading and trailing spaces are stripped from the strings before the 
  1020. comparison.  For example, 
  1021.  
  1022. My_Variable = '  Hello  ' 
  1023. IF My_Variable = 'Hello' THEN SAY 'It matches.' 
  1024.  
  1025. ...results in the expression being true, and the SAY instruction is executed. 
  1026.  
  1027. If you don't want leading and trailing blanks to be stripped before the 
  1028. comparison, then you can use the "strict" versions of the comparison operators. 
  1029.  
  1030. ==  "equal to" 
  1031. <<  "less than" 
  1032. >>  "greater than" 
  1033. <<=  "less than or equal to" 
  1034. >>=  "greater than or equal to" 
  1035. \==  "not equal to" 
  1036. \>>  "not greater than" 
  1037. \<<  "not less than" 
  1038.  
  1039. For example, 
  1040.  
  1041. My_Variable = '  Hello  ' 
  1042. IF My_Variable == 'Hello' THEN SAY 'It matches.' 
  1043.  
  1044. ...results in the expression being false, and the SAY instruction is not 
  1045. executed. 
  1046.  
  1047. The strict operators are also useful if you wish to compare a variable with a 
  1048. numeric value as if it were a string.  For example, consider the following two 
  1049. conditionals. 
  1050.  
  1051. My_Variable = '0.0' 
  1052. IF My_Variable = 0 THEN SAY "It matches." 
  1053. IF My_Variable == 0 THEN SAY "It matches again." 
  1054.  
  1055. The first conditional doesn't use a strict operator when it compares 
  1056. My_Variable to 0.  Therefore, the expression ends up being true.  The second 
  1057. conditional uses the strict operator ==, and therefore the expression ends up 
  1058. being false.  After all, although 0.0 is numerically the same as 0, the string 
  1059. '0.0' is not the same as '0'.  There's a decimal point and second 0 in '0.0' 
  1060. which does not appear in '0', so as literal strings, these two aren't equal. 
  1061.  
  1062.  
  1063. ΓòÉΓòÉΓòÉ 10.7. Boolean Operators in Comparisons (ie, combining expressions) ΓòÉΓòÉΓòÉ
  1064.  
  1065. Conditional expressions may be combined with the boolean operators: & (and), | 
  1066. (or) and && (xor).  They may also be reversed with the \ (not) operator. 
  1067.  
  1068. The & operator causes the combined expression to be regarded as true only if 
  1069. all of the individual expressions are true.  If any one (or more) of the 
  1070. individual expressions is false, then the combined expression is false. 
  1071.  
  1072. The | operator causes the combined expression to be regarded as true if one (or 
  1073. more) of the individual expressions is true.  If all of the individual 
  1074. expressions are false, then the combined expression is false. 
  1075.  
  1076. The && operator causes the combined expression to be regarded as true when one 
  1077. and only one of the individual expressions is true.  If more than one 
  1078. expression is true, or none of the expressions are true, then the combined 
  1079. expression is false. 
  1080.  
  1081. The \ operator reverses the result of any expression after it.  An expression 
  1082. that REXX normally evaluates as true is changed to false when the \ operator 
  1083. preceeds it.  Similarly, an expression that normally evaluates as false is 
  1084. changed to true when preceded by a \ operator. 
  1085.  
  1086. /* Decide what range My_Variable's value is in, and print out that range */ 
  1087. SAY "Enter a number" 
  1088. PULL My_Variable 
  1089. IF My_Variable>0 & My_Variable<10 THEN SAY "1-9" 
  1090. IF My_Variable\<10 & My_Variable<20 THEN SAY "10-19" 
  1091. IF \ (My_Variable<20 | My_Variable>=30) THEN SAY "20-29" 
  1092. IF My_Variable<=0 | My_Variable>=30 THEN SAY "Out of range" 
  1093.  
  1094. Note that we didn't put ELSE keywords before the second, third, and fourth IF 
  1095. keywords.  Therefore, REXX tests the expression of each of those IF 
  1096. conditionals, executing whichever ones happen to be true.  (Of course, due to 
  1097. the particular expressions that we've used, only 1 will ever be true for any 
  1098. given value of My_Variable). 
  1099.  
  1100. The above script may also be written using SELECT. 
  1101.  
  1102. /* Decide what range My_Variable's value is in, and print out that range */ 
  1103. SAY "Enter a number" 
  1104. PULL My_Variable 
  1105. SELECT 
  1106.   WHEN My_Variable>0 & My_Variable<10 THEN SAY "1-9" 
  1107.   WHEN My_Variable\<10 & My_Variable<20 THEN SAY "10-19" 
  1108.   WHEN \ (My_Variable<20 | My_Variable>=30) THEN SAY "20-29" 
  1109.   OTHERWISE SAY "Out of range" 
  1110. END 
  1111.  
  1112. Of course, only 1 of the WHEN instructions ever gets executed when this SELECT 
  1113. is executed. 
  1114.  
  1115.  
  1116. ΓòÉΓòÉΓòÉ 11. Variable Arrays (ie, Stem or compound variables) ΓòÉΓòÉΓòÉ
  1117.  
  1118. As well as "simple variables", REXX has arrays.  Any ordinary variable name can 
  1119. also be used as the name of an array.  An element (ie, field) of an array is 
  1120. accessed by typing the array name, a dot, and the element number or name.  The 
  1121. array name and the dot are together known as the "stem" of the array.  The 
  1122. element name is called a "compound symbol". 
  1123.  
  1124. For example, you could have an array with the variable name Days.  The first 
  1125. element in the array could be Days.1.  The second element in the array could be 
  1126. Days.2.  The third element in the array could be Days.3, etc. 
  1127.  
  1128. In fact not only numbers, but strings and variable names may be used as element 
  1129. names.  For example, the first element in the array could be Days.Monday.  The 
  1130. second element in the array could be Days.Tuesday.  The third element in the 
  1131. array could be Days.Wednesday, etc. 
  1132.  
  1133. Like with simple variables, an array does not have to be declared before it is 
  1134. used. 
  1135.  
  1136. /* This script uses an array named array with 3 elements named 1, 2, and 3 */ 
  1137. PULL val 
  1138. array.1 = val 
  1139. array.2 = val*val 
  1140. array.3 = val**3 
  1141. SAY array.1 array.2 array.3 array.1+array.2+array.3 
  1142.  
  1143. Additional element names can be appended to create 2-dimensional (or more) 
  1144. arrays.  For example, you could have an array with the variable name Months. 
  1145. The first element in the array could be Months.January.1.  The second element 
  1146. in the array could be Months.January.2, etc.  The last element in the array 
  1147. could be Months.December.31. 
  1148.  
  1149. The following script uses a 2-dimensional array named book.  Each book entry 
  1150. has 3 elements named author, title, and pub.  There can be an unlimited number 
  1151. of book entries, so element numbers are used for the first compound symbol. 
  1152. Therefore, book.1.author contains the author of the first book.  book.1.title 
  1153. contains the title of the first book.  book.1.pub contains the publisher of the 
  1154. first book.  book.2.author contains the author of the second book.  Etc.  The 
  1155. script initializes 2 book entries, asks the user what book number he'd like to 
  1156. see the information for, and prints out that book's author, title, and 
  1157. publisher. 
  1158.  
  1159. /* This program uses a 2-dimensional array named book with various elements. */ 
  1160. book.1.author="M. F. Cowlishaw" 
  1161. book.1.title="The REXX Language, a practical approach to programming" 
  1162. book.1.pub="Englewood Cliffs 1985" 
  1163. book.2.author="A. S. Rudd" 
  1164. book.2.title="Practical Usage of REXX" 
  1165. book.2.pub="Ellis Horwood 1990" 
  1166.  
  1167. /* Look up the book that the user indicates.  Use a variable to get the element 
  1168. number.  Note that we use that variable name when accessing the element number. 
  1169. */ 
  1170. SAY "Input a book number" 
  1171. PULL i 
  1172. SAY "Author:  " book.i.author 
  1173. SAY "Title:   " book.i.title 
  1174. SAY "Publisher:" book.i.pub 
  1175.  
  1176. As with simple variables, if a particular array element has not been given a 
  1177. value, then its name is used instead.  If you enter a 3 for the desired book 
  1178. number, then the following is displayed: 
  1179.  
  1180. Author:   BOOK.3.AUTHOR 
  1181. Title:   BOOK.3.TITLE 
  1182. Publisher: BOOK.3.PUB 
  1183.  
  1184. This is because these 3 elements were never initialized. 
  1185.  
  1186. You can easily initialize every element of an array using just one instruction 
  1187. by assigning a value to the stem itself.  Edit the above script and insert the 
  1188. following instruction after the opening comment: 
  1189.  
  1190. book.="Undefined" 
  1191.  
  1192. This gives every possible element of the array the value "Undefined", so that 
  1193. if you again type 3 for the desired book number, the following is displayed: 
  1194.  
  1195. Author:   Undefined 
  1196. Title:   Undefined 
  1197. Publisher: Undefined 
  1198.  
  1199. Because the element can be a variable name, this means that you could assign a 
  1200. new value to that variable, and thus access various fields of the array.  For 
  1201. example, assume that you want to create a list of the ages of various people. 
  1202. You want to use one array called Age to store all of these ages, and for a 
  1203. given person, you want to use his last name as the element name.  Let's 
  1204. identify 3 people whose last names are Baker, Jones, and Smith, and their ages 
  1205. are 30, 16, and 45.  Here we initialize the array. 
  1206.  
  1207. /* Initialize our Age array for 3 people. */ 
  1208. Age.Baker = 30 
  1209. Age.Jones = 16 
  1210. Age.Smith = 45 
  1211.  
  1212. Now, if you wanted to allow a user to look up a person's age by entering the 
  1213. last name of that person, you could do this as so: 
  1214.  
  1215. SAY 'Enter the last name of the person:' 
  1216. PARSE PULL name 
  1217. SAY 'The age of' name 'is' Age.name 'years.' 
  1218.  
  1219.  
  1220. ΓòÉΓòÉΓòÉ 12. Loops ΓòÉΓòÉΓòÉ
  1221.  
  1222. REXX has many ways to implement loops using the keywords DO and END.  DO 
  1223. indicates the start of the loop, and is placed before the first instruction in 
  1224. the loop.  END indicates the end of the loop, and is placed after the last 
  1225. instruction in the loop. 
  1226.  
  1227.  
  1228. ΓòÉΓòÉΓòÉ 12.1. Loops that repeat a set number of times ΓòÉΓòÉΓòÉ
  1229.  
  1230. You can specify how many times to repeat the instructions within the loop by 
  1231. putting a numeric expression after the DO keyword.  For example, here we say 
  1232. "Hello" 10 times. 
  1233.  
  1234. /* Say "Hello" ten times */ 
  1235. DO 10 
  1236.   SAY "Hello" 
  1237. END 
  1238.  
  1239. Alternately, the numeric expression could be represented by a variable's value 
  1240. (or any mathematical expression). 
  1241.  
  1242. /* Say "Hello" ten times */ 
  1243. My_Variable = 10 
  1244. DO My_Variable 
  1245.   SAY "Hello" 
  1246. END 
  1247.  
  1248. Note:  Even if you were to change the value of My_Variable within the loop (ie, 
  1249.        put an assignment instruction inside of the loop to set My_Variable to a 
  1250.        new value), the loop would still execute 10 times.  This usage of DO 
  1251.        copies the initial value of My_Variable to an internal REXX variable 
  1252.        which is then used to count how many times the loop repeats.
  1253.  
  1254. If instead of a numeric expression, you place the keyword FOREVER after DO, 
  1255. then the loop will continue to repeat indefinitely (unless the user presses the 
  1256. CTRL and BREAK keys to abort the script, or the ITERATE or LEAVE keywords are 
  1257. used within the loop). 
  1258.  
  1259. /* This script keeps saying "Hello" indefinitely */ 
  1260. DO FOREVER 
  1261.   SAY "Hello" 
  1262. END 
  1263.  
  1264. Control loops use a variable (called the "control variable") as a counter.  You 
  1265. specify the range over which the variable's (numeric) value is to be 
  1266. incremented, by specifying the initial (ie, start) value of the variable as 
  1267. well as the end value (ie, at what value the loop will stop repeating).  REXX 
  1268. automatically increments the variable's value upon each repeat of the loop, 
  1269. terminating the loop when the variable's value reaches the end value.  (REXX 
  1270. also initializes the variable to the start value upon the first iteration of 
  1271. the loop).  By default, the control variable increments by 1.  The start value 
  1272. is specified after the = sign following the variable name.  The end value is 
  1273. specified after the TO keyword.  The end value must be greater than or equal to 
  1274. the start value in order for the loop to be executed.  (If the start value is 
  1275. equal to the end value, then the loop is executed once only).  If the end value 
  1276. is less than the start value, then the loop will be skipped.  You may use the 
  1277. variable in some instruction within the loop, and this is extremely useful when 
  1278. you need to step through some array, for example. 
  1279.  
  1280. /* Count from 1 to 20, inclusive, saying each incremented value of the variable 
  1281. */ 
  1282. DO My_Variable=1 TO 20 
  1283.   SAY My_Variable 
  1284. END 
  1285.  
  1286. Here we print out the values of the array elements Array.1, Array.2, Array.3 
  1287. and Array.4. 
  1288.  
  1289. /* Print values of array elements Array.1, Array.2, Array.3 and Array.4 */ 
  1290. DO My_Variable=1 TO 4 
  1291.   SAY Array.My_Variable 
  1292. END 
  1293.  
  1294. You can use a variable's value (or any mathematical expression) to specify the 
  1295. start or end values.  Here we use the value of the variable count to specify 
  1296. the end value. 
  1297.  
  1298. /* Count from 1 to the value of count, inclusive, saying each incremented value 
  1299. of the variable */ 
  1300. DO My_Variable=1 TO count 
  1301.   SAY My_Variable 
  1302. END 
  1303.  
  1304. You can specify that the variable's value is to be incremented in steps other 
  1305. than by 1.  Use the BY keyword, followed by a numeric expression (ie, could be 
  1306. a variable or mathematical expression too) representing the increment amount. 
  1307. For example, here My_Variable is incremented by 2.3 upon each repeat of the 
  1308. loop. 
  1309.  
  1310. /* Print all multiples of 2.3 not more than 20 */ 
  1311. DO My_Variable=0 TO 20 BY 2.3 
  1312.   SAY My_Variable 
  1313. END 
  1314.  
  1315. You can even setup a loop such that the variable's value is decremented.  When 
  1316. doing this, the start value should be higher than the end value, and you should 
  1317. specify a negative increment amount (ie, a decrement amount).  Here we count 
  1318. down from 20 to 1 (ie, decrementing by 1 upon each repeat of the loop). 
  1319.  
  1320. /* Count from 20 to 1, inclusive, saying each decremented value of the variable 
  1321. */ 
  1322. DO My_Variable=20 TO 1 BY -1 
  1323.   SAY My_Variable 
  1324. END 
  1325.  
  1326. In fact, you could also use negative values for the start and end values. 
  1327.  
  1328. /* Count from -5 to -1, inclusive, saying each incremented value of the 
  1329. variable */ 
  1330. DO My_Variable=-5 TO -1 
  1331.   SAY My_Variable 
  1332. END 
  1333.  
  1334. Instead of specifying a start and end value, you can specify a start value and, 
  1335. using the FOR keyword, specify how many times the loop is to repeat.  The 
  1336. repeat count is the numeric expression after FOR.  Again, this can also be 
  1337. specified using a variable's value (or a mathematical expression). 
  1338.  
  1339. /* Print the first five multiples of 5.7 (ie, 0, 5.7, 11.4, 17.1, 22.8) */ 
  1340. DO My_Variable=0 FOR 5 BY 5.7 
  1341.   SAY My_Variable 
  1342. END 
  1343.  
  1344. If you only specify a start value, but no end value or repeat count, then the 
  1345. loop will repeat forever, incrementing the variable's value by the increment 
  1346. amount (unless the user presses CTRL and BREAK, or the ITERATE or LEAVE 
  1347. keywords are used within the loop). 
  1348.  
  1349. /* Print all the natural numbers */ 
  1350. DO My_Variable=0 
  1351.   SAY My_Variable 
  1352. END My_Variable 
  1353.  
  1354. The My_Variable at the end of the preceding example is optional.  At the end of 
  1355. any control loop, the name of the control variable may be placed after the END 
  1356. keyword, where it will be checked to see if it matches the control variable. 
  1357.  
  1358. Note:  Changing the value of My_Variable within any of the above control loops 
  1359.        (ie, put an assignment instruction inside of the loop to set My_Variable 
  1360.        to a new value), will affect how many times the loop repeats.  This 
  1361.        usage of DO checks the value of My_Variable each time the loop repeats, 
  1362.        incrementing its current value accordingly.  In fact, after the loop has 
  1363.        finished, the value of My_Variable will then be one more than the repeat count.
  1364.  
  1365.  
  1366. ΓòÉΓòÉΓòÉ 12.2. Loops that repeat until a condition is met ΓòÉΓòÉΓòÉ
  1367.  
  1368. A set of instructions may be executed repeatedly until some condition is true, 
  1369. by placing the UNTIL keyword after DO, and then following it with some 
  1370. conditional expression (as are used in conditional instructions).  For example, 
  1371. here we repeat the loop until the variable answer does not have the value "NO". 
  1372.  
  1373. /* I won't take no for an answer */ 
  1374. DO UNTIL answer \= "NO" 
  1375.   PULL answer 
  1376. END 
  1377.  
  1378. Alternatively, a loop can be executed as long as some condition is true by 
  1379. placing the WHILE keyword after DO. 
  1380.  
  1381. /* This loop repeats as long as there is no error */ 
  1382. DO WHILE error=0 
  1383.   PULL a 
  1384.   IF a="ERROR" THEN error=1 
  1385.   ELSE SAY a 
  1386. END 
  1387.  
  1388. Using WHILE, if the expression is true to start with, then the set of 
  1389. instructions within the loop will not be executed at all.  Using UNTIL, the 
  1390. instructions within the loop will always be executed at least once.  This is 
  1391. because UNTIL tests to see if the expression is true at the end of each loop's 
  1392. iteration, whereas WHILE tests to see if the expression is true at the start of 
  1393. each iteration. 
  1394.  
  1395. Another important distinction is that with WHILE, the loop continues executing 
  1396. as long as the expression is true (ie, a false expression ends the loop), 
  1397. whereas with UNTIL, the loop continues as long as the expression is false (ie, 
  1398. a true expression ends the loop). 
  1399.  
  1400. You can place a numeric value after DO in order to specify how many times to 
  1401. repeat the loop, and then also use the UNTIL or WHILE keywords to specify some 
  1402. condition that may prematurely end the loop.  Of course, you can use a 
  1403. variable's value (or mathematical expression) to specify the repeat count. 
  1404.  
  1405. /* I won't take NO for an answer unless it is typed three times */ 
  1406. DO 3 UNTIL answer \= "NO" 
  1407.   PULL answer 
  1408. END 
  1409.  
  1410. You can also use a control variable along with the UNTIL or WHILE keywords. 
  1411.  
  1412. /* Input upto 10 answers, but stop when empty string is entered */ 
  1413. DO n=1 TO 10 UNTIL answer=="" 
  1414.   PULL answer 
  1415.   answers.n=answer 
  1416. END 
  1417.  
  1418.  
  1419. ΓòÉΓòÉΓòÉ 12.3. ITERATE and LEAVE keywords ΓòÉΓòÉΓòÉ
  1420.  
  1421. The ITERATE and LEAVE keywords allow you to skip to the next iteration of the 
  1422. loop, or to break out of (ie, end) the loop respectively.  For example: 
  1423.  
  1424. /* Input ten answers in an array, but stop when empty string is entered */ 
  1425. DO n=1 TO 10 
  1426.   PULL My_Variable.n 
  1427.   IF My_Variable.n == "" THEN LEAVE 
  1428. END 
  1429.  
  1430. /* Print all integers from 1-10 except 3 */ 
  1431. DO n=1 TO 10 
  1432.   IF n=3 THEN ITERATE 
  1433.   SAY n 
  1434. END 
  1435.  
  1436. If a variable name is placed after the keywords ITERATE or LEAVE, then you can 
  1437. iterate or leave the loop whose control variable is that variable name.  This 
  1438. is how, when you have nested loops, you can jump out of an inner loop and skip 
  1439. some of the outer loops -- simply LEAVE or ITERATE to the desired outer loop by 
  1440. placing that outer loop's control variable's name after the LEAVE or ITERATE. 
  1441.  
  1442. /* Jumping out of an inner loop to an outer loop */ 
  1443. DO loop1=1 TO 3 
  1444.   SAY "I'm in loop1. loop1=" loop1 
  1445.   DO loop2=1 TO 3 
  1446.    SAY "I'm in loop2. loop2=" loop2 
  1447.    DO loop3=1 TO 3 
  1448.      SAY "I'm in loop3. loop3=" loop3 
  1449.      /* Jump out to loop1, thereby skipping loop2's remaining iterations. We 
  1450. jump back to the very first line in this example. */ 
  1451.      ITERATE loop1 
  1452.    END 
  1453.   END 
  1454. END 
  1455.  
  1456. /* Print pairs (i,j) where 1 <= i,j <= 5, except (2,j) if j>=3 */ 
  1457. DO i=1 TO 5 
  1458.   DO j=1 TO 5 
  1459.     IF i=2 & j=3 THEN ITERATE i /* or "LEAVE j" would work, or just "LEAVE" */ 
  1460.     SAY "("i","j")" 
  1461.   END 
  1462. END 
  1463.  
  1464.  
  1465. ΓòÉΓòÉΓòÉ 13. Functions ΓòÉΓòÉΓòÉ
  1466.  
  1467. A REXX Function is a routine (supplied by the REXX interpreter or contained 
  1468. within some add-on, binary executable known as a DLL) that your REXX script can 
  1469. call, perhaps passing some data to it upon which the Function operates.  A 
  1470. Function performs its work, and then returns a value (which may be an error 
  1471. number or error string, or some other data).  When a REXX script calls a 
  1472. Function, the script halts until the Function has completed its work and 
  1473. returned its value. 
  1474.  
  1475. There are numerous Functions built into the REXX interpreter, and these are 
  1476. automatically available to be called by a script.  A listing of each built-in 
  1477. Function's name, what data (ie, arguments) it allows to be passed to it, and 
  1478. what data (value) it returns, can be found in the REXX Procedures Language 
  1479. 2/Rexx book by IBM.  Functions contained within add-on DLLs can also be called 
  1480. by your script, but first you usually must issue the interpreter's RXFUNCADD 
  1481. Function to let the interpreter know where to find the DLL containing the 
  1482. desired function, as well as what the function's name is. 
  1483.  
  1484. Just like Instruction Keywords such as SAY, a Function has a name which you use 
  1485. to call the Function.  For example, the interpreter has a built-in Function 
  1486. named TIME.  A Function is called by typing its name (case doesn't matter) 
  1487. immediately followed by ( (ie, there must be no space inbetween the name and 
  1488. open parenthesis).  After the (, you put any data that you wish passed to the 
  1489. Function, and finally a closing parenthesis ).  Here's an example of calling 
  1490. the TIME Function: 
  1491.  
  1492. TIME()  /* Actually, the CALL instruction needs to precede this */ 
  1493.  
  1494. You'll note that we didn't place any data inbetween the parentheses, because we 
  1495. aren't passing any arguments to TIME. 
  1496.  
  1497. The TIME Function happens to return a string containing the hours, minutes, and 
  1498. seconds of the current time (in 24 hour, military time), each separated by a 
  1499. colon.  For example, the time may be reported as 01:30:44 (ie, AM). 
  1500.  
  1501. Since a Function returns some data, you can say that the Function has a value 
  1502. just like a variable.  Therefore, you can treat a Function exactly like a 
  1503. variable that has a value, except that this is a read-only variable (ie, you 
  1504. can't assign a new value to a Function's name).  For example, just like you can 
  1505. assign the value of one variable to another variable, you can assign the value 
  1506. of a Function to a variable. 
  1507.  
  1508. My_Time = TIME() 
  1509.  
  1510. The preceding instruction assigns the value of the TIME Function (ie, the 
  1511. current time) to the variable My_Time.  For example, after executing that 
  1512. instruction, My_Time's value may be the string 01:30:44. 
  1513.  
  1514. You can also use a Function anywhere you would use a variable's value.  For 
  1515. example, here we use the value of TIME in the Conditional IF/THEN instruction. 
  1516. We check to see if TIME's value is 10:00:00 (ie, 10AM), and if so, we SAY "It's 
  1517. time". 
  1518.  
  1519. /* Check for 10AM */ 
  1520. IF TIME() == '10:00:00' THEN SAY "It's time" 
  1521.  
  1522. So here you see a primary difference between a REXX Keyword and a Function.  A 
  1523. Function has a value, and be used as if it were a read-only variable.  REXX 
  1524. Keywords do not have values, and also are used only at specific places within 
  1525. an instruction, sometimes only in conjunction with other keywords. 
  1526.  
  1527. TIME also allows one argument.  Sometimes, arguments can be optionally omitted, 
  1528. as we did previously with TIME.  TIME allows a string to be passed which must 
  1529. be one of the following, depending upon how you wish TIME to format the 
  1530. returned time string: CIVIL, ELAPSED, HOURS, LONG, MINUTES, SECONDS, NORMAL, or 
  1531. RESET.  If we specify the CIVIL option, then the returned time string takes the 
  1532. format of the hour and minutes in 12 hour format, followed by AM or PM, for 
  1533. example, 10:00:AM.  Here we assign that return to My_Time. 
  1534.  
  1535. My_Time = TIME('CIVIL') 
  1536.  
  1537. Note that CIVIL was placed in quotes to make sure that the interpreter regards 
  1538. it as a literal string, rather than a variable name whose value should be 
  1539. passed to TIME.  You can alternately specify variable names as arguments to a 
  1540. Function.  In that case, the interpreter, as usual, replaces the variable name 
  1541. with its value, and that value is what gets passed to the Function as the 
  1542. argument.  Here, we pass the string CIVIL using a variable. 
  1543.  
  1544. My_Option = 'CIVIL' 
  1545. My_Time = TIME(My_Option) 
  1546.  
  1547. Here are some more examples of using a Function's (returned) value. 
  1548.  
  1549. /* Use TIME's value in a conditional loop (ie, loop until 10 o'clock) */ 
  1550. DO UNTIL TIME() == '10:00:00' 
  1551.   SAY "It's not 10 o'clock yet" 
  1552. END 
  1553.  
  1554. /* Use TIME's value as an argument for the SAY instruction (ie, print the time) 
  1555. */ 
  1556. SAY TIME() 
  1557.  
  1558. You can even use a Function's value as an argument to another Function.  Here 
  1559. we use the returned value of TIME as an argument to the LENGTH Function.  The 
  1560. LENGTH Function allows one argument, any string or numeric value, and it 
  1561. returns the number of characters in that string.  Then, we use the returned 
  1562. value of LENGTH as an argument for the SAY instruction. 
  1563.  
  1564. /* Use TIME's value as an argument for the LENGTH Function which in turn 
  1565. supplies an arg for SAY (ie, print number of characters in the time) */ 
  1566. SAY LENGTH(TIME('CIVIL')) 
  1567.  
  1568. In this case, the interpreter executes the lowest nested function first.  Here, 
  1569. that's TIME.  TIME is called with its argument "CIVIL'.  The returned value of 
  1570. TIME (let's assume that it's the string 10:00AM) is then passed as an argument 
  1571. to LENGTH.  LENGTH would return the value 7 (because there are 7 characters in 
  1572. the string 10:00AM).  This 7 is then the argument for SAY, and therefore a 7 
  1573. gets printed to the screen. 
  1574.  
  1575. If you wish to not use the Function's value in any way (ie, you're not 
  1576. assigning it to a variable, or using its value in a conditional expression, or 
  1577. in a conditional loop, or as an argument itself), then you must place the 
  1578. keyword CALL before the Function name to toss the returned value away, or REXX 
  1579. will report an error.  For example, here we call the DIRECTORY Function, 
  1580. supplying an argument that is the directory we desire to be made the current 
  1581. one.  DIRECTORY returns a string telling what is the current directory before 
  1582. the change (ie, the previously current directory).  We just throw away that 
  1583. return value. 
  1584.  
  1585. CALL DIRECTORY(  'C:\TEMP'  ) 
  1586.  
  1587. Note that I added blank spaces around the argument for readability.  This is 
  1588. always optional. 
  1589.  
  1590. Actually, the return value is not thrown away when you use call, but rather, 
  1591. the interpreter stores it in the special variable named RESULT. 
  1592.  
  1593. When a Function allows more than one argument, each argument must be separated 
  1594. by a comma.  For example, the LINEOUT Function allows 3 arguments.  The first 
  1595. arg is the name of the file to which data is written.  The second arg is the 
  1596. actual data to be written (ie, a string, numeric value, variable's value, or 
  1597. Function's value).  The third arg is a 1 if you want to overwrite any existing 
  1598. file, or omit the arg if you wish to append the data to the end of any existing 
  1599. file.  For example, here we write the string more data to the file C:\DATAFILE, 
  1600. overwriting any existing file. 
  1601.  
  1602. error = LINEOUT('C:\DATAFILE',  'more data',  1) 
  1603.  
  1604. Once again, note that blank space can be put between args to improve 
  1605. readability. 
  1606.  
  1607. Note:  If you place CALL before the preceding instruction (in order to throw 
  1608.        away the return value), the REXX interpreter will cause an error.  It 
  1609.        seems that, unless a function only takes one argument, when you want to 
  1610.        use CALL with it, you need to remove the parentheses around the 
  1611.        arguments.  I consider this to be an unintuitive aberration of OS/2 
  1612.        REXX.  So, in fact, if you want to use CALL in the above example, the 
  1613.        instruction will be: 
  1614.  
  1615. CALL LINEOUT 'C:\DATAFILE',  'more data',  1 
  1616.  
  1617. In the above, I'm throwing away the return value of LINEOUT, which would be an 
  1618. error number (ie, 0 if there was no error writing the line, otherwise 1). 
  1619. You'd normally want to check that return.
  1620.  
  1621. To omit an arg, simply put its comma, with nothing before the comma.  For 
  1622. example, if you omit the first arg to LINEOUT, then the Function defaults to 
  1623. writing the line to the display (ie, same thing as the SAY command).  Here I 
  1624. omit the first arg. 
  1625.  
  1626. error = LINEOUT(,  'more data',  1) 
  1627.  
  1628. Omitting the last arg is even easier.  You just omit it, and then you can omit 
  1629. the comma of the previous arg too (ie, which separates the two args). 
  1630.  
  1631. CALL LINEOUT  ,  'more data' 
  1632.  
  1633. In fact, if you wish to omit several args, and they are all at the end of the 
  1634. calling template, then you just omit those args, as well as any trailing comma 
  1635. (after the last arg that isn't omitted). 
  1636.  
  1637.  
  1638. ΓòÉΓòÉΓòÉ 14. Parsing (ie, breaking apart data into separate pieces) ΓòÉΓòÉΓòÉ
  1639.  
  1640. Parsing is the act of breaking apart one piece of data into separate pieces. 
  1641. For example, let's say that the value of the variable My_Variable is the string 
  1642. This is some data.  You wish to break this apart so that each word is assigned 
  1643. to a different variable.  You use the PARSE instruction to do this. 
  1644.  
  1645. By default, PARSE breaks apart data wherever there is at least one blank space. 
  1646. So, the first piece of data that PARSE breaks off of My_Variable's value is the 
  1647. word "This".  This process is referred to as "tokenization", and so "This" is 
  1648. the first token.  The second token (ie, second piece of data that PARSE breaks 
  1649. off) is the word "is".  The third token is "some", and the fourth (and last 
  1650. token) is "data".  PARSE trims any leading and trailing spaces from each token 
  1651. that is broken off, except for the last token.  (One leading space upon the 
  1652. last token is eaten by the parsing process). 
  1653.  
  1654. One of the following keywords must follow the PARSE keyword: ARG, PULL, VAR, 
  1655. SOURCE, VERSION, LINEIN, or VALUE.  Which one you use depends upon where you're 
  1656. getting the data being broken apart, and how you want it broken apart.  You can 
  1657. also use the keyword UPPER in conjunction with any of the preceding keywords in 
  1658. order to tell REXX to change all lower case letters to upper case in any tokens 
  1659. that are broken off. 
  1660.  
  1661.  
  1662. ΓòÉΓòÉΓòÉ 14.1. VAR ΓòÉΓòÉΓòÉ
  1663.  
  1664. If you wish to break apart a variable's value into separate pieces, you'll use 
  1665. the VAR (or VALUE) keyword.  After the VAR keyword, you specify the variable 
  1666. name that contains the data to be broken apart (ie, the source).  Then, you 
  1667. specify the names of other variables into which each token is placed.  For 
  1668. example, here we specify that My_Variable's value is to be broken apart, and 
  1669. the first token is placed into the variable token.1, the second token is placed 
  1670. into the variable token.2, the third token is placed into the variable token.3, 
  1671. and the fourth token is placed into the variable token.4. 
  1672.  
  1673. /* Parse My_Variable into 4 tokens */ 
  1674. My_Variable = "This is some data" 
  1675. PARSE VAR My_Variable token.1 token.2 token.3 token.4 
  1676. DO i=1 TO 4 
  1677.   SAY "token."i "= '"token.i"'" 
  1678. END 
  1679.  
  1680. If you supply less token variables than there are actual tokens within the 
  1681. source, then the last token variable will contain all remaining tokens.  For 
  1682. example, consider the following line: 
  1683.  
  1684. PARSE VAR My_Variable token.1 token.2 token.3 
  1685.  
  1686. "This" is broken off and assigned to token.1, "is" is broken off and assigned 
  1687. to token.2, and since token.3 is the last supplied token variable, the 
  1688. remainder of My_Variable's value, "some data" is assigned to token.3.  So, the 
  1689. last token always gets whatever is left over of the value after preceding 
  1690. tokens have been broken off.  Also, remember that leading (except for one 
  1691. space) and trailing spaces are not removed from the last token variable. 
  1692.  
  1693. It's also acceptable to specify more token variables than there actually are 
  1694. tokens within the source.  For example: 
  1695.  
  1696. PARSE VAR My_Variable token.1 token.2 token.3 token.4 token.5 
  1697.  
  1698. "This" is broken off and assigned to token.1, "is" is broken off and assigned 
  1699. to token.2, "some" is broken off and assigned to token.3, "data" is broken off 
  1700. and assigned to token.4.  There are no more tokens within My_Variable, so 
  1701. token.5 is assigned to be an empty (ie, null) string containing no characters 
  1702. at all.  (Actually, if there were more than one trailing space after "data", 
  1703. these would be assigned to token.5). 
  1704.  
  1705. PARSE does not alter the source variable (ie, being parsed).  So after the 
  1706. PARSE instructions above, My_Variable is still "This is some data".  On the 
  1707. other hand, you can specify My_Variable as one of the token variables as well, 
  1708. in which case it will be altered.  This is very handy if you wish to break off 
  1709. the first word of a variable, and then reassign the remaining tokens back to 
  1710. that variable.  Here we break off the first word of My_Variable, assigning that 
  1711. token to token.1, and then the remaining tokens are reassigned to My_Variable. 
  1712.  
  1713. PARSE VAR My_Variable token.1 My_Variable 
  1714.  
  1715. After the above line, token.1's value is "This" and My_Variable's new value is 
  1716. "is some data". 
  1717.  
  1718. /* Parse My_Variable into all of its tokens */ 
  1719. SAY "Input a line" 
  1720. PULL My_Variable 
  1721. count = 0 
  1722. DO WHILE My_Variable \== "" 
  1723.   PARSE VAR My_Variable token.count My_Variable 
  1724.   SAY "'"token.count"'" 
  1725.   count = count + 1 
  1726. END 
  1727. SAY "There are" count "tokens." 
  1728.  
  1729. If you use PARSE VAR without specifying any token variable names, then the 
  1730. specified source variable is accessed.  If it does not have a value, the 
  1731. NOVALUE condition is raised, if enabled. 
  1732.  
  1733.  
  1734. ΓòÉΓòÉΓòÉ 14.2. Using search strings (to break apart tokens) ΓòÉΓòÉΓòÉ
  1735.  
  1736. PARSE defaults to breaking off tokens at blank spaces. 
  1737.  
  1738. If you wish the value to be tokenized at characters other than a blank space, 
  1739. you can specify that as a literal string (we'll call the search string) after 
  1740. the token variable name.  For example, assume that My_Variable's value is the 
  1741. string "This is some data; separated by a semi-colon, and then a comma".  You 
  1742. wish to break this up into 3 tokens, separating the first token at the 
  1743. semi-colon (ie, "This is some data"), and the second token at the comma (ie, 
  1744. "separated by a semi-colon"), with the last token being "and then a comma". 
  1745. Here's how we do that: 
  1746.  
  1747. /* Parse My_Variable into 3 tokens, broken at ; and , */ 
  1748. My_Variable = "This is some data;    separated by a semi-colon, and then a 
  1749. comma" 
  1750. PARSE VAR My_Variable token.1 ';' token.2 ',' token.3 
  1751. DO i=1 TO 3 
  1752.   SAY "token."i "= '"token.i"'" 
  1753. END 
  1754.  
  1755. Note that since we aren't tokenizing by blank space, the interpreter doesn't 
  1756. trim the leading spaces off of the second token.  You'd have to use the TRIM 
  1757. Function to subsequently do that. 
  1758.  
  1759. You can token by entire strings (ie, patterns).  For example, here we break 
  1760. apart the first token at the string "some", and the second token at the string 
  1761. "more". 
  1762.  
  1763. /* Parse My_Variable at the string "some" and "more" */ 
  1764. My_Variable = "This is some data; and this is more" 
  1765. PARSE VAR My_Variable token.1 "some" token.2 "more" token.3 
  1766. DO i=1 TO 3 
  1767.   SAY "token."i "= '"token.i"'" 
  1768. END 
  1769.  
  1770. Note that the search strings "some" and "more" are completely removed from the 
  1771. tokens.  If "some" did not appear in My_Variable at all, then the first token 
  1772. would contain the entire string, and the second and third tokens would be null 
  1773. strings.  If "some" appeared, but "more" did not, then the first token would be 
  1774. "This is ", the second token would be the remaining data, and the third token 
  1775. would be a null string. 
  1776.  
  1777. It's possible to tokenise the source data appearing inbetween search strings. 
  1778. For example, 
  1779.  
  1780. /* Parse My_Variable between "some" and "more" */ 
  1781. My_Variable = "This is some data; and this is more" 
  1782. PARSE VAR My_Variable token.1 "some" token.1 token.2 token.3 "more" 
  1783. DO i=1 TO 3 
  1784.   SAY "token."i "= '"token.i"'" 
  1785. END 
  1786.  
  1787. The above tokenises everything between "some" and "more" and places the tokens 
  1788. in token.1 (ie, "data;"), token.2 (ie, "and"), and token.3 (ie, "this is "). 
  1789.  
  1790. You can also use a variable containing the desired search string.  Put the 
  1791. variable name containing the search string in parentheses when you use it with 
  1792. PARSE.  Here we use 2 variables to specify 2 search strings. 
  1793.  
  1794. /* Parse My_Variable using search strings */ 
  1795. My_Variable = "This is some data;    separated by a semi-colon, and then a 
  1796. comma" 
  1797. searchstr1 = ';' 
  1798. searchstr2 = ',' 
  1799. PARSE VAR My_Variable token.1 (searchstr1) token.2 (searchstr2) token.3 
  1800. DO i=1 TO 3 
  1801.   SAY "token."i "= '"token.i"'" 
  1802. END 
  1803.  
  1804.  
  1805. ΓòÉΓòÉΓòÉ 14.3. Throwing away tokens ΓòÉΓòÉΓòÉ
  1806.  
  1807. Placing a dot instead of a token variable name causes that token to be thrown 
  1808. away.  For example, here we throw away the second and fourth tokens of 
  1809. My_Variable (ie, "is" and "data"). 
  1810.  
  1811. /* Parse My_Variable, tossing away 2nd and 4th tokens */ 
  1812. My_Variable = "This is some data" 
  1813. PARSE VAR My_Variable token.1 . token.2 . 
  1814.  
  1815. It's often a good idea to place a dot after the last token variable name.  Not 
  1816. only does this throw away any extra tokens that you don't want, but it also 
  1817. ensures that none of the tokens that you do break off contain spaces. 
  1818. (Remember, only the last token may contain spaces, and that's one that you're 
  1819. throwing away). 
  1820.  
  1821.  
  1822. ΓòÉΓòÉΓòÉ 14.4. Parse at particular character positions ΓòÉΓòÉΓòÉ
  1823.  
  1824. It's possible to parse by character (numeric) position instead of by searching 
  1825. for a string.  Character positions start at 1 for the first character, and 
  1826. range upwards for further characters (ie, the second character in the source is 
  1827. 2, etc).  You can indicate at which character to start parsing a token by 
  1828. placing this character position before the token variable name.  Then, you 
  1829. place how many characters you wish to parse into that token after the token 
  1830. variable name, with a + sign immediately before the count. 
  1831.  
  1832. /* Parse My_Variable by character position */ 
  1833. My_Variable = "This is some data" 
  1834. PARSE VAR My_Variable   4 token.1 +6   token.2 +5   3 token.3 
  1835. DO i=1 TO 3 
  1836.   SAY "token."i "= '"token.i"'" 
  1837. END 
  1838.  
  1839. token.1 will be the 6 characters of My_Variable's value starting at character 4 
  1840. (ie, "s is s").  token.2 will be the next 5 characters (ie, "ome d").  Note 
  1841. that there is no character position specified for the second token, so that is 
  1842. why it starts where the previous token ended.  token.3 will be the all data 
  1843. starting at character 3 (ie, "is is some data"). 
  1844.  
  1845. In above example, the position is absolute.  That is, when you specify 4 for 
  1846. the position, you mean the fourth character in the source string.  But, you can 
  1847. also specify relative position, by putting a + or - sign before the position 
  1848. number.  This means that you want a position relative to the next character 
  1849. that PARSE is set to operate upon (after breaking off any previous token). 
  1850.  
  1851. /* Parse My_Variable by relative character position */ 
  1852. My_Variable = "This is some data" 
  1853. PARSE VAR My_Variable   token.1 +6  -3 token.2 
  1854. SAY "token.1 = '"token.1"'" 
  1855. SAY "token.2 = '"token.2"'" 
  1856. END 
  1857.  
  1858. Above, we chop of the first 6 characters of the source string and place it into 
  1859. token.1.  After doing this, PARSE will be set to start breaking off the source 
  1860. string at the seventh character.  But, since we used a - sign before the 
  1861. position number preceding the next token variable name, we move to a relative 
  1862. position.  In this case, we move 3 characters back, so PARSE starts breaking 
  1863. off the second token at the fourth character in the source.  So token.2 is "s 
  1864. is some data". 
  1865.  
  1866. Obviously, when using relative positions, you'll have to be careful that REXX 
  1867. doesn't mistake a relative position for a given token as the character count 
  1868. for the preceding token.  This could happen if you omitted the character count 
  1869. for the preceding token. 
  1870.  
  1871.  
  1872. ΓòÉΓòÉΓòÉ 14.5. VALUE ΓòÉΓòÉΓòÉ
  1873.  
  1874. The VALUE keyword is similiar to the VAR keyword except that VALUE can be used 
  1875. with Function returns and expressions whereas VAR needs to operate upon a 
  1876. variable's value (ie, you must supply a variable name as the source).  You need 
  1877. to put the WITH keyword after the source to be parsed (ie, before the token 
  1878. variable names). 
  1879.  
  1880. Tokens are broken off at blank spaces, unless you specify a different search 
  1881. string after a token variable name. 
  1882.  
  1883. Tokens can be thrown away by specifying a dot instead of token variable name. 
  1884.  
  1885. Tokens can be parsed by character position. 
  1886.  
  1887. Here we get the returned time from the TIME Function, and parse it apart at the 
  1888. colon characters into three token variables. 
  1889.  
  1890. /* Parse TIME into 3 tokens, broken at : */ 
  1891. PARSE VALUE TIME() WITH token.1 ':' token.2 ':' token.3 
  1892. DO i=1 TO 3 
  1893.   SAY "token."i "= '"token.i"'" 
  1894. END 
  1895.  
  1896.  
  1897. ΓòÉΓòÉΓòÉ 14.6. ARG ΓòÉΓòÉΓòÉ
  1898.  
  1899. The ARG keyword is used to retrieve arguments that the user typed on the OS/2 
  1900. command line when he started the script (ie, any text that he typed after the 
  1901. name of the REXX script). 
  1902.  
  1903. Tokens are broken off at blank spaces, unless you specify a different search 
  1904. string after a token variable name. 
  1905.  
  1906. Tokens can be thrown away by specifying a dot instead of token variable name. 
  1907.  
  1908. Tokens can be parsed by character position. 
  1909.  
  1910. The following script parses its arguments: 
  1911.  
  1912. /* Parse the arguments */ 
  1913. PARSE ARG token.1 token.2 token.3 token.4 . 
  1914. DO i=1 TO 4 
  1915.   SAY "Argument" i "is:" token.i 
  1916. END 
  1917.  
  1918. Run the above script from the OS/2 command line, and type "alpha beta gamma 
  1919. delta" after the script name.  The script should print out: 
  1920.  
  1921. Argument 1 is: alpha 
  1922. Argument 2 is: beta 
  1923. Argument 3 is: gamma 
  1924. Argument 4 is: delta 
  1925.  
  1926. The argument "alpha beta gamma delta" has been parsed into 4 tokens.  The 
  1927. tokens were split up at the spaces in the input.  If you experiment with the 
  1928. script, you should see that if you do not type 4 words as arguments, then the 
  1929. last tokens printed out are empty, and that if you type more than four words 
  1930. then the last token contains all the extra data.  Also, even if multiple spaces 
  1931. appear between the words, only the last token contains spaces. 
  1932.  
  1933. Replace PARSE with PARSE UPPER in the program.  Now, when you supply arguments, 
  1934. they will be tokenized as uppercase.  You can simply use ARG as an abbreviation 
  1935. for PARSE UPPER ARG, so for example, the following 2 lines are identical: 
  1936.  
  1937. PARSE UPPER ARG token.1 
  1938. ARG token.1 
  1939.  
  1940.  
  1941. ΓòÉΓòÉΓòÉ 14.7. SOURCE ΓòÉΓòÉΓòÉ
  1942.  
  1943. The SOURCE keyword parses information about how the script was invoked, and 
  1944. what the script's name is.  The source string contains the characters OS/2, 
  1945. followed by either COMMAND, FUNCTION, or SUBROUTINE, depending on whether the 
  1946. script was invoked as a host command (ie, directly launched by typing the name 
  1947. at an OS/2 command prompt, or launched by an OS/2 program that can start REXX 
  1948. scripts) or from a function call in an expression or using the CALL 
  1949. instruction.  These two strings are followed by the complete path specification 
  1950. of the script. 
  1951.  
  1952. Tokens are broken off at blank spaces, unless you specify a different search 
  1953. string after a token variable name. 
  1954.  
  1955. Tokens can be thrown away by specifying a dot instead of token variable name. 
  1956.  
  1957. Tokens can be parsed by character position. 
  1958.  
  1959. For example, if you start a script called "TEST.CMD" in the C:\OS2 directory, 
  1960. from an OS/2 command line, and the script contains this line: 
  1961.  
  1962. PARSE SOURCE token.1 token.2 token.3 
  1963.  
  1964. then token.1 is "OS/2", token.2 is "COMMAND", and token.3 is "C:\OS2\TEST.CMD". 
  1965.  
  1966.  
  1967. ΓòÉΓòÉΓòÉ 14.8. PULL ΓòÉΓòÉΓòÉ
  1968.  
  1969. The PULL keyword parses a line of text from the default input stream, which is 
  1970. usually the user entering text at an OS/2 command prompt.  (Actually, PULL 
  1971. first tries to remove the next data item in the script's data stack, and uses 
  1972. that for the source if there is an item there.  If no item is on the stack, 
  1973. then it reads from standard in, which is usually the keyboard.  The data stack 
  1974. will be discussed later). 
  1975.  
  1976. You can simply use PULL as an abbreviation for PARSE UPPER PULL, so for 
  1977. example, the following 2 lines are identical: 
  1978.  
  1979. PARSE UPPER PULL token.1 
  1980. PULL token.1 
  1981.  
  1982. If no line is available, the script will normally pause until a line is 
  1983. complete. 
  1984.  
  1985. To check if any lines are available in the default character input stream, use 
  1986. the built-in Function LINES. 
  1987.  
  1988. See also Data stack 
  1989.  
  1990.  
  1991. ΓòÉΓòÉΓòÉ 14.9. LINEIN ΓòÉΓòÉΓòÉ
  1992.  
  1993. The LINEIN keyword parses a line of text from the default input stream, which 
  1994. is usually the user entering text at an OS/2 command prompt.  (Unlike PULL, 
  1995. this doesn't first try to remove the next line in the script's data stack. 
  1996. Otherwise, functionality is the same). 
  1997.  
  1998. PARSE LINEIN is really just an abbreviation for PARSE VALUE LINEIN() WITH, the 
  1999. former being a lot easier to notate. 
  2000.  
  2001. If no line is available, the script will normally pause until a line is 
  2002. complete.  PARSE LINEIN should only be used when direct access to the character 
  2003. input stream is necessary.  Line-by-line input from the user should normally be 
  2004. done via the PULL (or PARSE PULL) instruction. 
  2005.  
  2006. To check if any lines are available in the default character input stream, use 
  2007. the built-in function LINES. 
  2008.  
  2009. Using PARSE LINEIN by itself (ie, without any token variable names after it) 
  2010. causes the next line to be removed from standard input, and discarded. 
  2011.  
  2012.  
  2013. ΓòÉΓòÉΓòÉ 14.10. VERSION ΓòÉΓòÉΓòÉ
  2014.  
  2015. The VERSION keyword parses information about the REXX language version\level 
  2016. and date of the interpreter.  This consists of five words (delimited by 
  2017. blanks): first the string "REXXSAA", then the language level (currently 
  2018. "4.00"), and finally the release date (currently "13 June 1989"). 
  2019.  
  2020. You should parse this information by words rather than by character position, 
  2021. as the language version\level could be different lengths for various versions. 
  2022.  
  2023.  
  2024. ΓòÉΓòÉΓòÉ 15. Terminating a REXX script ΓòÉΓòÉΓòÉ
  2025.  
  2026. If you wish to manually stop a running script (ie, tell the interpreter to 
  2027. abort), press the Control (Ctrl) and Break keys simultaneously.  That is, press 
  2028. and hold down the Ctrl key and then press the Break key once. 
  2029.  
  2030. A script can stop itself by executing the EXIT Instruction, which consists 
  2031. simply of the EXIT keyword.  An EXIT is implicitly understood to be at the 
  2032. bottom of a script (ie, when the interpreter gets to the last line in a script, 
  2033. it automatically ends the script after that last instruction, unless that 
  2034. instruction causes a jump back to some other instruction in the script such as 
  2035. END or SIGNAL).  So, you don't need the EXIT instruction at the bottom of a 
  2036. script, although it's OK to put one there. 
  2037.  
  2038. /* Terminate the script before the last line, if the user answers YES */ 
  2039. SAY "Do you want to terminate before printing the word 'Hello'?" 
  2040. PULL answer 
  2041. IF answer == "YES" THEN EXIT 
  2042. SAY "Hello" 
  2043.  
  2044. If you wish to return an error number or string to the OS/2 Command Line (or if 
  2045. the script was launched by another REXX script, return the error to that REXX 
  2046. script's RC variable), then simply place that error number or string after the 
  2047. EXIT keyword.  Usually, you return a 0 if the script has no errors.  (Not 
  2048. supplying any arg after EXIT tells the interpreter to assume a return of 0). 
  2049. Here, we return an error number of 30. 
  2050.  
  2051. EXIT 30 
  2052.  
  2053.  
  2054. ΓòÉΓòÉΓòÉ 16. Labels (ie, marking a place in your script), and jumping there ΓòÉΓòÉΓòÉ
  2055.  
  2056. A label is used to mark a place in your REXX script.  A label name can be any 
  2057. legal variable name.  In order to indicate a label, you put a colon : 
  2058. immediately after the label.  Here we have a label named RightHere, marking a 
  2059. SAY instruction. 
  2060.  
  2061. RightHere:  SAY "This instruction has a label" 
  2062.  
  2063. The label could optionally be put on a separate line (ie, above the instruction 
  2064. that it marks).  Also, the label may be indented. 
  2065.  
  2066. The SIGNAL instruction allows you to specify a label to jump to.  You specify 
  2067. the label name after the SIGNAL keyword.  The interpreter jumps to the 
  2068. instruction following that label, and resumes executing instructions at that 
  2069. place. 
  2070.  
  2071. /* Terminate the script before the last line, if the user answers YES */ 
  2072. SAY "Do you want to terminate before printing the word 'Hello'?" 
  2073. PULL answer 
  2074. IF answer == "YES" THEN SIGNAL Here 
  2075. SAY "Hello" 
  2076. Here: 
  2077. EXIT 
  2078.  
  2079. If you use SIGNAL within a loop or SELECT group, to jump to a label outside of 
  2080. that loop or SELECT group, then you effectively jump out of (ie, terminate) the 
  2081. loop or SELECT group itself. 
  2082.  
  2083. A common use of SIGNAL is to jump to an error handling routine when something 
  2084. goes wrong, so that the program can clean up and EXIT. 
  2085.  
  2086. Note:  Make sure that you don't name any variables the same as any labels in 
  2087.        your script.  Otherwise, the interpreter will always regard that name as 
  2088.        referring to the label rather than a variable, and perhaps cause an 
  2089.        error condition.
  2090.  
  2091.  
  2092. ΓòÉΓòÉΓòÉ 17. Error Trapping (ie, handling errors that the interpreter reports) ΓòÉΓòÉΓòÉ
  2093.  
  2094. There are certain error conditions which the interpreter recognizes.  The names 
  2095. of such error conditions are SYNTAX (ie, any error you made in notating your 
  2096. instructions such as putting the UPPER keyword before PARSE), ERROR (any error 
  2097. that a Function or subroutine or instruction or external program that you 
  2098. launch causes as a result of doing its work, such as LINEIN having a problem 
  2099. reading in the next line), FAILURE (some Functions in DLLs may cause failures 
  2100. instead of errors), HALT (when the user stops script execution by pressing CTRL 
  2101. and BREAK) and NOVALUE (when a variable is used without having been assigned a 
  2102. value).  The interpreter does default handling for each of these error 
  2103. conditions.  Sometimes, the default handling is to print a descriptive error 
  2104. message to the OS/2 command prompt window, and end the script (as with SYNTAX, 
  2105. ERROR, FAILURE, and HALT).  Sometimes, the default handling is to ignore 
  2106. instances of the error condition (as with NOVALUE). 
  2107.  
  2108. Besides jumping to a specific label, the SIGNAL instruction also allows you to 
  2109. replace a default error condition handling with your own REXX instructions. 
  2110. You can specify a label that the interpreter will automatically jump to if a 
  2111. certain error condition happens.  This is referring to "trapping an error 
  2112. condition". 
  2113.  
  2114. Error trapping for one of the above conditions is turned on by putting the 
  2115. keyword ON after SIGNAL, followed by the condition name.  By default, the label 
  2116. that the interpreter jumps to is the same as the condition name.  For example, 
  2117. assume you put the following line at the top of your script: 
  2118.  
  2119. SIGNAL ON SYNTAX 
  2120.  
  2121. Now, whenever the interpreter finds a syntax error in your script, the 
  2122. interpreter will try to jump to a label named SYNTAX somewhere in your script. 
  2123. Obviously, you should put that label somewhere in your script, probably before 
  2124. an EXIT instruction so that the script ends at that point.  For example, you 
  2125. may have these lines at the bottom of your script: 
  2126.  
  2127. SYNTAX: 
  2128.   SAY "Syntax error" 
  2129.   EXIT 
  2130.  
  2131. Note that the above routine does what the interpreter's default SYNTAX handling 
  2132. would do.  But, you could do something different, for example, maybe ask the 
  2133. user if he wants to continue with the script execution, and then jump (ie, 
  2134. SIGNAL) to some other part of the script. 
  2135.  
  2136. If you wanted to name your label something other than the same as the condition 
  2137. name, then you can put the NAME keyword followed by the desired label name. 
  2138. Here, we jump to the label MyError whenever a syntax error occurs. 
  2139.  
  2140. SIGNAL ON SYNTAX NAME MyError 
  2141.  
  2142. You can disable an error trap at any point by putting the keyword OFF after 
  2143. SIGNAL, followed by the condition name.  When the interpreter executes the 
  2144. following instruction, it no longer jumps to the SYNTAX label when it finds a 
  2145. syntax error.  Instead, it does its default handling for syntax error 
  2146. conditions. 
  2147.  
  2148. SIGNAL OFF SYNTAX 
  2149.  
  2150. You can turn trapping on and off at various places for a given error condition. 
  2151.  
  2152. Whenever a SIGNAL occurs, a special variable named SIGL is set to the line 
  2153. number of the instruction which caused the error condition.  If the signal was 
  2154. due to an ERROR trap, then the special variable RC will be set to the error 
  2155. number or message returned by the Instruction, Function, external program, or 
  2156. subroutine. 
  2157.  
  2158. Note:  SIGL and RC are variables that are created by the interpreter, which 
  2159.        assigns them values at certain points, as a result of script execution. 
  2160.        You should never name your own variables SIGL or RC, but may reference 
  2161.        these variables.  For example, after running an external program, you 
  2162.        can find out if it was successful by checking if RC is 0.  An RC value 
  2163.        of 0 usually means "success", whereas any other numeric value is an 
  2164.        error number.
  2165.  
  2166. /* This program goes on forever until the user stops it */ 
  2167. SAY " Press Control-C to halt" 
  2168. SIGNAL ON HALT 
  2169. DO i=1 
  2170.   SAY i 
  2171.   DO 10000 
  2172.   END 
  2173. END 
  2174. EXIT 
  2175.  
  2176. HALT: 
  2177.   SAY "Died at line" SIGL 
  2178.  
  2179. You can alternately use the CALL instruction followed by the keyword ON and the 
  2180. desired condition instead of SIGNAL ON.  For example: 
  2181.  
  2182. CALL ON SYNTAX NAME MyError 
  2183.  
  2184. The difference is that MyError should be a Subroutine that ends with RETURN. 
  2185. (Subroutines are discussed later).  When the interpreter encounters the RETURN, 
  2186. it resumes execution after the instruction which caused the error.  Using CALL 
  2187. ON therefore allows you to execute some error handling and then resume the 
  2188. script from where the error occurred. 
  2189.  
  2190.  
  2191. ΓòÉΓòÉΓòÉ 18. Writing Functions and Subroutines in REXX ΓòÉΓòÉΓòÉ
  2192.  
  2193. See the section Functions for a general discussion of Functions. 
  2194.  
  2195. You can write your own Functions in REXX, placing them in your script (or 
  2196. putting them in a separate script that you call from your script).  To identify 
  2197. a Function in your script, you need to put a label at the start of it.  The 
  2198. following script contains an internal Function named square, and calls it with 
  2199. some data (ie, passes it 1 argument).  This Function simply squares that 
  2200. argument and returns the result as its value. 
  2201.  
  2202. /* Call the Function square() with an arg, and print the Function's returned 
  2203. value */ 
  2204. SAY "The results are:" square(3) square(5) square(9) 
  2205. EXIT 
  2206.  
  2207. square: /* here's a function to square its argument */ 
  2208.   PARSE ARG myarg 
  2209.   RETURN myarg*myarg 
  2210.  
  2211. The output of this script is: "The results are: 9 25 81". 
  2212.  
  2213. Remember that a Function is called by typing its name, immediately followed by 
  2214. a (, then any passed args, and finally a closing ).  A Function should also 
  2215. return a value. 
  2216.  
  2217. When the interpreter encounters the Function call square(3), it searches the 
  2218. script for a label called "square".  It finds that label on line 5 in the above 
  2219. example.  The interpreter then executes the instructions starting at that line, 
  2220. until it encounters a RETURN instruction, whereupon it resumes executing the 
  2221. instruction that originally called the Function, replacing that Function call 
  2222. with the returned value (ie, square(3) gets replaced by its returned value of 
  2223. 9, and that's what the SAY instruction displays). 
  2224.  
  2225. Note:  The EXIT instruction in the above script causes the interpreter to 
  2226.        finish executing at that line instead of running down into the Function. 
  2227.        It's important to make sure that you don't let the interpreter 
  2228.        accidentally drop down into Functions at the bottom of your script. 
  2229.        It's best to put all your Functions at the bottom of the script, and 
  2230.        place one EXIT above them all.  Note that a Function can never 
  2231.        accidentally drop down into another Function below it as long as it ends 
  2232.        with RETURN, since RETURN jumps back to the instruction that originally 
  2233.        called the Function.
  2234.  
  2235. While that Function is being executed, the arguments to the Function can be 
  2236. determined with PARSE ARG in the same way as the arguments to a script.  In the 
  2237. above example, we parse the argument passed to square() into a variable named 
  2238. myarg.  So, for the call square(3), myarg is assigned the value 3. 
  2239.  
  2240. When the RETURN instruction is reached, the expression specified after RETURN 
  2241. is evaluated and used as the return value of the Function.  The expression can 
  2242. be a variable's value, mathematical expression, or even the return from another 
  2243. Function. 
  2244.  
  2245. You can have more than one RETURN instruction in a Function, each returning a 
  2246. different value.  But, the interpreter always jumps out of a Function 
  2247. immediately when it encounters a RETURN, and returns to the instruction that 
  2248. called the Function.  Here we have two ways out of the Function answer(), plus 
  2249. two different possible return values: 
  2250.  
  2251. answer: /* here's a Function that returns 1 if the user answers "YES", or 0 if 
  2252. he answers anything else */ 
  2253.   SAY "Do you want to learn REXX programming?" 
  2254.   PARSE PULL ans 
  2255.   IF ans == "YES" THEN RETURN 1 
  2256.   RETURN 0 
  2257.  
  2258. A Function can take multiple arguments, which are each separated with a comma, 
  2259. as so: 
  2260.  
  2261. /* Call a Function with 3 arguments */ 
  2262. SAY "The results are:" condition(5,"Yes","No") condition(10,"X","Y") 
  2263. EXIT 
  2264.  
  2265. condition: /* If the first argument is less than 10, return the second, else 
  2266. return the third. */ 
  2267.   PARSE ARG c,x,y 
  2268.   IF c<10 THEN RETURN x 
  2269.   ELSE RETURN y 
  2270.  
  2271. A Subroutine is similar to a Function, except that it need not return a value 
  2272. (ie, supply a value after the RETURN keyword).  It is called with the CALL 
  2273. instruction.  You do not place a ( and ) after the Subroutine name.  Any args 
  2274. passed to the Subroutine are listed after the Subroutine name, and are not 
  2275. separated by commas (and therefore, the arguments are seen as one long string. 
  2276. If you want to tokenize it, you'll have to fetch the args into one variable 
  2277. using PARSE ARG, and then use a PARSE VAR to break up the string into separate 
  2278. pieces). 
  2279.  
  2280. /* Call a Subroutine named box to print a string in a box */ 
  2281. CALL box "This is a sentence in a box" 
  2282. CALL box "Is this a question in a box?" 
  2283. EXIT 
  2284.  
  2285. box: /* Print the argument in a box */ 
  2286.   PARSE ARG text 
  2287.   SAY "+--------------------------------+" 
  2288.   SAY "|"CENTRE(text,32)"|"       /* centre the text in the box */ 
  2289.   SAY "+--------------------------------+" 
  2290.   RETURN 
  2291.  
  2292. If you do choose to return a value from a subroutine (ie, put some expression 
  2293. after the RETURN keyword), the interpreter stores this value in the special 
  2294. variable named RESULT.  You can't consider a Subroutine itself to directly 
  2295. return a value like a Function does.  For example, consider the following call 
  2296. to Subroutine box, and assume that box's RETURN instruction returns a value 
  2297. string of "done": 
  2298.  
  2299. SAY box "an argument" 
  2300.  
  2301. This will not print "done".  Rather, it will simply print "BOX an argument". 
  2302. First of all, the interpreter doesn't recognize box as a Subroutine name 
  2303. because the CALL keyword has been omitted, so box is never even called.  The 
  2304. interpreter thinks that box is a variable name, and since it hasn't been 
  2305. assigned a value, it defaults to its name uppercased.  Even if you put the CALL 
  2306. keyword before box, that wouldn't result in box being called.  The interpreter 
  2307. would misinterpret CALL as the name of another variable, as the CALL keyword 
  2308. can't be part of a SAY instruction, and "CALL BOX an argument" would be 
  2309. printed. 
  2310.  
  2311. It is possible to call a Function, even a built-in Function, as if it were a 
  2312. Subroutine (ie, no parentheses around args, and it doesn't directly return a 
  2313. value).  You need to use the CALL instruction to actually call the Function. 
  2314. The value returned by the Function is placed into the special variable named 
  2315. RESULT, just like with a Subroutine.  (Optionally, you can still use 
  2316. parentheses and args separated by commas). 
  2317.  
  2318. /* Print the time, using the CALL instruction */ 
  2319. CALL TIME "CIVIL" 
  2320. SAY RESULT 
  2321.  
  2322.  
  2323. ΓòÉΓòÉΓòÉ 18.1. PROCEDURE (ie, different set of variables for a Function versus the rest of the script) ΓòÉΓòÉΓòÉ
  2324.  
  2325. If a Function (or Subroutine) does not need to use the variables which the rest 
  2326. of the script creates, or if the Function uses variables which the rest of the 
  2327. script does not need to access, then you can start the Function with the 
  2328. PROCEDURE instruction.  This clears all the existing variables away out of 
  2329. sight, and prepares for a new set of variables.  This new set will be destroyed 
  2330. when the Function returns.  The advantage to this is that it ensures that the 
  2331. Function won't ever alter the value of any variable used by the rest of your 
  2332. script, even if the Function creates a variable with the same name as one used 
  2333. elsewhere in your script (ie, the variable in the Function belongs to an 
  2334. entirely different set of variables than the one with the same name elsewhere). 
  2335. Likewise, if a Function calls another Function which contains the PROCEDURE 
  2336. instruction, that second Function won't alter the values of any variables used 
  2337. by the first Function.  So, PROCEDURE is a way to protect variables from being 
  2338. inadvertently altered by calls to Functions or Subroutines. 
  2339.  
  2340. The following script calculates the factorial of a number recursively. 
  2341. PROCEDURE makes recursion possible and easy. 
  2342.  
  2343. /* Calculate factorial x, that is, 1*2*3* ... *x  */ 
  2344. SAY "Enter a number" 
  2345. PARSE PULL num . 
  2346. SAY num"!="factorial(num) 
  2347. EXIT 
  2348.  
  2349. factorial: /* calculate the factorial of the argument */ 
  2350.   PROCEDURE 
  2351.   PARSE ARG num 
  2352.   IF num<3 THEN RETURN num 
  2353.   ELSE RETURN factorial(num-1) * p 
  2354.  
  2355. First of all, the num variable initially passed to factorial is not the same 
  2356. num variable used within factorial (ie, in the PARSE ARG instruction) due to 
  2357. the PROCEDURE instruction.  So, that PARSE ARG isn't altering the original num 
  2358. variable, but rather, creating a new variable named num.  Furthermore, that 
  2359. second num variable is then passed to factorial again.  (ie, factorial calls 
  2360. itself when it goes to return a value).  When factorial is called again, it 
  2361. creates yet another num variable to be used up until that nested call returns. 
  2362.  
  2363. If the Subroutine or Function needs access to just a few variables used 
  2364. elsewhere in the script, but wants to protect all other variables, then put the 
  2365. EXPOSE keyword after PROCEDURE, followed by any variable names that you don't 
  2366. want hidden away.  In this way, your Function can alter the values of 
  2367. particular variables used elsewhere in the script, while also protecting other 
  2368. variables.  Consider the following: 
  2369.  
  2370. /* Assign values to variables First and Second */ 
  2371. First = 0 
  2372. Second = 0 
  2373. /* Call Function alter */ 
  2374. CALL alter() 
  2375. SAY "First =" First", Second =" Second 
  2376. EXIT 
  2377.  
  2378. alter: 
  2379.   PROCEDURE EXPOSE First /* don't protect the variable First */ 
  2380.   First = 1 
  2381.   Second = 1 
  2382.   RETURN 0 
  2383.  
  2384. The above prints out "First = 1, Second = 0".  Note that the alter Function was 
  2385. able to change the value of First used in the SAY command, but not the value of 
  2386. Second.  That's because the Second variable that alter changes is an entirely 
  2387. different variable than the Second variable used elsewhere in the script.  On 
  2388. the other hand, the First variable used within alter is the very same one used 
  2389. elsewhere. 
  2390.  
  2391.  
  2392. ΓòÉΓòÉΓòÉ 18.2. External REXX Functions (ie, calling Functions within another REXX script) ΓòÉΓòÉΓòÉ
  2393.  
  2394. You can write Functions and Subroutines which are not contained in the same 
  2395. REXX script.  In order to do this, write the Function and save it as a separate 
  2396. file (with a .cmd extension on the filename).  This type of Function is called 
  2397. an "external" Function, as opposed to an "internal" Function which can be found 
  2398. inside the currently running script. 
  2399.  
  2400. For example, If you want to call your Function as "foobar()" (or Subroutine as 
  2401. "CALL foobar"), then you should save it in a file named "foobar.cmd" which can 
  2402. be found in the current directory or in your path. 
  2403.  
  2404. The PROCEDURE instruction is automatically executed before running your 
  2405. external Function, and so it should not be placed at the start of the Function. 
  2406. It is not possible for an external Function to access any of its calling 
  2407. script's variables, except by the passing of arguments (which the external 
  2408. Function accesses via PARSE ARG) or by data items which the calling script 
  2409. pushes onto the second script's data stack. 
  2410.  
  2411. For returning from external Functions, as well as the RETURN instruction, there 
  2412. is EXIT.  The EXIT instruction may be used to return any data to the calling 
  2413. script in the same way as RETURN, but EXIT can be used to return to the calling 
  2414. script even when it is used inside of some Subroutine within the external 
  2415. Function itself (ie, EXIT can be used to break out of nested or recursive 
  2416. calls, and immediately return to the calling script). 
  2417.  
  2418.  
  2419. ΓòÉΓòÉΓòÉ 19. Data stack (ie, PUSHing, QUEUEing, and PULLing) ΓòÉΓòÉΓòÉ
  2420.  
  2421. Each script has a data stack, which is accessed via the PUSH, QUEUE, and PULL 
  2422. (ie, PARSE PULL) instructions.  The PULL instruction can retrieve data (typed 
  2423. within an OS/2 command prompt window) from the user as we have seen before. 
  2424. But, if there is some data on the stack then PULL will retrieve that instead. 
  2425. QUEUE and PUSH can be used to place a data item onto the stack (to be 
  2426. subsequently retrieved via PULL).  PULL actually removes the data item from the 
  2427. stack, and places it into whatever variable you specify.  Here we PUSH or QUEUE 
  2428. data items, and PULL them. 
  2429.  
  2430. /* Access the stack */ 
  2431. QUEUE "Hello!" 
  2432. PARSE PULL answer   /* answer contains "Hello!" */ 
  2433. PARSE PULL answer2  /* PARSE PULL gets input from the user now since there's no 
  2434. data on the stack */ 
  2435. PUSH "67890" 
  2436. PUSH "12345" 
  2437. PARSE PULL answer3  /* answer3 contains "12345" */ 
  2438. /* There is one item left on the stack, "67890" */ 
  2439.  
  2440. The difference between PUSH and QUEUE is that when the items are pulled off the 
  2441. stack, the items which were queued appear in the same order that they were 
  2442. queued (FIFO, or first in, first out), and the items which were pushed appear 
  2443. in reverse order (LIFO, or last in, first out).  In other words, if you QUEUE 
  2444. five items, the order that they get pulled out is items 1, 2, 3, 4, 5.  If you 
  2445. instead PUSH those five items, the order that they get pulled out is items 5, 
  2446. 4, 3, 2, 1. 
  2447.  
  2448. Using PULL (or PARSE PULL) by itself (ie, without any token variable names 
  2449. after it) causes the next item to be removed from the data stack, and 
  2450. discarded. 
  2451.  
  2452.  
  2453. ΓòÉΓòÉΓòÉ 20. Running executables and OS/2 commands ΓòÉΓòÉΓòÉ
  2454.  
  2455. A REXX script can run any executable (ie, a program written in another 
  2456. language), including MS-DOS and Windows programs.  For example, a REXX script 
  2457. can run OS/2's DISKCOPY.COM program, and even receive back an error code 
  2458. telling whether DISKCOPY performed its operation successfully. 
  2459.  
  2460. When the interpreter encounters an instruction which doesn't begin with a 
  2461. recognizable keyword, or isn't a variable assignment, it treats that line as a 
  2462. string expression which is to be evaluated and passed to the environment.  The 
  2463. default environment for scripts launched from a command prompt or desktop 
  2464. object is an OS/2 command prompt.  So in effect, the interpreter ships off that 
  2465. line as if the user had typed it at an OS/2 command prompt.  Therefore, if the 
  2466. line is: 
  2467.  
  2468. del '*.*' 
  2469.  
  2470. The interpreter doesn't recognize "del" as a keyword (such as CALL, SAY, IF, 
  2471. etc).  Neither does it regard it as a call to a Function because there is no ( 
  2472. after del.  It also doesn't regard this as an assignment because there is no = 
  2473. after del.  So, the interpreter decides to pass the line to the OS/2 Command 
  2474. Prompt.  But first, the interpreter evaluates the line.  It sees that del is 
  2475. not in quotes, so it assumes that del is a variable name.  It fetches the value 
  2476. of del, which if del has not been assigned a value defaults to "DEL".  Then, it 
  2477. sees the literal string '*.*'.  It removes the outside quotes.  (When 
  2478. evaluating literal strings, the outside quotes are always removed by the 
  2479. interpreter before it sends the literal string off to some environment.  If you 
  2480. actually wanted a pair of quotes, you'd have to double-quote the string so that 
  2481. after the interpreter removed the outside pair, one pair would still remain). 
  2482. So, the actual text that gets passed to the OS/2 command prompt is DEL *.*. 
  2483. The net result is that the OS/2 command prompt uses the OS/2 del command to 
  2484. delete all files in the current directory. 
  2485.  
  2486. In fact, it's best to quote the del too, since you literally want that text 
  2487. passed to the OS/2 command prompt.  You don't want the interpreter to regard 
  2488. del as a variable name and possibly replace it with some value that isn't what 
  2489. you want passed to the OS/2 Command Prompt. 
  2490.  
  2491. 'del *.*' 
  2492.  
  2493. In the above, the interpreter doesn't regard del as a variable when evaluating 
  2494. the line.  del is simply part of the literal string. 
  2495.  
  2496. Of course, you could use a variable's value to specify the desired program name 
  2497. to execute.  In this case, we want the interpreter to recognize command as a 
  2498. variable name and replace with its value (ie, 'del'). 
  2499.  
  2500. command = 'del' 
  2501. command '*.*' 
  2502.  
  2503. The interpreter suspends your REXX script (on that instruction that launched 
  2504. the other program) while that program is running.  When the OS/2 command prompt 
  2505. (ie, shell) finishes running the specified executable, it returns (to the 
  2506. interpreter) whatever value that executable returned.  (Most executables return 
  2507. a 0 if they execute successfully.  This is particularly true of the standard 
  2508. OS/2 commands such as del, copy, etc).  The interpreter puts this value in the 
  2509. special variable RC and resumes executation of your script.  So, you can often 
  2510. check the RC variable to see if the executable did its job successfully. 
  2511.  
  2512. 'del *.*' 
  2513. IF RC = 0 THEN SAY "It worked" 
  2514. ELSE SAY "It didn't work" 
  2515.  
  2516. The OS/2 shell has a START command which causes the launched program to be 
  2517. started up as a separate process.  In this case, control is returned to your 
  2518. REXX script immediately upon launch of the other program.  Your REXX script 
  2519. doesn't have to wait for that other program to terminate before it can proceed 
  2520. doing other things.  Your script continues executing WHILE the other program is 
  2521. also executing.  In this case, you won't be able to get an error code (returned 
  2522. in RC) from the other program when it terminates.  Here we launch a program 
  2523. called BLORT.EXE: 
  2524.  
  2525. 'start blort.exe' 
  2526.  
  2527.  
  2528. ΓòÉΓòÉΓòÉ 21. INTERPRET ΓòÉΓòÉΓòÉ
  2529.  
  2530. Suppose you have a variable named inst which contains the string "var=var+1" 
  2531. (ie, that's its value).  You can execute that string as an instruction, by 
  2532. typing: 
  2533.  
  2534. INTERPRET inst 
  2535.  
  2536. Therefore, the variable named var is now incremented. 
  2537.  
  2538. The INTERPRET instruction may be used to execute a Rexx instruction entered by 
  2539. the user, or to assign values to variables whose names are not known in 
  2540. advance. 
  2541.  
  2542. /* Get the desired name of a variable from the user, and set that variable to 
  2543. 42 */ 
  2544. PARSE PULL var 
  2545. INTERPRET var "=" 42 
  2546.  
  2547.  
  2548. ΓòÉΓòÉΓòÉ 22. Tracing (ie, debugging) ΓòÉΓòÉΓòÉ
  2549.  
  2550. If a program goes wrong and you need more information in order to work out why, 
  2551. the interpreter provides you with the ability to trace all or part of your 
  2552. script to see what is happening. 
  2553.  
  2554. The most common form of tracing is turned on by using the TRACE instruction 
  2555. with an argument of R. 
  2556.  
  2557. TRACE R 
  2558.  
  2559. This causes each instruction to be listed before it is executed. Also, it 
  2560. displays the results of each calculation after it has been found. 
  2561.  
  2562. Another useful trace instruction is: 
  2563.  
  2564. TRACE ?A 
  2565.  
  2566. This makes the interpreter list each instruction and stop before it is 
  2567. executed.  You can execute the instruction by pressing return, or you can type 
  2568. in some instruction to be interpreted, after which the interpreter will pause 
  2569. again.  You can use this to examine the value of the script's variables (by 
  2570. issuing a SAY instruction with the names of variables whose values you wish to 
  2571. display) and so forth. 
  2572.  
  2573. If you want the interpreter to stop only when passing a label, use: 
  2574.  
  2575. TRACE ?L 
  2576.  
  2577. This is useful for setting breakpoints in the script, or for making the script 
  2578. stop at entry to a Function or Subroutine. 
  2579.  
  2580.  
  2581. ΓòÉΓòÉΓòÉ 23. More helpful error messages ΓòÉΓòÉΓòÉ
  2582.  
  2583. The OS/2 Command Prompt can supply helpful descriptive messages about 
  2584. particular errors you may see the interpreter display.  For example, suppose 
  2585. that the interpreter ends a script (named C:\OS2\MYSCRIPT.CMD) with the 
  2586. following error message: 
  2587.  
  2588.   6+++ SAY "The sum of the two numbers is" num1 & num2 
  2589. REX0034: Error 34 running C:\OS2\MYSCRIPT.CMD,line 6:logical value not 0 or 1 
  2590.  
  2591. The first line of this error message is the actual instruction in your script 
  2592. that caused the error.  It is usually prefaced with the line number. 
  2593. (Unfortunately, the interpreter doesn't count comments and blank lines, so when 
  2594. you look for that line number in your script, remember to skip such).  The 
  2595. second line starts with an error number (which I've shown in color).  Then, the 
  2596. name of the script is shown, the line number where the error occurred, and a 
  2597. description of the error.  If this description is not enough, go to a Command 
  2598. Prompt window, and issue the HELP command followed by that error number. 
  2599.  
  2600. HELP REX0034 
  2601.  
  2602. This will display a more descriptive message as so: 
  2603.  
  2604. REX0034 ***Logical Value not 0 or 1*** 
  2605.  
  2606. Explanation: The expression in an IF, WHEN, DO WHILE, or DO UNTIL phrase must 
  2607. result in a '0' or a '1', as must any term operated on by a logical operator.