How to program an Application: Difference between revisions
(→A Word on Editors: More precise) |
m (fixed typos) |
||
(17 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
{{FIXME|Finish article.}} | {{FIXME|Finish article.}} | ||
Getting started on programming the AS/400 isn't hard. According to Frank Soltis, | Getting started on programming the AS/400 isn't hard. According to Frank Soltis, the most effective way to get a machine sold is to actually bring an AS/400 along to the future customer, and show an C''x''O in a one hour crash course how to code a simple ''business application''.<br /> | ||
Well, something an arbitrary business buffoon can do, you can do, too. Since the usual [[wikipedia:"Hello, World!" program|Hello World]] is just too lame, let's start with an actually usable example: A simple address book application. | Well, something an arbitrary business buffoon can do, you can do, too. Since the usual [[wikipedia:"Hello, World!" program|Hello World]] is just too lame, let's start with an actually usable example: A simple address book application. | ||
Line 6: | Line 6: | ||
Since we're talking about a database machine, the first we need to know is how to create ''Database Tables''. | Since we're talking about a database machine, the first we need to know is how to create ''Database Tables''. | ||
Editing Database Content is usually done in forms. These are called ''Display Files''. So, let's learn how to create Display Files in the next turn. | Editing Database Content is usually done in screen ''forms''. These are called ''Display Files''. So, let's also learn how to create Display Files in the next turn. | ||
Finally, there must be a program for handling key presses from the user and coping with the | Finally, there must be a program for handling key presses from the user and coping with the I/O of database- and display files. | ||
Optionally, there can be more files to support additional functions in a program. Printer files allow for formatted output (tabular report) to a printer. InterSystem Communication Files allow for Record-I/O to other programs on the local or a remote host. We will not dig into these, for now. | |||
=== Programming Languages === | === Programming Languages === | ||
Line 23: | Line 25: | ||
RPG and COBOL are available in two flavors: [[wikipedia:Integrated Language Environment|ILE]] and [https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/ilec/opmdesc.htm OPM]. See linked explanations for details. | RPG and COBOL are available in two flavors: [[wikipedia:Integrated Language Environment|ILE]] and [https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/ilec/opmdesc.htm OPM]. See linked explanations for details. | ||
It makes no sense to utilize OPM compilers | It makes no sense to utilize OPM compilers for new projects. It's best you save space and deinstall these as well as the ''*PRV'' variants, that generate code for the immediately previous OS release. We'll solely focus on ILE since it has (amongst others) the advantage of linking (binding) compiled object code from different languages together to form a program. | ||
The IBM website features [https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzahg/rzahglanguages.htm extensive documentation] for each language. | |||
== A Word on Editors == | == A Word on Editors == | ||
Line 35: | Line 39: | ||
|valign="top"|'''SEU on OS/400''' | |valign="top"|'''SEU on OS/400''' | ||
|valign="top"|Built-in contextual support for many file types and kind of lines with precise column requirements.<br />Editing is done in an implicit array of blanks in permanent overwrite mode for easier placement of characters in proper position. | |valign="top"|Built-in contextual support for many file types and kind of lines with precise column requirements.<br />Editing is done in an implicit array of blanks in permanent overwrite mode for easier placement of characters in proper position. | ||
|valign="top"|Can display only a few lines of code, | |valign="top"|Can display only a few lines of code, that reduces clarity and thus forces a lot of scrolling.<br />Uniform colouring of code is increasingly uncommon and makes it even more difficult to keep an overview. | ||
|- | |- | ||
|valign="top"|'''Other on other platforms''' | |valign="top"|'''Other on other platforms''' | ||
|valign="top"|Familiar operation and UI.<br />Easy content duplication with clearly visible text range selection, and copy-paste.<br />Possibility to create custom rules for syntax highlighting. | |valign="top"|Familiar operation and UI.<br />Easy content duplication with clearly visible text range selection, and copy-paste.<br />Possibility to create custom rules for syntax highlighting. | ||
|valign="top"|Cumbersome handling: After every change | |valign="top"|Cumbersome handling: After every change that should result in a compile run, changed files have to be transferred back in some way. | ||
|} | |} | ||
The Killer-Feature of SEU is the contextual support it provides. For beginners, it's much easier to utilize this helpful function often until some knowledge and | The Killer-Feature of SEU is the extensive contextual support it provides for RPG and DDS, and partly for COBOL. For beginners, it's much easier to utilize this helpful function often until some knowledge, routine and working programs as copy-source have been established. | ||
=== Vim === | |||
Vim is most often the editor of choice for seasoned Text-UI affictionados. Since ''vim'' is able to open files on remote-locations via URL notation, you can perfectly use it for editing on the fly from any platform vim is available for. There are even extensions for [https://github.com/kaimoku/vim-syntax-for-i syntax-highlighting] of common code.<ref>No longer working with vim 8.</ref> Automation of login can be done via [http://www.mavetju.org/unix/netrc.php ''~/.netrc'' file]: | |||
* Create/edit your ''~/.vimrc'' to switch to ASCII mode on start, add: | |||
let g:netrw_ftpmode="ascii" | |||
* Create/edit your ''~/.netrc'' to have credentials ready, add: | |||
machine my-machine-name | |||
login myuser | |||
password mypassword | |||
macdef init | |||
ascii | |||
Important: The file '''must''' end with a blank line! Do a <code>chmod 600 ~/.netrc</code> for some more security. | |||
* Edit files giving vim the remote URL: | |||
vim <nowiki>ftp://my-machine-name/mylib/mysrcpf.mymember</nowiki> | |||
With this toolset, you can develop with a tall ''vim'' window on your desktop machine, klick on a 5250-session to compile and maybe have a second 5250 session open for running the program. | |||
<gallery class="center"> | |||
File:Vim-screen-dspf-dds.png|Vim showing 91 lines of DDS | |||
File:Vim-screen-rpgle.png|Vim showing 91 lines of RPG IV positional code | |||
</gallery> | |||
== Preparation == | == Preparation == | ||
As you probably know from your experience with common systems, it's considered bad habit to work with administrative rights all of the time. I recommend [[Creating | As you probably know from your experience with common systems, it's considered bad habit to work with administrative rights all of the time. I recommend [[Creating a User Account]] for you to properly work without accidentally doing harm to the system. ''Sign in'' as this user now. This gives you a subset of menu items in the ''main'' menu and makes your own Library your ''current library''. For now, consider this almost the same thing as using the <code>cd</code> command of a shell to make a directory your current one. | ||
As outlined in [[Filesystems and Files on the AS/400#File Types|File Types]], we'll need to create a file to hold source code. Let's do that and make the maximum line length a bit larger for more flexibility.<ref>IBM delivers ready made, empty source files in the QGPL-Library. Every class of file has it's own source file, such as QCLSRC for CL source code. I consider this confusing: Working on multiple files is more cumbersome than working on multiple members of one file. The files in a member could be marked as a given type of content. The only drawback is that one must use distinct names on members. The QSYS.LIB-Filesystem can hold files with the same ''name'' as long as they have distinct ''types''.</ref> | As outlined in [[Filesystems and Files on the AS/400#File Types|File Types]], we'll need to create a file to hold source code. Let's do that and make the maximum line length a bit larger for more flexibility.<ref>IBM delivers ready made, empty source files in the QGPL-Library. Every class of file has it's own source file, such as QCLSRC for CL source code. I consider this confusing: Working on multiple files is more cumbersome than working on multiple members of one file. The files in a member could be marked as a given type of content. The only drawback is that one must use distinct names on members. The QSYS.LIB-Filesystem can hold files with the same ''name'' as long as they have distinct ''types''.</ref> | ||
Line 63: | Line 91: | ||
== Coding the Database Table == | == Coding the Database Table == | ||
We're going to code the description of a database file, | We're going to code the description of a database file, that is the traditional way to create database files in OS/400.<ref>Database files can also be created with the interactive SQL facility, though. But one can't derive a textual description from a SQL created database file.</ref> The ''language'' for the statements is called ''DDS''<ref>Data Description Statements.</ref> that is not a line oriented description like HTML. The position of statements within one line are also important.<ref>This stems from old times when punch cards were used for programming stuff. Since compatibility is mandatory, IBM extended DDS from time to time with new keywords, but left the previous stuff alone.</ref> | ||
For an address book, let's assume the following fields are of primary interest: | For an address book, let's assume the following fields are of primary interest: | ||
Line 101: | Line 129: | ||
Physical Files must have exactly one record format. | Physical Files must have exactly one record format. | ||
The next few lines define the fields of the database file. I don't want getting unnecessary initial complexity, so I defined all fields as ch'''a'''racter with static 48 places.<ref>The AS/400 database knows about ''varchar'' field, but the handling in the code later would be really clumsy. So I refrain from that for now. Not used places are automatically filled with blanks.</ref> The ''Birthday''-field is the only exception, | The next few lines define the fields of the database file. I don't want getting unnecessary initial complexity, so I defined all fields as ch'''a'''racter with static 48 places.<ref>The AS/400 database knows about ''varchar'' field, but the handling in the code later would be really clumsy. So I refrain from that for now. Not used places are automatically filled with blanks.</ref> The ''Birthday''-field is the only exception, that is defined as a date field. | ||
Some fields may be left empty. To save space, these may be NULL, | Some fields may be left empty. To save space, these may be NULL, that is not the same as ''empty''. Therefore they are defined with an additional parameter ''alwnull''.<br /> | ||
NULL fields permit fields of records to utilize no space at all, but need special attention in the code. This isn't as clumsy as coping with ''varlen'' strings, though. | NULL fields permit fields of records to utilize no space at all, but need special attention in the code. This isn't as clumsy as coping with ''varlen'' strings, though. | ||
The last three lines denote ''key fields''. When reading records, they'll be retrieved in key order (ascending by default). According to the first line, entries must be ''unique'' over all key fields. So you may not have more than one entry named Fred Flintstone born on 1989-08-20. This is a somewhat crude way to prevent duplicates.<ref>If Fred has more than one place to live, the right way to handle that would be to create a second table | The last three lines denote ''key fields''. When reading records, they'll be retrieved in key order (ascending by default). According to the first line, entries must be ''unique'' over all key fields. So you may not have more than one entry named Fred Flintstone born on 1989-08-20. This is a somewhat crude way to prevent duplicates.<ref>If Fred has more than one place to live, the right way to handle that would be to create a second table that lists every possible street address for a given Tuple Name—First Name—Birthday. Of course we might introduce entry IDs to keep the address table small. As said, I want to keep complexity low.</ref> | ||
After saving the member, one may type ''14'' into the field of the ''wrkmbrpdm'' members list to instruct it to compile the file with default values to the default location | After saving the member, one may type ''14'' into the field of the ''wrkmbrpdm'' members list to instruct it to compile the file with default values to the default location that is your current library. | ||
=== A Word about the Compilation of Objects === | === A Word about the Compilation of Objects === | ||
Compilation per default takes place as background (batch) job | Compilation per default takes place as background (batch) job that is more friendly to other tasks running in interactive mode but it's a bit clumsy to handle. One needs to look into the session's [[Messages and Message Queues|message queue]] to see if the compilation succeeded or failed, to be followed by a look into the [[Spooled Files and Output Queues|spooled file]], searching the verbose compiler output for possible culprits.<br /> | ||
One may press <code>F18</code> in the ''wrkmbrpdm'' screen to access another screen with user based defaults. The third option must be set to ''N''. | One may press <code>F18</code> in the ''wrkmbrpdm'' screen to access another screen with user based defaults. The third option must be set to ''N''. | ||
== See also == | |||
* [[Editing Source Files using Eclipse and FTP]] | |||
== Weblinks == | |||
* [https://www.pocnet.net/computer/fallout/ Helper Programs] for the Fallout Role Playing Game Series | |||
* [https://github.com/PoC-dev/as400-sfltemplates Templates] for easy development of one-database-table maintenance programs | |||
== Footnotes == | == Footnotes == |
Revision as of 19:44, 8 February 2024
This article isn't finished yet or needs to be revised. Please keep in mind that thus it may be incomplete.
Reason: Finish article. |
Getting started on programming the AS/400 isn't hard. According to Frank Soltis, the most effective way to get a machine sold is to actually bring an AS/400 along to the future customer, and show an CxO in a one hour crash course how to code a simple business application.
Well, something an arbitrary business buffoon can do, you can do, too. Since the usual Hello World is just too lame, let's start with an actually usable example: A simple address book application.
Components of a typical Program
Since we're talking about a database machine, the first we need to know is how to create Database Tables.
Editing Database Content is usually done in screen forms. These are called Display Files. So, let's also learn how to create Display Files in the next turn.
Finally, there must be a program for handling key presses from the user and coping with the I/O of database- and display files.
Optionally, there can be more files to support additional functions in a program. Printer files allow for formatted output (tabular report) to a printer. InterSystem Communication Files allow for Record-I/O to other programs on the local or a remote host. We will not dig into these, for now.
Programming Languages
Available on a full install of an older OS/400 are compilers for
and interpreters for
- REXX, a scripting language derived from the mainframe world.
RPG and COBOL are available in two flavors: ILE and OPM. See linked explanations for details.
It makes no sense to utilize OPM compilers for new projects. It's best you save space and deinstall these as well as the *PRV variants, that generate code for the immediately previous OS release. We'll solely focus on ILE since it has (amongst others) the advantage of linking (binding) compiled object code from different languages together to form a program.
The IBM website features extensive documentation for each language.
A Word on Editors
If you are familiar with vi or vim on Unix-like platforms, learning SEU will be an easy task. You may alternatively utilize an editor of your choice on the platform of your choice.[2] To help you chose, we'll take a closer look on the pros and cons of each solution.
Editor | Pro | Con |
---|---|---|
SEU on OS/400 | Built-in contextual support for many file types and kind of lines with precise column requirements. Editing is done in an implicit array of blanks in permanent overwrite mode for easier placement of characters in proper position. |
Can display only a few lines of code, that reduces clarity and thus forces a lot of scrolling. Uniform colouring of code is increasingly uncommon and makes it even more difficult to keep an overview. |
Other on other platforms | Familiar operation and UI. Easy content duplication with clearly visible text range selection, and copy-paste. Possibility to create custom rules for syntax highlighting. |
Cumbersome handling: After every change that should result in a compile run, changed files have to be transferred back in some way. |
The Killer-Feature of SEU is the extensive contextual support it provides for RPG and DDS, and partly for COBOL. For beginners, it's much easier to utilize this helpful function often until some knowledge, routine and working programs as copy-source have been established.
Vim
Vim is most often the editor of choice for seasoned Text-UI affictionados. Since vim is able to open files on remote-locations via URL notation, you can perfectly use it for editing on the fly from any platform vim is available for. There are even extensions for syntax-highlighting of common code.[3] Automation of login can be done via ~/.netrc file:
- Create/edit your ~/.vimrc to switch to ASCII mode on start, add:
let g:netrw_ftpmode="ascii"
- Create/edit your ~/.netrc to have credentials ready, add:
machine my-machine-name login myuser password mypassword macdef init ascii
Important: The file must end with a blank line! Do a chmod 600 ~/.netrc
for some more security.
- Edit files giving vim the remote URL:
vim ftp://my-machine-name/mylib/mysrcpf.mymember
With this toolset, you can develop with a tall vim window on your desktop machine, klick on a 5250-session to compile and maybe have a second 5250 session open for running the program.
Preparation
As you probably know from your experience with common systems, it's considered bad habit to work with administrative rights all of the time. I recommend Creating a User Account for you to properly work without accidentally doing harm to the system. Sign in as this user now. This gives you a subset of menu items in the main menu and makes your own Library your current library. For now, consider this almost the same thing as using the cd
command of a shell to make a directory your current one.
As outlined in File Types, we'll need to create a file to hold source code. Let's do that and make the maximum line length a bit larger for more flexibility.[4]
CRTSRCPF FILE(SOURCES) RCDLEN(112)
The white text in the status line will show you that the file has been created.
Working with Members in Files
The easiest way to edit members of source files is to utilize part of the Program Development Manager.
WRKMBRPDM FILE(SOURCES)
You'll be presented with a screen form to handle members. Press F6
to show the Start SEU[5] screen. Fill out the two first fields:
- SRCMBR is addrpf (for addresses physical file),
- TYPE is pf for physical file.
Press Enter
to start SEU and present an empty file.
Coding the Database Table
We're going to code the description of a database file, that is the traditional way to create database files in OS/400.[6] The language for the statements is called DDS[7] that is not a line oriented description like HTML. The position of statements within one line are also important.[8]
For an address book, let's assume the following fields are of primary interest:
- Name,
- First Name,
- Birthday,
- Street and Number,
- ZIP Code and City Name,
- Phone Number,
- Cellular Phone Number,
- E-Mail Address.
Plain DDS Code looks like this:
A UNIQUE A R ADDRTBL A NAME 48A A FIRSTNAME 48A A BIRTHDAY L A STREETNUM 48A A ZIPCITY 48A A PHONE 48A ALWNULL A CELLPHONE 48A ALWNULL A EMAIL 48A ALWNULL A K NAME A K FIRSTNAME A K BIRTHDAY
To understand a bit better, I'll elaborate.
As you can see, everything is written in upper case. To be honest, I don't know if a file with lower case characters in any place but comments is compilable.
Every line starts with an A in the 6th place of a line. The first five once were reserved for optional line numbering but I've seen no examples where this is actually done.
The first line denotes that this file may not have duplicate values in key fields (coded later).
The second line names this record format. This should be different from the file name. If not, you'll earn compiler warnings: In the actual program, when working with that file, it's ambiguous if you refer to the file name or the record format. For that reason, I name record formats for physical files with the suffix tbl.
Physical Files must have exactly one record format.
The next few lines define the fields of the database file. I don't want getting unnecessary initial complexity, so I defined all fields as character with static 48 places.[9] The Birthday-field is the only exception, that is defined as a date field.
Some fields may be left empty. To save space, these may be NULL, that is not the same as empty. Therefore they are defined with an additional parameter alwnull.
NULL fields permit fields of records to utilize no space at all, but need special attention in the code. This isn't as clumsy as coping with varlen strings, though.
The last three lines denote key fields. When reading records, they'll be retrieved in key order (ascending by default). According to the first line, entries must be unique over all key fields. So you may not have more than one entry named Fred Flintstone born on 1989-08-20. This is a somewhat crude way to prevent duplicates.[10]
After saving the member, one may type 14 into the field of the wrkmbrpdm members list to instruct it to compile the file with default values to the default location that is your current library.
A Word about the Compilation of Objects
Compilation per default takes place as background (batch) job that is more friendly to other tasks running in interactive mode but it's a bit clumsy to handle. One needs to look into the session's message queue to see if the compilation succeeded or failed, to be followed by a look into the spooled file, searching the verbose compiler output for possible culprits.
One may press F18
in the wrkmbrpdm screen to access another screen with user based defaults. The third option must be set to N.
See also
Weblinks
- Helper Programs for the Fallout Role Playing Game Series
- Templates for easy development of one-database-table maintenance programs
Footnotes
- ↑ Report Program Generator.
- ↑ Windows Notepad is not a proper editor. It's sufficient for notes, though. Hence the name.
- ↑ No longer working with vim 8.
- ↑ IBM delivers ready made, empty source files in the QGPL-Library. Every class of file has it's own source file, such as QCLSRC for CL source code. I consider this confusing: Working on multiple files is more cumbersome than working on multiple members of one file. The files in a member could be marked as a given type of content. The only drawback is that one must use distinct names on members. The QSYS.LIB-Filesystem can hold files with the same name as long as they have distinct types.
- ↑ Source Entry Utility.
- ↑ Database files can also be created with the interactive SQL facility, though. But one can't derive a textual description from a SQL created database file.
- ↑ Data Description Statements.
- ↑ This stems from old times when punch cards were used for programming stuff. Since compatibility is mandatory, IBM extended DDS from time to time with new keywords, but left the previous stuff alone.
- ↑ The AS/400 database knows about varchar field, but the handling in the code later would be really clumsy. So I refrain from that for now. Not used places are automatically filled with blanks.
- ↑ If Fred has more than one place to live, the right way to handle that would be to create a second table that lists every possible street address for a given Tuple Name—First Name—Birthday. Of course we might introduce entry IDs to keep the address table small. As said, I want to keep complexity low.