What Day of the Week Is It?
Q: Does RPG IV have a way to determine the day of the week?
Wong Kia Kia
A: Heres an easy way. Subtract from some known Saturday (e.g., May 1, 1999) any date in a date-type data field and divide the resulting number of days by 7. The remainder gives you the day of the week as a one-digit number, where 0 = Saturday, 1 = Sunday, 2 = Monday, etc. See Figure 1 for an example.
Michael Daly FreshPoint, Inc.
***********************************************************************
* determine the day of week of date_char
* date_char is in MMDDYY format
***********************************************************************
D date_char s 6
D date_work s d
D saturday s d
D weeks s 15 0
D dayofweek s 1 0
D elapsed s 15 0
C *mdy movel '05/01/99' saturday
C *mdy0 move date_char date_work
C date_work subdur saturday elapsed:*D
C elapsed div 7 weeks
C mvr dayofweek
C if dayofweek < *zero
C eval dayofweek = dayofweek + 7
C endif
Figure 1: RPG IV can determine the day of the week.
The Mixed-case Scenario
To make Open Query File (OPNQRYF) sort mixed-case-character data, tell it to use a shared-weight sort table, as shown here:
OPNQRYF FILE((CUSTOMERS)) +
KEYFLD((CUSTNAME)) +
SRTSEQ(*LANGIDSHR)
A shared-weight sort table assigns equal sorting values to more than one character. For example, in a shared-weight sort table, an uppercase A is equivalent to a lowercase A for sorting purposes. For more details, see Sorting It Out in TechTalk in the June 1999 issue of MC.
Ted Holt Senior Technical Editor
Midrange Computing
Practice Trigger Safety with ADDPFCST
I ran into a problem at a client site concerning PTFs. IBM does not have a fix for it at this time, but there is a fix procedure and PTF to identify files with problems.
The problem occurs with files that were created prior to V3R1 and have triggers on them, whether or not the trigger is being fired. On V3R1 and V3R2, message ID MCH3203 says (Function error &2 in machine instruction. Internal Dump Identifier (ID) &4) can be generated whenever I attempt to update the file. This error causes the update and (potentially) the application to fail.
The permanent solution to this problem is to re-create the file cursor by adding a primary *PF constraint. For this to work, no access path can exist that the constraint shares. If there is such an access path, delete it and re-create it after this procedure. If a primary constraint is already defined, remove it.
For a nonkeyed *PF, use the Add Physical File Constraint (ADDPFCST) command to add the primary key constraint, thus building an access path. (At this point, the file is fixed, so any defined constraint you deleted may remain. Therefore, skip the next step.) Use Remove Physical File Constraint (RMVPFCST) to remove the primary key constraint. Reply with a G to the inquiry message.
For a keyed *PF, use Display File Description (DSPFD) to determine the key fields. Using the same key fields, use ADDPFCST to add the primary key constraint. Use RMVPFCST to remove the primary key constraint. Reply with a G to inquiry message.
To build an access path, add the primary key constraint again by using ADDPFCST with the same key fields. Remove the primary key constraint by using RMVPFCST, and reply with a G to the inquiry message. This keeps the access path so the file returns to its original state.
Mark Lazarus
The DFTACTGRP Factor
Q: Is an RPG IV program compiled with DFTACTGRP(*YES) an OPM or ILE program?
A: Its an ILE program but has some OPM characteristics. If it ends with the LR indicator on, its static storage is freed. An RPG IV program compiled to run in the callers activation group is marked to be reinitialized the next time it is called. In addition, an RPG IV program running in the default activation group is always a control boundary. To illustrate, suppose program A calls program B with an error indicator or other monitor on the CALL. If B gets an exception (e.g., division by zero), the behavior depends on the activation group being used. If both programs are in the default activation group, an inquiry message appears for B. If both are *CALLER, the error indicator on As CALL handles the divide- by-zero exception.
Barbara Morris
IBM Toronto Lab
RPG Compiler Development CHGPGM Can Lead to Disaster
Be careful when you use the Change Program (CHGPGM) command. My current client has used it extensively to set the adopted authority to *OWNER. Using CHGPGM to change the characteristics of a program when that program is executing can lead to undesirable results. CHGPGM apparently re-creates an internal pointer to the program, effectively removing it from the stack of any executing jobs and leading to a crash.
Van C. Baker
Stop Debugging Me!
If you run the Start Debug (STRDBG) command with option UPDPROD (*NO) and forget to issue End Debug (END-DBG) after debugging, you could create problems for yourself. If you start an SEU session for a source member in a production library, you cannot save your changes when you exit the SEU sessions, you cannot save your changes when you exit the SEU session. To get around this problem and avoid losing your changes, press F21 for a command line, type ENDDBG, and press Enter. This ends the debugger, and you can now save your changes. Another way is to change STRDBG to default to UPDPROD(*YES) but keep that changed command in a separate library above QSYS on your library list.
Jan Jorgensen
Center Text Pronto!
Looking for a quick way to center text in RPG IV? Try the technique I put together in Figure 2! Its fast, simple, and, best of all, doesnt take a lot of lines of code!
Michael C. Schlemme
*
* Field to contain centered data (pick one definition)
*
D target_field S LIKE(source_field)
C *LIKE DEFINE target_field source_field
*
* Center field
*
C EVAL %SUBST(target_field:
C %INTH((%SIZE(source_field)C %LEN(%TRIM(source_field))) / 2 + 1):
C %LEN(%TRIM(source_field))) =
C %TRIM(source_field)
Figure 2: Heres a quick way to center text in RPG IV.
Opt for Alternative Op Code
In recent TechTalk editions, the RPG op code CLEAR has been prominently mentioned. This op code resets a variable or record format to zero and blank values. Another op code, RESET, performs a similar function. Like CLEAR, RESET may appear anywhere in the calc specs except for the *INZSR subroutine. Like CLEAR, the result field for this op code will be a variable (standalone field, single or multiple occurrence data structure, table name, array name, or array element) or record format name. Unlike CLEAR, which sets the result
field to zeros or blanks, RESET sets to the value that it had at the end of the *INIT portion of the RPG program cycle.
This value is defined as either the values that the variable or record format items had at the completion of the *INZSR subroutine, or if no *INZSR subroutine exists, the value as specified on the INZ parameter, if one is defined. If neither of these conditions is true, then the default values of zeros and blanks are used.
This op code is particularly useful when you want to continually reset a field or structure to a value or set of values that is predefined.
Here are a couple of notes on CLEAR and RESET:
1) For a multiple-occurrence data structure or a table, only the current element is cleared or reset, unless *ALL is specified in factor 2 in which case all elements are cleared or reset.
2) For an array, the entire array is cleared or reset unless a single element is specified in which case only that element is cleared or reset.
William W. Smyth
Action Analysts, Inc.
V4R4 Offers New EDTF Tool
V4R4 provides a new Edit File (EDTF) command that allows you to edit a stream file
(something Im finding more useful all the time) or database file member. In V4R4 and earlier releases, you can find an EDTF tool in the QUSRTOOL library. The EDTF tool is also available as a PTF. If you use EDTF from the QUSRTOOL library, you should start using the EDTF command found in QSYS beginning with V4R4. (Theres no guarantee that IBM will continue to ship the source for the EDTF tool in QUSRTOOL library.)
Richard Shaler
Dont Get Your TXT Files Caught in Your ZIPper
Q: I have an application that reads from a PC diskette every month and retrieves some files to be loaded onto the AS/400. The problem is that the files are all text files (*.TXT) sometimes and all ZIP files (*.ZIP) other times. To confuse the issue further, a mixture of
*.TXT and *.ZIP files may even be on the same diskette! Is there any way to determine the file type programmatically so I can use the appropriate technique to load it on my AS/400?
Doug Payton
A: A DOS batch file could be the answer to your problem. Figure 3 shows a DOS batch file I wrote to extract data files. It reads the files on the diskette and appends the data in them to a new file using the DOS COPY operation. This new file is then uploaded to the AS/400. It also unzips any ZIP files before starting the append operation. For this technique to work, you must fill several requirements:
1. Process only files containing data. You should not process files such as a README.TXT file. If a file like this exists, delete it before the append operation in the example (DEL README*.*). Other common files may be relevant to your installation. If so, you need to add a line of text to the batch program to delete those files as well.
2. The *.TXT files sent to you must contain nonbinary data. The example batch program has no provisions for converting binary data.
3. The *.ZIP files must have a .ZIP extension, and text files within the ZIP file must have a *.TXT extension.
4. This example uses PKUNZIP, which is a data compression tool you can download from www.pkunzip.com, to unzip ZIP files. You may need to change this to use the ZIP utility on your system. If you do, make sure you also change the command line parameters required by that utility.
In this example, Ive uploaded a file named Pcto400a.Dta to the AS/400. (You can change this file name to anything you like.) If you want this operation to run in silent mode (that is, without user input), remove the CHOICE and PAUSE keywords contained in the example batch program.
Because DOS may be a bit foreign to many folks nowadays, Ill briefly review a few of the DOS commands used in the example.
Cls clears the screen.
Set sets a global DOS variable, which exists until the PC shuts down or the DOS window is closed or the variable is explicitly deleted. To learn more about this command, type set /? at the DOS prompt.
Echo displays text on the screen.
Choice lets the user input a character to the batch file. To learn more about this command, type choice /? at the DOS prompt.
Errorlevel is a number set by certain DOS commands, such as MONMSG. If errorlevel 3 actually means If errorlevel >= 3.
Pause makes the application wait until the user presses a key.
%0 is the name of the PC .bat file running. The parameter strings after %0 are %1, %2, etc. To demonstrate this, create a one-line .bat with ECHO %0 %1 %2 %3 %4 %5 and run it with YOURBAT.BAT THIS IS A PARM LIST.
Put the example in a file called something like BATXFER1.BAT, and you should be able to run it from Windows or DOS.
Chris Ringer
@Echo Off
Cls
:: variables: TempDir is a PC Work directory/folder to process files in
:: : DataFile is data file name(s) to be processed from A:
:: : Sendfile is PC file name to be sent to AS/400
Set TempDir=Qtemp1
Set DataFile=*.txt
Set SendFile=PCto400a.dta
Echo PC Batch Program %0 is running:
Echo.
Echo Processing PC file(s) received on Diskette...
Echo.
:AGAIN
:: errorlevels: 1=Yes, 2=No, 3=Cancel
Choice /C:YNC /N /T:C,60 Is Diskette in Drive A:? [Y-es,N-o,C-ancel]
If ErrorLevel 3 Goto :TheEnd
If ErrorLevel 2 Goto :AGAIN
:CLEARING
Echo Clearing Transfer work folder on PC...
C:
If not Exist %TempDir% ul Md %TempDir%
Cd %TempDir%
If Exist %DataFile% Del %DataFile%
If Exist %SendFile% Del %SendFile%
If Exist *.zip Del *.zip
Echo Copying %DataFile% PC files from A: to C:...
If Exist A:%DataFile% Copy A:%DataFile% C:
If Exist A:*.Zip Copy A:*.Zip C:
Echo Checking newly copied files on C:...
If Exist *.zip Goto :ZIPFILE
If Exist %DataFile% Goto :DATAFILES
Goto :ERROR1
:ZIPFILE
Echo Testing PC Zip file(s) for integrity...
PkUnZip -t *.zip
If ErrorLevel 1 Goto :ERROR2
Echo Unzipping PC file(s) with overwrite...
PkUnZip -o *.zip
Del *.Zip
:DATAFILES
Echo Appending PC %DataFile% data files together into one file...
Copy %DataFile% %SendFile%
If Not Exist %SendFile% Goto :ERROR3
:UPLOAD
Echo Uploading %SendFile% file to AS/400...
:: (put your FTP or RFROMPCB in here to upload PCto400a.dta)
Goto :TheEnd
:ERROR1
Echo ERROR: PC File(s) to be processed NOT found!
Pause
Goto :TheEnd
:ERROR2
Echo ERROR: PC Zip File could not be unzipped...
Pause
Goto :TheEnd
:ERROR3
Echo ERROR: PC Data file(s) could not be appended together...
Pause
Goto :TheEnd
:TheEnd
Echo PC Batch Program %0 is ending...
:: delete environment variables
Set TempDir=
Set DataFile=
Set SendFile=
Exit
Figure 3: This DOS batch file determines a file type before uploading it to your AS/400.
Capturing the Elusive AS/400 Screen
Designing or documenting a system often requires that word processing documents contain AS/400 screen captures, but have you tried to do this? Before I learned the following trick to handle this problem, I would create a box or some other word processing structure and fill it with the contents of the screen. I had to concern myself with fonts and font sizes to ensure that everything lined up as it would on an AS/400 screen.
If you use a Windows workstation with emulation, however, there is an easier way. Hold down the Alt key and press Print Screen, and the current window is placed onto the Windows clipboard. If the current window is an AS/400 session, for example, that screen is placed on the clipboard. This is always the case even if Alt+Print Screen is defined as System Request. If the System Request line appears at the bottom of your window, press Reset. You may then go to your word processing program (or spreadsheet or presentation program) and paste the contents.
The clipboard pastes in the same fashion for Windows paint or imaging programs, so the technique works for any active window you may wish to place onto another document. I even use it to save the last screen of a game after Ive reached my personal high!
William W. Smyth
Action Analysts, Inc.
Cataloging Troubles?
Q: My systems database cross-reference file, QSYS/QADBIFLD, appears to be damaged. It doesnt return field names to ODBC when I execute an SQL call from a PC. Whats really strange is that, when I use Query/400, I can see all of my files in the cross-reference physical file, QSYS/QADBXREF, but very few of those files exist in QSYS/QADBIFLD. How can I get the system to rebuild the catalog files? This problem started when the system
suddenly increased from 85 percent DASD to 96 percent and suddenly dropped to 66 percent 16 hours later. After that, my ODBC application started failing because it couldnt find the files it needed. Any suggestions?
Phil Simon
A: The Reclaim Storage (RCLSTG) command has an option to rebuild database cross- reference files. Run this command to clean up auxiliary storage when you have an unexpected system failure.
David Morris
Job Information with Just a Job Number
Looking for a quick way to find job information if all you know is the job number? Heres a little utility I developed called Work with Job by Number (WRKJOBNUM). To obtain job information, simply pass WRKJOBNUM the number of the job in question, and it displays the information. You can even modify this technique to retrieve information programmatically in an interactive program. Ive often wondered why IBM has never provided a command like this before, seeing as how the job number is unique, but this handy utility makes up for Big Blues lack of foresight. The code for both the command and command processing program can be found on the MC Web site at www.midrangecomputing.com/mc/.
Albert York
LATEST COMMENTS
MC Press Online