227 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| 
 | |
| Implementation notes:
 | |
| 
 | |
|   This is a true OS/400 implementation, not a PASE implementation (for PASE,
 | |
| use an AIX implementation).
 | |
| 
 | |
|   The biggest problem with OS/400 is EBCDIC. The current libxml2 implementation
 | |
| uses UTF-8 internally. To ease encoding conversion between the calling
 | |
| applications and libxml2, supplementary "convert and latch" functions are
 | |
| provided (See below). To bind the EBCDIC OS/400 system calls and libxml2,
 | |
| an ASCII run-time environment (QADRT) has been used and wrapper functions have
 | |
| been designed.
 | |
| 
 | |
| Other problems are:
 | |
| - Source code line length: to be stored in DB2 members, source files may not
 | |
|   have lines longer than 100 characters. Some header and documentation files
 | |
|   have been modified accordingly.
 | |
| - va_list dereferencing: the OS/400 implementation of va_list type is an array
 | |
|   but the compiler forbids explicit array dereferencing. Source files have
 | |
|   been updated accordingly.
 | |
| - Depending on the compilation/execution environment, it is possible that
 | |
|   stdin/stdout/stderr are not associated with a file descriptor; as a side
 | |
|   effect, open() may return a file descriptor value 0, 1 or 2 that is NOT
 | |
|   a C standard file. Thus using such a number may be inaccurate.
 | |
| - iconv_open() arguments: OS/400 uses non-standard encoding names and does not
 | |
|   support standard names. For this reason, a name wrapper has been designed.
 | |
| - dlopen() (support for xmodule): the function and its corollaries are not
 | |
|   provided by the OS/400 library. However a local implementation is provided.
 | |
| 
 | |
| 
 | |
| Compiling on OS/400:
 | |
| 
 | |
| _ As a prerequisite, QADRT development environment must be installed.
 | |
| _ Install the libxml2 source directory in IFS.
 | |
| _ Enter shell (QSH)
 | |
| _ Change current directory to the libxml2 installation directory
 | |
| _ Change current directory to ./os400
 | |
| _ Edit file iniscript.sh. You may want to change tunable configuration
 | |
|   parameters, like debug info generation, optimisation level, listing option,
 | |
|   target library, zlib availability, etc.
 | |
| _ Copy any file in the current directory to makelog (i.e.:
 | |
|   cp initscript.sh makelog): this is intended to create the makelog file with
 | |
|   an ASCII CCSID!
 | |
| _ Enter the command "sh make.sh >makelog 2>&1'
 | |
| _ Examine the makelog file to check for compilation errors.
 | |
| 
 | |
|   Leaving file initscript.sh unchanged, this will produce the following
 | |
| OS/400 objects:
 | |
| _ Library LIBXML2. All other objects will be stored in this library.
 | |
| _ Modules for all libxml2 units, with full debug info and no code optimization.
 | |
| _ Binding directory LIBXML2_A, to be used at calling program link time for
 | |
|   statically binding the modules (specify BNDSRVPGM(QADRTTS QGLDCLNT QGLDBRDR)
 | |
|   when creating a program using LIBXML2_A).
 | |
| _ Service program LIBXML2. To be used at calling program run-time
 | |
|   when this program has dynamically bound libxml2 at link time.
 | |
| _ Binding directory LIBXML2. To be used to dynamically bind libxml2 when
 | |
|   linking a calling program.
 | |
| _ Source file LIBXML. It contains all the header members needed to compile a
 | |
|   C/C++ module using libxml2.
 | |
| _ Standard and additional C/C++ libxml2 header members (possibly renamed) in
 | |
|   file LIBXML.
 | |
| _ IFS directory /libxml2 with subdirectory include/libxml containing all
 | |
|   C/C++ header files for IFS-based compilation.
 | |
| _ Source file LIBXMLRPG. It contains all the include members needed to compile a
 | |
|   ILE/RPG module/program using libxml2 (ILE/RPG binding).
 | |
