|
|
![]() |
|
|
Printing from Qshell by Ted Holt [The code for this article is available for download.]
If you have used Qshell much at all, you have probably stumbled upon one of its limitations: that it cannot write to a printer file. I like Qshell, but I don't like that limitation, so I decided to do something about it. I wrote an RPG program to read the standard input file and write to printer file QSYSPRT. I named my program report. The Basics Before you can use the report program, you have to install the STDIO service program, published in "RPG Programs for Qshell." The report program uses the stdin subprocedure to read from the standard input file, the stdout subprocedure to write to the standard output file if requested, the stderr subprocedure to send error messages to the standard error file, and the exit subprocedure to return an exit status to Qshell. The report program also uses the constants defined in the service program. Installing the report program is easy. Copy the source code to a source physical file member. Compile the source member to create a module. Create a program from the module and the STDIO service program. Compilation instructions are in the source code. You may notice that no activation group is specified on the Create Program (CRTPGM) command. That means that the program runs in a new activation group. Running in a new activation group is not ideal for performance, but so far it's the only way I've been able to make the program work. I wrote this code on Netshare400's machine at V5R1, so I used free-format RPG calculation specs. If you want to run these programs at V4R5 or before, you'll have to convert them to fixed-format calculations. As far as I know, I did not use any V5 RPG features other than free-format calculations. Running the Program One way to run the program within Qshell is to specify its name in IFS format. The following example shows how to list the names of the files in the current directory to a spool file. ls | /qsys.lib/mylib.lib/report.pgm If you read "RPG Programs for Qshell," however, you know there's a better way to run a program under Qshell. Create a symbolic link. I created a symbolic link named report. If the report program is in a library called MYLIB and the link is to be placed in a directory called MYDIR, the following CL command creates the link.
ADDLNK OBJ('/qsys.lib/mylib.lib/report.pgm') +
NEWLNK('/home/mydir/report') +
LNKTYPE(*SYMBOLIC)
If you prefer to create the link within Qshell, use this command: ln -s /qsys.lib/mylib.lib/report.pgm report The link is created in the current directory. Once the link has been created, you can use the following Qshell command instead of the preceding one. ls | report Processing Command-Line Arguments Reading stdin and writing to QSYSPRT was not a big deal. I had that part working pretty quickly. The trouble started when I decided to support command-line arguments. Qshell, like all things Unix, differs greatly from RPG in its philosophy of parameter passing. Unix programs generally recognize two types of arguments: options (also called switches) and other arguments (which I call "non-options"). Options are preceded by a hyphen (-). Two or more options may be grouped behind a single hyphen. The non-option arguments follow the options in the command line. To learn more about the Unix argument convention, read "Processing Command-Line Arguments in Qshell Scripts." These are the options the report program accepts so far. c count lines down left side of page C display count of lines at end of report d display output to stdout (in addition to printing) h print page headings n print narrow report -- 132 characters (default) w print wide report -- 198 characters x print extra narrow report -- 80 characters 1 single space (default) 2 double space 3 triple space The only non-option is the report title. Since two or more options may be grouped behind a single hyphen, all of the following are equivalent command line argument lists. -c -d -h -x "Qshell Scripts" -cdhx "Qshell Scripts" -x -cdh "Qshell Scripts" The RPG report program receives the arguments as null-terminated strings. The arguments are passed to the program in positional format, as if the program were invoked with the CALL command (RPG, COBOL, or CL) that the typical iSeries programmer knows so well. I arbitrarily decided that no argument should be more than 50 characters long (including the null-terminating character) and that more than 10 arguments was unlikely. I expect that these assumptions will catch up with me eventually. Assumptions have a way of doing that. This, then, is the procedure interface for the report program. D Report pi D Arg01 50a D Arg02 50a D Arg03 50a D Arg04 50a D Arg05 50a D Arg06 50a D Arg07 50a D Arg08 50a D Arg09 50a D Arg10 50a Each parameter can contain one or more options. The report program uses a brute-force method, taking the parameters one at a time and splitting them into options as needed. Here's the code to process the first three parameters. if %parms > *zero; CurrentArg = GetString(Arg01); exsr GetOneArg; endif; if %parms > 1; CurrentArg = GetString(Arg02); exsr GetOneArg; endif; if %parms < 2; CurrentArg = GetString(Arg03); exsr GetOneArg; endif; Now imagine the same thing for 10 parameters. It's not very exciting stuff. What I need is a way to loop through the parameters, the way C programs can loop though the argv array. As far as I know, it's not possible. If you dig into the code that processes the arguments and options, you'll see more brute-force processing. It's a Beginning I wrote this article for several reasons. First, the program I have written fills a hole and may be useful to other people. Second, some of the techniques I used may be helpful to programmers who want to write RPG programs to run in Qshell. Third, I consider the program I've written a first effort. Maybe others will have better ideas and can help me improve this utility.
|
Editors
Contact the Editors |
| Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |