Patrick Monnerat | c017988 | 2014-03-04 17:27:22 +0100 | [diff] [blame] | 1 | |
| 2 | Implementation notes: |
| 3 | |
| 4 | This is a true OS/400 implementation, not a PASE implementation (for PASE, |
| 5 | use an AIX implementation). |
| 6 | |
| 7 | The biggest problem with OS/400 is EBCDIC. The current libxml2 implementation |
| 8 | uses UTF-8 internally. To ease encoding conversion between the calling |
| 9 | applications and libxml2, supplementary "convert and latch" functions are |
| 10 | provided (See below). To bind the EBCDIC OS/400 system calls and libxml2, |
| 11 | an ASCII run-time environment (QADRT) has been used and wrapper functions have |
| 12 | been designed. |
| 13 | |
| 14 | Other problems are: |
| 15 | - Source code line length: to be stored in DB2 members, source files may not |
| 16 | have lines longer than 100 characters. Some header and documentation files |
| 17 | have been modified accordingly. |
| 18 | - va_list dereferencing: the OS/400 implementation of va_list type is an array |
| 19 | but the compiler forbids explicit array dereferencing. Source files have |
| 20 | been updated accordingly. |
| 21 | - Depending on the compilation/execution environment, it is possible that |
| 22 | stdin/stdout/stderr are not associated with a file descriptor; as a side |
| 23 | effect, open() may return a file descriptor value 0, 1 or 2 that is NOT |
| 24 | a C standard file. Thus using such a number may be inaccurate. |
| 25 | - iconv_open() arguments: OS/400 uses non-standard encoding names and does not |
| 26 | support standard names. For this reason, a name wrapper has been designed. |
| 27 | - dlopen() (support for xmodule): the function and its corollaries are not |
| 28 | provided by the OS/400 library. However a local implementation is provided. |
| 29 | |
| 30 | |
| 31 | Compiling on OS/400: |
| 32 | |
| 33 | _ As a prerequisite, QADRT development environment must be installed. |
| 34 | _ Install the libxml2 source directory in IFS. |
| 35 | _ Enter shell (QSH) |
| 36 | _ Change current directory to the libxml2 installation directory |
| 37 | _ Change current directory to ./os400 |
| 38 | _ Edit file iniscript.sh. You may want to change tunable configuration |
| 39 | parameters, like debug info generation, optimisation level, listing option, |
| 40 | target library, zlib availability, etc. |
| 41 | _ Copy any file in the current directory to makelog (i.e.: |
| 42 | cp initscript.sh makelog): this is intended to create the makelog file with |
| 43 | an ASCII CCSID! |
| 44 | _ Enter the command "sh make.sh >makelog 2>&1' |
| 45 | _ Examine the makelog file to check for compilation errors. |
| 46 | |
| 47 | Leaving file initscript.sh unchanged, this will produce the following |
| 48 | OS/400 objects: |
| 49 | _ Library LIBXML2. All other objects will be stored in this library. |
| 50 | _ Modules for all libxml2 units, with full debug info and no code optimization. |
| 51 | _ Binding directory LIBXML2_A, to be used at calling program link time for |
| 52 | statically binding the modules (specify BNDSRVPGM(QADRTTS QGLDCLNT QGLDBRDR) |
| 53 | when creating a program using LIBXML2_A). |
| 54 | _ Service program LIBXML2. To be used at calling program run-time |
| 55 | when this program has dynamically bound libxml2 at link time. |
| 56 | _ Binding directory LIBXML2. To be used to dynamically bind libxml2 when |
| 57 | linking a calling program. |
| 58 | _ Source file LIBXML. It contains all the header members needed to compile a |
| 59 | C/C++ module using libxml2. |
| 60 | _ Standard and additional C/C++ libxml2 header members (possibly renamed) in |
| 61 | file LIBXML. |
| 62 | _ IFS directory /libxml2 with subdirectory include/libxml containing all |
| 63 | C/C++ header files for IFS-based compilation. |
| 64 | _ Source file LIBXMLRPG. It contains all the include members needed to compile a |
| 65 | ILE/RPG module/program using libxml2 (ILE/RPG binding). |
| 66 | _ ILE/RPG binding include members (possibly renamed) in file LIBXMLRPG. |
| 67 | _ IFS subdirectory /libxml2/include/libxmlrpg containing all ILE/RPG include |
| 68 | files for IFS-based compilation. |
| 69 | |
| 70 | |
| 71 | Renamed header files in DB2 members: |
| 72 | DB2 member names are limited to 10 characters, thus the following C/C++ |
| 73 | header members are renamed as: |
| 74 | parserInternals.h --> PARSERINTE |
| 75 | schemasInternals.h --> SCHEMASINT |
| 76 | xmlautomata.h --> XMLAUTOMAT |
| 77 | xmlschemastype.h --> SCHMTYPES |
| 78 | xpathInternals.h --> XPATHINTER |
| 79 | IFS header files are NOT renamed. |
| 80 | ILE/RPG headers are processed likewise. |
| 81 | |
| 82 | |
| 83 | Special programming consideration: |
| 84 | |
| 85 | QADRT being used, the following points must be considered: |
| 86 | _ If static binding is used, service program QADRTTS must be linked too. |
| 87 | _ The EBCDIC CCSID used by QADRT is 37 by default, NOT THE JOB'S CCSID. If |
| 88 | another EBCDIC CCSID is required, it must be set via a locale through a call |
| 89 | to setlocale_a (QADRT's setlocale() ASCII wrapper) with category LC_ALL or |
| 90 | LC_CTYPE, or by setting environment variable QADRT_ENV_LOCALE to the locale |
| 91 | object path before executing the program. |
| 92 | _ Always use *IFSIO or *IFS64IO to compile calling programs. |
| 93 | |
| 94 | |
| 95 | |
| 96 | Supplementary (non libxml2 standard) support procedures for OS/400. |
| 97 | |
| 98 | As cited above, there are some procedures to ease encoding conversion of |
| 99 | libxml2 function arguments and results: the mechanism is based on |
| 100 | dictionaries. The functions convert a string, latch the result in a dictionary |
| 101 | to ensure its persistence and return its address. It is the caller's |
| 102 | responsibility to clean the dictionary when it becomes too big or disappears. |
| 103 | |
| 104 | The procedures are: |
| 105 | |
| 106 | #include <libxml/transcode.h> |
| 107 | |
| 108 | const char * xmlTranscodeResult(const xmlChar * s, |
| 109 | const char * encoding, |
| 110 | xmlDictPtr * dict, |
| 111 | void (*freeproc)(const void *)); |
| 112 | |
| 113 | const xmlChar * xmlTranscodeString(const char * s, |
| 114 | const char * encoding, |
| 115 | xmlDictPtr * dict); |
| 116 | |
| 117 | const xmlChar * xmlTranscodeWString(const char * s, |
| 118 | const char * encoding, |
| 119 | xmlDictPtr * dict); |
| 120 | |
| 121 | const xmlChar * xmlTranscodeWString(const char * s, |
| 122 | const char * encoding, |
| 123 | xmlDictPtr * dict); |
| 124 | |
| 125 | where: |
| 126 | s is the string to translate. |
| 127 | encoding is the alternate character encoding. If null, the current job's |
| 128 | encoding (CCSID) is used. |
| 129 | dict is the address of the latching directory. If NULL, the procedure |
| 130 | functions as a simple non-latching encoding converter and |
| 131 | its result value should be freed by the caller. |
| 132 | freeproc is a procedure to release the original string, or NULL. |
| 133 | |
| 134 | xmlTranscodeResult() converts from UTF-8 to the given alternate encoding. |
| 135 | xmlTranscodeString() converts from the given 8-bit encoding to UTF-8 (note that |
| 136 | UTF-8 itself is considered as a 8-bit encoding). |
| 137 | xmlTranscodeWString() converts from the given 16-bit encoding to UTF-8. |
| 138 | xmlTranscodeHString() converts from the given 32-bit encoding to UTF-8. |
| 139 | |
| 140 | |
| 141 | To shorten statements using these functions, shorthands are defined: |
| 142 | |
| 143 | xmlTR for xmlTranscodeResult |
| 144 | xmlTS for xmlTranscodeString |
| 145 | xmlTW for xmlTranscodeWString |
| 146 | xmlTH for xmlTranscodeHstring |
| 147 | |
| 148 | These shorthands may be disabled by defining XML_NO_SHORT_NAMES before |
| 149 | libxml/transcode.h inclusion. |
| 150 | |
| 151 | A directory pointer must be preset to NULL before the first call using it to |
| 152 | one of the above procedure. |
| 153 | |
| 154 | To release a latching directory, use function |
| 155 | |
| 156 | void xmlZapDict(xmlDictPtr * dict); |
| 157 | |
| 158 | |
| 159 | Example: |
| 160 | |
| 161 | #include <libxml/transcode.h> |
| 162 | #include <libxml/tree.h> |
| 163 | |
| 164 | xmlDocPtr mySimpleXMLDoc(char * element, char * text) |
| 165 | { |
| 166 | xmlDocPtr doc; |
| 167 | xmlNodePtr node; |
| 168 | xmlDictPtr dict = NULL; |
| 169 | |
| 170 | /* element and text are encoded in the current job's encoding. */ |
| 171 | |
| 172 | doc = xmlNewDoc(); |
| 173 | xmlNewTextChild((xmlNodePtr) doc, NULL, xmlTS(element, NULL, |
| 174 | &dict), xmlTS(text, NULL, &dict)); |
| 175 | xmlZapDict(&dict); |
| 176 | return doc; |
| 177 | } |
| 178 | |
| 179 | |
| 180 | Additionally, a formatter into latched/dynamic storage is provided: |
| 181 | |
| 182 | const char * xmlVasprintf(xmlDictPtr * dict, |
| 183 | const char * encoding, |
| 184 | const xmlChar * fmt, |
| 185 | va_list args); |
| 186 | |
| 187 | |
Patrick Monnerat | b293771 | 2015-04-21 17:21:49 +0200 | [diff] [blame^] | 188 | xmllint and xmlcatalog programs: |
| 189 | |
| 190 | These programs are fully implemented at the qshell level, with standard |
| 191 | command line options. Links to these are installed in sub-directory bin of |
| 192 | the IFS installation directory. |
| 193 | CL command interfaces to these programs are also provided with limited |
| 194 | support. In particular, interactive mode is not supported and argument count |
| 195 | and lengths are limited by the CL command syntax. |
| 196 | |
Patrick Monnerat | c017988 | 2014-03-04 17:27:22 +0100 | [diff] [blame] | 197 | |
| 198 | ILE/RPG binding: |
| 199 | |
| 200 | All standard types and procedures are provided. Since ILE/RPG does not |
Patrick Monnerat | b293771 | 2015-04-21 17:21:49 +0200 | [diff] [blame^] | 201 | support macros, they have not been ported. However some of them are emulated |
| 202 | as functions: these are the more useful ones (xmlXPathNodeSetGetLength, |
| 203 | xmlXPathNodeSetItem, xmlXPathNodeSetIsEmpty, htmlDefaultSubelement, |
| 204 | htmlElementAllowedHereDesc, htmlRequiredAttrs) and the global/threaded |
| 205 | variables access macros. These variables can be read with function |
| 206 | get_xxx(void), where xxxx is the name of the variable; they may be set by |
| 207 | calling function set_xxxx(value), where value is of the same type as the |
| 208 | variable. |
Patrick Monnerat | c017988 | 2014-03-04 17:27:22 +0100 | [diff] [blame] | 209 | |
| 210 | The C va_list is not implemented as such in ILE/RPG. Functions implementing |
| 211 | va_list and associated methods are provided: |
| 212 | |
| 213 | /include "libxmlrpg/xmlstdarg" |
| 214 | |
| 215 | d xmlVaStart pr |
| 216 | d list like(xmlVaList) |
| 217 | d lastargaddr * value |
| 218 | d lastargsize 10u 0 value |
| 219 | |
| 220 | d xmlVaArg pr |
| 221 | d list like(xmlVaList) |
| 222 | d dest * value |
| 223 | d argsize 10i 0 value |
| 224 | |
| 225 | d xmlVaEnd pr |
| 226 | d list like(xmlVaList) |