| _ ILE/RPG binding include members (possibly renamed) in file LIBXMLRPG.
 | |
| _ IFS subdirectory /libxml2/include/libxmlrpg containing all ILE/RPG include
 | |
|   files for IFS-based compilation.
 | |
| 
 | |
| 
 | |
| Renamed header files in DB2 members:
 | |
|   DB2 member names are limited to 10 characters, thus the following C/C++
 | |
| header members are renamed as:
 | |
|   parserInternals.h     -->     PARSERINTE
 | |
|   schemasInternals.h    -->     SCHEMASINT
 | |
|   xmlautomata.h         -->     XMLAUTOMAT
 | |
|   xmlschemastype.h      -->     SCHMTYPES
 | |
|   xpathInternals.h      -->     XPATHINTER
 | |
| IFS header files are NOT renamed.
 | |
| ILE/RPG headers are processed likewise.
 | |
| 
 | |
| 
 | |
| Special programming consideration:
 | |
| 
 | |
| QADRT being used, the following points must be considered:
 | |
| _ If static binding is used, service program QADRTTS must be linked too.
 | |
| _ The EBCDIC CCSID used by QADRT is 37 by default, NOT THE JOB'S CCSID. If
 | |
|   another EBCDIC CCSID is required, it must be set via a locale through a call
 | |
