Porting C-Source to OS/400: Difference between revisions
(+Link) |
(Reworked) |
||
(One intermediate revision by the same user not shown) | |||
Line 3: | Line 3: | ||
Most often, the real challenge is to manually put together a ''config.h'' file. Since there's no capable UNIX shell environment, <code>./configure</code> is no option.<ref>With V4R5, IBM claims to have implemented the C90 standard in Compiler and C-Library. I did not yet find a readymade ''config.h'' with all statements needed for a C90 environment.</ref> | Most often, the real challenge is to manually put together a ''config.h'' file. Since there's no capable UNIX shell environment, <code>./configure</code> is no option.<ref>With V4R5, IBM claims to have implemented the C90 standard in Compiler and C-Library. I did not yet find a readymade ''config.h'' with all statements needed for a C90 environment.</ref> | ||
These are definitions for integers, being used often. | |||
<syntaxhighlight lang="c"> | |||
typedef unsigned long long int uint64_t; | |||
typedef unsigned int uint32_t; | |||
typedef unsigned short int uint16_t; | |||
</syntaxhighlight> | |||
<blockquote>'''Note:''' The IMPI (CISC) C compiler in V3R2 and earlier doesn't know <tt>long long</tt>, it's 32 bits only.</blockquote> | |||
== Preparations for QSYS.LIB == | == Preparations for QSYS.LIB == | ||
Preparations are mostly one on UNIX/Linux side. | Preparations are mostly one on UNIX/Linux side. This is required to make the older V4R5 compiler happy. Newer compilers might be more forgiving. | ||
# Convert to native line endings for your platform, if the source files don't match. | |||
# Convert Tabs to spaces:<ref>Tabs appear in SEU as only one blank. This makes source indentation hardly visible.</ref><br><code>for FILE in *.c *.h; do cp ${FILE} ${FILE}~; expand -i -t4 < ${FILE}~ > ${FILE}; done</code> | # Convert Tabs to spaces:<ref>Tabs appear in SEU as only one blank. This makes source indentation hardly visible.</ref><br><code>for FILE in *.c *.h; do cp ${FILE} ${FILE}~; expand -i -t4 < ${FILE}~ > ${FILE}; done</code> | ||
# Find out longest line in all C- and H-Files.<br><code>wc -L *.c |sort -rn |head</code> | # Find out longest line in all C- and H-Files.<br><code>wc -L *.c |sort -rn |head</code> | ||
# Eliminate too long lines by wrapping. This is easily done with <code>set colorcolumn=80</code> in ''vim'', and scrolling through the files with a wide window. <ref>Wider than 80 chars, that is.</ref> | # Eliminate too long lines by wrapping. This is easily done with <code>set colorcolumn=80</code> in ''vim'', and scrolling through the files with a wide window. <ref>Wider than 80 chars, that is.</ref> | ||
# Find C++-style comments and convert to proper C comments. | |||
# Find function definitions which should be inlined, remove the word "inline" from the definition, and add a hint for the preprocessor/compiler that a function should be inlined before the function definition: <code>#pragma inline (''functionname'')</code> | |||
# Find and remove text following <code>#endif</code> preprocessor statements in the same line (thought as comment). | |||
# Create (at least) '''two''' appropriate SRCPF with matching maximum line lengths through the RCDLEN parameter for CRTSRCPF: | # Create (at least) '''two''' appropriate SRCPF with matching maximum line lengths through the RCDLEN parameter for CRTSRCPF: | ||
## One (or more) for C-Files (''may'' be named ''QCSRC''),<ref>It could be clever to create one PF per subdirectory.</ref> | ## One (or more) for C-Files (''may'' be named ''QCSRC''),<ref>It could be clever to create one PF per subdirectory.</ref> | ||
Line 15: | Line 27: | ||
# Upload. | # Upload. | ||
## If the file names are already shorter than 10 Characters (excluding file extension), just upload to a SRC PF:<br><code>for FILE in *.c; do echo -n "put ${FILE} MYLIB/QCSRC."; basename ${FILE} .c; done |ftp as400</code><ref>Automatic login and switching to ASCII mode is done though a ''~/.netrc''-file.</ref><ref>FTP ASCII takes care to convert ASCII to EBCDIC.</ref>. | ## If the file names are already shorter than 10 Characters (excluding file extension), just upload to a SRC PF:<br><code>for FILE in *.c; do echo -n "put ${FILE} MYLIB/QCSRC."; basename ${FILE} .c; done |ftp as400</code><ref>Automatic login and switching to ASCII mode is done though a ''~/.netrc''-file.</ref><ref>FTP ASCII takes care to convert ASCII to EBCDIC.</ref>. | ||
## If the file names are longer, you'll have considerable fun to come up with shorter names | ## If the file names are longer, you'll have considerable fun to come up with shorter names. Possibly ''grep'' through, and replace names in all text files if you needed to shorten a ''.h'' name. Finally, put together a text file with appropriate ''put'' commands, and hope for the best. | ||
# Change file type to ''C'':<br><code>for FILE in *.c; do echo "quote rcmd CHGPFM FILE(MYLIB/QCSRC) MBR( | # Change file type to ''C'':<br><code>for FILE in *.c; do echo "quote rcmd CHGPFM FILE(MYLIB/QCSRC) MBR($(basename ${FILE} .c)) SRCTYPE(C)"; done |ftp as400</code><ref>This is a good example how to exploit the ftp server's ability to call CL commands as a replacement for ''rcmd''.</ref> Note: You'll need to do this for header files, also! | ||
The precompiler searches private includes in ''*LIBL/H'', without the ''.h''-Extension. | The precompiler searches private includes in ''*LIBL/H'', without the ''.h''-Extension. | ||
Line 22: | Line 34: | ||
== Compile Cycle == | == Compile Cycle == | ||
Compile object files as follows: | Compile object files as follows: | ||
CRTCMOD MODULE(MYLIB/MAIN) SRCFILE(MYLIB/QCSRC) DEFINE(DEF1 DEF2=1) OPTION(*LOGMSG) OUTPUT(*PRINT)< | CRTCMOD MODULE(MYLIB/MAIN) SRCFILE(MYLIB/QCSRC) DEFINE(DEF1 DEF2=1) OPTION(*LOGMSG) OUTPUT(*PRINT) | ||
* Add <code>SYSIFCOPT(*IFSIO *IFS64IO)</code> to the compiler parameters if the code contains <code>fopen()</code> calls. | |||
* If you added <code>#pragma inline (''functionname'')</code> to the code, add <code>INLINE(*ON)</code> to the compiler parameters | |||
If compilation fails, output will go into a spooled file in | If compilation fails, output will go into a spooled file in the configured output queue. This is the most tedious task. | ||
# Compile, | |||
# check output, | |||
# fix problems, | |||
# <code>goto 1</code>. | |||
If all object modules have been created, you can then link them to a ''*PGM'' object as follows: | |||
CRTPGM PGM(MYLIB/MYPG) MODULE(MYLIB/*ALL) ENTMOD(*PGM) ACTGRP(*NEW) DETAIL(*BASIC) | CRTPGM PGM(MYLIB/MYPG) MODULE(MYLIB/*ALL) ENTMOD(*PGM) ACTGRP(*NEW) DETAIL(*BASIC) | ||
== Footnotes == | == Footnotes == |
Latest revision as of 23:35, 19 January 2025
This article isn't finished yet or needs to be revised. Please keep in mind that thus it may be incomplete.
Reason: Complete with Links to all necessary Books. |
Because of the uncommon file handling, name length and character constraints, porting is already a mostly manual task.[1]
Most often, the real challenge is to manually put together a config.h file. Since there's no capable UNIX shell environment, ./configure
is no option.[2]
These are definitions for integers, being used often.
typedef unsigned long long int uint64_t;
typedef unsigned int uint32_t;
typedef unsigned short int uint16_t;
Note: The IMPI (CISC) C compiler in V3R2 and earlier doesn't know long long, it's 32 bits only.
Preparations for QSYS.LIB
Preparations are mostly one on UNIX/Linux side. This is required to make the older V4R5 compiler happy. Newer compilers might be more forgiving.
- Convert to native line endings for your platform, if the source files don't match.
- Convert Tabs to spaces:[3]
for FILE in *.c *.h; do cp ${FILE} ${FILE}~; expand -i -t4 < ${FILE}~ > ${FILE}; done
- Find out longest line in all C- and H-Files.
wc -L *.c |sort -rn |head
- Eliminate too long lines by wrapping. This is easily done with
set colorcolumn=80
in vim, and scrolling through the files with a wide window. [4] - Find C++-style comments and convert to proper C comments.
- Find function definitions which should be inlined, remove the word "inline" from the definition, and add a hint for the preprocessor/compiler that a function should be inlined before the function definition:
#pragma inline (functionname)
- Find and remove text following
#endif
preprocessor statements in the same line (thought as comment). - Create (at least) two appropriate SRCPF with matching maximum line lengths through the RCDLEN parameter for CRTSRCPF:
- One (or more) for C-Files (may be named QCSRC),[5]
- One for H-Files (must be named H).
- Upload.
- If the file names are already shorter than 10 Characters (excluding file extension), just upload to a SRC PF:
for FILE in *.c; do echo -n "put ${FILE} MYLIB/QCSRC."; basename ${FILE} .c; done |ftp as400
[6][7]. - If the file names are longer, you'll have considerable fun to come up with shorter names. Possibly grep through, and replace names in all text files if you needed to shorten a .h name. Finally, put together a text file with appropriate put commands, and hope for the best.
- If the file names are already shorter than 10 Characters (excluding file extension), just upload to a SRC PF:
- Change file type to C:
for FILE in *.c; do echo "quote rcmd CHGPFM FILE(MYLIB/QCSRC) MBR($(basename ${FILE} .c)) SRCTYPE(C)"; done |ftp as400
[8] Note: You'll need to do this for header files, also!
The precompiler searches private includes in *LIBL/H, without the .h-Extension.
Compile Cycle
Compile object files as follows:
CRTCMOD MODULE(MYLIB/MAIN) SRCFILE(MYLIB/QCSRC) DEFINE(DEF1 DEF2=1) OPTION(*LOGMSG) OUTPUT(*PRINT)
- Add
SYSIFCOPT(*IFSIO *IFS64IO)
to the compiler parameters if the code containsfopen()
calls. - If you added
#pragma inline (functionname)
to the code, addINLINE(*ON)
to the compiler parameters
If compilation fails, output will go into a spooled file in the configured output queue. This is the most tedious task.
- Compile,
- check output,
- fix problems,
goto 1
.
If all object modules have been created, you can then link them to a *PGM object as follows:
CRTPGM PGM(MYLIB/MYPG) MODULE(MYLIB/*ALL) ENTMOD(*PGM) ACTGRP(*NEW) DETAIL(*BASIC)
Footnotes
- ↑ It's possible to use stream files in IFS as compiler input, but compiled objects have to be put into a QSYS.LIB, library. So, the file name restrictions apply anyway. The line length problem is mostly gone, though.
- ↑ With V4R5, IBM claims to have implemented the C90 standard in Compiler and C-Library. I did not yet find a readymade config.h with all statements needed for a C90 environment.
- ↑ Tabs appear in SEU as only one blank. This makes source indentation hardly visible.
- ↑ Wider than 80 chars, that is.
- ↑ It could be clever to create one PF per subdirectory.
- ↑ Automatic login and switching to ASCII mode is done though a ~/.netrc-file.
- ↑ FTP ASCII takes care to convert ASCII to EBCDIC.
- ↑ This is a good example how to exploit the ftp server's ability to call CL commands as a replacement for rcmd.