|   to setlocale_a (QADRT's setlocale() ASCII wrapper) with category LC_ALL or
 | |
|   LC_CTYPE, or by setting environment variable QADRT_ENV_LOCALE to the locale
 | |
|   object path before executing the program.
 | |
| _ Always use *IFSIO or *IFS64IO to compile calling programs.
 | |
| 
 | |
| 
 | |
| 
 | |
| Supplementary (non libxml2 standard) support procedures for OS/400.
 | |
| 
 | |
|   As cited above, there are some procedures to ease encoding conversion of
 | |
| libxml2 function arguments and results: the mechanism is based on
 | |
| dictionaries. The functions convert a string, latch the result in a dictionary
 | |
| to ensure its persistence and return its address. It is the caller's
 | |
| responsibility to clean the dictionary when it becomes too big or disappears.
 | |
| 
 | |
| The procedures are:
 | |
| 
 | |
| #include <libxml/transcode.h>
 | |
| 
 | |
| const char *  xmlTranscodeResult(const xmlChar * s,
 | |
|                                  const char * encoding,
 | |
|                                  xmlDictPtr * dict,
 | |
|                                  void (*freeproc)(const void *));
 | |
| 
 | |
| const xmlChar * xmlTranscodeString(const char * s,
 | |
|                                    const char * encoding,
 | |
|                                    xmlDictPtr * dict);
 | |
| 
 | |
| const xmlChar * xmlTranscodeWString(const char * s,
 | |
|                                     const char * encoding,
 | |
|                                     xmlDictPtr * dict);
 | |
| 
 | |
| const xmlChar * xmlTranscodeWString(const char * s,
 | |
|                                     const char * encoding,
 | |
|                                     xmlDictPtr * dict);
 | |
| 
 | |
| where:
 | |
| s               is the string to translate.
 | |
| encoding        is the alternate character encoding. If null, the current job's
 | |
|                 encoding (CCSID) is used.
 | |
| dict            is the address of the latching directory. If NULL, the procedure
 | |
|                 functions as a simple non-latching encoding converter and
 | |
|                 its result value should be freed by the caller.
 | |
| freeproc        is a procedure to release the original string, or NULL.
 | |
| 
 | |
| xmlTranscodeResult()  converts from UTF-8 to the given alternate encoding.
 | |
| xmlTranscodeString()  converts from the given 8-bit encoding to UTF-8 (note that
 | |
|                       UTF-8 itself is considered as a 8-bit encoding).
 | |
| xmlTranscodeWString() converts from the given 16-bit encoding to UTF-8.
 | |
| xmlTranscodeHString() converts from the given 32-bit encoding to UTF-8.
 | |
| 
 | |
| 
 | |
| To shorten statements using these functions, shorthands are defined:
 | |
| 
 | |
| xmlTR for xmlTranscodeResult
 | |
| xmlTS for xmlTranscodeString
 | |
| xmlTW for xmlTranscodeWString
 | |
| xmlTH for xmlTranscodeHstring
 | |
| 
 | |
| These shorthands may be disabled by defining XML_NO_SHORT_NAMES before
 | |
| libxml/transcode.h inclusion.
 | |
| 
 | |
| A directory pointer must be preset to NULL before the first call using it to
 | |
| one of the above procedure.
 | |
| 
 | |
| To release a latching directory, use function
 | |
| 
 | |
| void          xmlZapDict(xmlDictPtr * dict);
 | |
| 
 | |
| 
 | |
| Example:
 | |
| 
 | |
| #include <libxml/transcode.h>
 | |
| #include <libxml/tree.h>
 | |
| 
 | |
| xmlDocPtr mySimpleXMLDoc(char * element, char * text)
 | |
| {
 | |
|         xmlDocPtr doc;
 | |
|         xmlNodePtr node;
 | |
|         xmlDictPtr dict = NULL;
 | |
| 
 | |
|         /* element and text are encoded in the current job's encoding. */
 | |
| 
 | |
|         doc = xmlNewDoc();
 | |
|         xmlNewTextChild((xmlNodePtr) doc, NULL, xmlTS(element, NULL,
 | |
|                                &dict), xmlTS(text, NULL, &dict));
 | |
|         xmlZapDict(&dict);
 | |
|         return doc;
 | |
| }
 | |
| 
 | |
| 
 | |
| Additionally, a formatter into latched/dynamic storage is provided:
 | |
| 
 | |
| const char *    xmlVasprintf(xmlDictPtr * dict,
 | |
|                              const char * encoding,
 | |
|                              const xmlChar * fmt,
 | |
|                              va_list args);
 | |
| 
 | |
| 
 | |
| xmllint and xmlcatalog programs:
 | |
| 
 | |
|   These programs are fully implemented at the qshell level, with standard
 | |
| command line options. Links to these are installed in sub-directory bin of
 | |
| the IFS installation directory.
 | |
|   CL command interfaces to these programs are also provided with limited
 | |
| support. In particular, interactive mode is not supported and argument count
 | |
| and lengths are limited by the CL command syntax.
 | |
| 
 | |
| 
 | |
| ILE/RPG binding:
 | |
| 
 | |
|   All standard types and procedures are provided. Since ILE/RPG does not
 | |
| support macros, they have not been ported. However some of them are emulated
 | |
| as functions: these are the more useful ones (xmlXPathNodeSetGetLength,
 | |
| xmlXPathNodeSetItem, xmlXPathNodeSetIsEmpty, htmlDefaultSubelement,
 | |
| htmlElementAllowedHereDesc, htmlRequiredAttrs) and the global/threaded
 | |
| variables access macros. These variables can be read with function
 | |
| get_xxx(void), where xxxx is the name of the variable; they may be set by
 | |
| calling function set_xxxx(value), where value is of the same type as the
 | |
| variable.
 | |
| 
 | |
|   The C va_list is not implemented as such in ILE/RPG. Functions implementing
 | |
| va_list and associated methods are provided:
 | |
| 
 | |
|       /include "libxmlrpg/xmlstdarg"
 | |
| 
 | |
|      d xmlVaStart      pr
 | |
|      d  list                               like(xmlVaList)
 | |
|      d  lastargaddr                    *   value
 | |
|      d  lastargsize                  10u 0 value
 | |
| 
 | |
|      d xmlVaArg        pr
 | |
|      d  list                               like(xmlVaList)
 | |
|      d  dest                           *   value
 | |
|      d  argsize                      10i 0 value
 | |
| 
 | |
|      d xmlVaEnd        pr
 | |
|      d  list                               like(xmlVaList)
 |