diff --git a/os400/make-src.sh b/os400/make-src.sh index 6bd1c6966..6094de8e1 100644 --- a/os400/make-src.sh +++ b/os400/make-src.sh @@ -17,7 +17,7 @@ cd "${TOPDIR}" echo '#pragma comment(user, "libxml2 version '"${LIBXML_VERSION}"'")' > os400.c echo '#pragma comment(user, __DATE__)' >> os400.c echo '#pragma comment(user, __TIME__)' >> os400.c -echo '#pragma comment(copyright, "Copyright (C) 1998-2014 Daniel Veillard. OS/400 version by P. Monnerat.")' >> os400.c +echo '#pragma comment(copyright, "Copyright (C) 1998-2015 Daniel Veillard. OS/400 version by P. Monnerat.")' >> os400.c make_module OS400 os400.c LINK= # No need to rebuild service program yet. MODULES= @@ -250,7 +250,7 @@ make_module --ebcdic --sysiconv LIBXMLMAIN "${SCRIPTDIR}/libxmlmain.c" if action_needed "${LIBIFSNAME}/XMLLINT.PGM" "xmllint.c" || action_needed "${LIBIFSNAME}/XMLLINT.PGM" "${LIBIFSNAME}/${SRVPGM}.SRVPGM" || - action_needed "${LIBIFSNAME}/XMLLINT.PGM" "${LIBIFSNAME}/LIMXMLMAIN.MODULE" + action_needed "${LIBIFSNAME}/XMLLINT.PGM" "${LIBIFSNAME}/LIBXMLMAIN.MODULE" then make_module XMLLINT xmllint.c CMD="CRTPGM PGM(${TARGETLIB}/XMLLINT) MODULE(${TARGETLIB}/XMLLINT)" CMD="${CMD} ENTMOD(${TARGETLIB}/LIBXMLMAIN)" @@ -306,7 +306,7 @@ if action_needed "${LIBIFSNAME}/XMLCATALOG.PGM" "xmlcatalog.c" || action_needed "${LIBIFSNAME}/XMLCATALOG.PGM" \ "${LIBIFSNAME}/${SRVPGM}.SRVPGM" || action_needed "${LIBIFSNAME}/XMLCATALOG.PGM" \ - "${LIBIFSNAME}/LIMXMLMAIN.MODULE" + "${LIBIFSNAME}/LIBXMLMAIN.MODULE" then make_module XMLCATALOG xmlcatalog.c CMD="CRTPGM PGM(${TARGETLIB}/XMLCATALOG)" CMD="${CMD} MODULE(${TARGETLIB}/XMLCATALOG)" @@ -325,3 +325,31 @@ fi rm -f "${IFSDIR}/bin/xmlcatalog" ln -s "${LIBIFSNAME}/XMLCATALOG.PGM" "${IFSDIR}/bin/xmlcatalog" + +# Prepare the XMLCATALOG command and its response program. + +if action_needed "${LIBIFSNAME}/XMLCATLGCL.PGM" "${SCRIPTDIR}/xmlcatlgcl.c" +then make_module --ebcdic XMLCATLGCL "${SCRIPTDIR}/xmlcatlgcl.c" + CMD="CRTPGM PGM(${TARGETLIB}/XMLCATLGCL)" + CMD="${CMD} MODULE(${TARGETLIB}/XMLCATLGCL)" + CMD="${CMD} ACTGRP(*NEW) TEXT('XMLCATALOG command response')" + CMD="${CMD} TGTRLS(${TGTRLS})" + system "${CMD}" + rm -f "${LIBIFSNAME}/XMLCATLGCL.MODULE" +fi + +if action_needed "${LIBIFSNAME}/TOOLS.FILE/XMLCATALOG.MBR" \ + "${SCRIPTDIR}/xmlcatalog.cmd" +then CMD="CPY OBJ('${SCRIPTDIR}/xmlcatalog.cmd')" + CMD="${CMD} TOOBJ('${LIBIFSNAME}/TOOLS.FILE/XMLCATALOG.MBR')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" +fi + +if action_needed "${LIBIFSNAME}/XMLCATALOG.CMD" \ + "${LIBIFSNAME}/TOOLS.FILE/XMLCATALOG.MBR" +then CMD="CRTCMD CMD(${TARGETLIB}/XMLCATALOG) PGM(${TARGETLIB}/XMLCATLGCL)" + CMD="${CMD} SRCFILE(${TARGETLIB}/TOOLS) SRCMBR(XMLCATALOG)" + CMD="${CMD} THDSAFE(*YES) TEXT('XML/SGML catalog tool') REPLACE(*YES)" + system "${CMD}" +fi diff --git a/os400/xmlcatalog.cmd b/os400/xmlcatalog.cmd new file mode 100644 index 000000000..aac523f2b --- /dev/null +++ b/os400/xmlcatalog.cmd @@ -0,0 +1,93 @@ +/* XMLCATALOG CL command. */ +/* */ +/* See Copyright for the status of this software. */ +/* */ +/* Author: Patrick Monnerat , DATASPHERE S.A. */ + +/* Interface to program XMLCATLGCL */ + + CMD PROMPT('XML/SGML catalog tool') + + /* Catalog file path. */ + + PARM KWD(INSTMF) TYPE(*PNAME) LEN(5000) VARY(*YES *INT2) + + CASE(*MIXED) EXPR(*YES) MIN(1) SPCVAL((*NEW '')) + + CHOICE('Stream file path') + + PROMPT('XML/SGML catalog file') + + /* Catalog kind: XML/SGML. */ + + PARM KWD(KIND) TYPE(*CHAR) LEN(7) VARY(*YES *INT2) + + EXPR(*YES) RSTD(*YES) DFT(*XML) + + SPCVAL((*XML '') (*SGML '--sgml')) + + PROMPT('Catalog kind') + + /* Output file. */ + + PARM KWD(OUTSTMF) TYPE(*PNAME) LEN(5000) VARY(*YES *INT2) + + CASE(*MIXED) EXPR(*YES) DFT(*STDOUT) + + SPCVAL((*STDOUT '') (*INSTMF X'00')) + + CHOICE('*STDOUT, *INSTMF or file path') + + PROMPT('Output stream file path') + + /* SGML super catalog update. */ + + PARM KWD(SUPERUPD) TYPE(*CHAR) LEN(17) VARY(*YES *INT2) + + SPCVAL((*YES '') (*NO '--no-super-update')) + + EXPR(*YES) DFT(*YES) RSTD(*YES) + + PROMPT('Update the SGML super catalog') + + /* Verbose/debug output. */ + + PARM KWD(VERBOSE) TYPE(*CHAR) LEN(4) VARY(*YES *INT2) + + RSTD(*YES) SPCVAL((*YES '-v') (*NO '')) + + EXPR(*YES) DFT(*NO) + + PROMPT('Output debugging information') + + /* Interactive shell not supported. */ + + /* Values to delete. */ + + PARM KWD(DELETE) TYPE(*PNAME) LEN(256) VARY(*YES *INT2) + + CASE(*MIXED) MAX(64) EXPR(*YES) + + CHOICE('Identifier value') + + PROMPT('Delete System/URI identifier') + + /* Values to add. */ + + PARM KWD(ADD) TYPE(ADDELEM) MAX(10) + + PROMPT('Add definition') +ADDELEM: ELEM TYPE(*CHAR) LEN(16) VARY(*YES *INT2) DFT(*PUBLIC) + + PROMPT('Entry type') + + EXPR(*YES) RSTD(*YES) SPCVAL( + + (*PUBLIC 'public') + + (*SYSTEM 'system') + + (*URI 'uri') + + (*REWRITESYSTEM 'rewriteSystem') + + (*REWRITEURI 'rewriteURI') + + (*DELEGATEPUBLIC 'delegatePublic') + + (*DELEGATESYSTEM 'delegateSystem') + + (*DELEGATEURI 'delegateURI') + + (*NEXTCATALOG 'nextCatalog') + + (*FILENAME '') + + ) + ELEM TYPE(*PNAME) LEN(256) VARY(*YES *INT2) EXPR(*YES) + + CASE(*MIXED) PROMPT('Original reference/file name') + ELEM TYPE(*PNAME) LEN(256) VARY(*YES *INT2) EXPR(*YES) + + CASE(*MIXED) PROMPT('Replacement entity URI') + + /* Entities to resolve. */ + + PARM KWD(ENTITY) TYPE(*PNAME) LEN(256) VARY(*YES *INT2) + + CASE(*MIXED) EXPR(*YES) MAX(150) + + PROMPT('Resolve entity') + + /* Additional catalog files. */ + + PARM KWD(CATALOG) TYPE(*PNAME) LEN(5000) VARY(*YES *INT2) + + CASE(*MIXED) EXPR(*YES) MAX(150) DFT(*DEFAULT) + + CHOICE('Catalog stream file path') + + PROMPT('Additional catalog file') SPCVAL( + + (*DEFAULT '/etc/xml/catalog') + + (*NONE '') + + ) diff --git a/os400/xmlcatlgcl.c b/os400/xmlcatlgcl.c new file mode 100644 index 000000000..c178b41d7 --- /dev/null +++ b/os400/xmlcatlgcl.c @@ -0,0 +1,259 @@ +/** +*** XMLCATALOG command response program. +*** +*** See Copyright for the status of this software. +*** +*** Author: Patrick Monnerat , DATASPHERE S.A. +**/ + +#include +#include +#include +#include + + +/* Variable-length string, with 16-bit length. */ +typedef struct { + short len; + char string[5000]; +} vary2; + + +/* Variable-length string, with 32-bit length. */ +typedef struct { + int len; + char string[5000]; +} vary4; + + +/* Multiple occurrence parameter list. */ +#define paramlist(itemsize, itemtype) \ + _Packed struct { \ + short len; \ + _Packed union { \ + char _pad[itemsize]; \ + itemtype param; \ + } item[1]; \ + } + +/* Add element list structure. */ +typedef struct { + short elcount; /* Element count (=3). */ + paramlist(16, char) type; /* vary2(16). */ + paramlist(256, char) origin; /* vary2(256). */ + paramlist(256, char) replace; /* vary2(256). */ +} addelement; + + +/* Arguments from CL command. */ +typedef struct { + char * pgm; /* Program name. */ + vary2 * instmf; /* Input catalog file name. */ + vary2 * kind; /* Catalog kind. */ + vary2 * outstmf; /* Output catalog file name. */ + vary2 * superupd; /* --no-super-update. */ + vary2 * verbose; /* Verbose output. */ + paramlist(256 + 2, vary2) * delete; /* Identifiers to delete. */ + paramlist(2, unsigned short) * add; /* Items to add. */ + paramlist(256 + 2, vary2) * resolve; /* Identifiers to resolve. */ + paramlist(5000 + 2, vary2) * catalog; /* Additional catalog files. */ +} arguments; + + +/* Definition of QSHELL program. */ +extern void qshell(vary4 * cmd); +#pragma linkage(qshell, OS) +#pragma map(qshell, "QSHELL/QZSHQSHC") + +/* Macro to handle displacements. */ +#define OFFSETBY(t, p, n) ((t *) (((char *) (p)) + (n))) + + +static void +vary4nappend(vary4 * dst, const char * src, size_t len) + +{ + if (len > sizeof(dst->string) - dst->len) + len = sizeof(dst->string) - dst->len; + + if (len) { + memcpy(dst->string + dst->len, src, len); + dst->len += len; + } +} + + +static void +vary4append(vary4 * dst, const char * src) + +{ + vary4nappend(dst, src, strlen(src)); +} + + +static void +vary4arg(vary4 * dst, const char * arg) + +{ + vary4nappend(dst, " ", 1); + vary4append(dst, arg); +} + + +static void +vary4varg(vary4 * dst, vary2 * arg) + +{ + vary4nappend(dst, " ", 1); + vary4nappend(dst, arg->string, arg->len); +} + + +static void +vary4vescape(vary4 * dst, vary2 * arg) + +{ + int i; + + for (i = 0; i < arg->len; i++) + if (arg->string[i] == '\'') + vary4nappend(dst, "'\"'\"'", 5); + else + vary4nappend(dst, arg->string + i, 1); +} + + +static void +vary4vargquote(vary4 * dst, vary2 * arg) + +{ + vary4nappend(dst, " '", 2); + vary4vescape(dst, arg); + vary4nappend(dst, "'", 1); +} + + +int +main(int argsc, arguments * args) + +{ + vary4 cmd; + int i; + char c; + addelement * aelp; + + /* Specify additional catalogs. */ + cmd.len = 0; + if (args->catalog->len) { + for (i = 0; i < args->catalog->len && + !args->catalog->item[i].param.len; i++) + ; + + vary4append(&cmd, "XML_CATALOG_FILES="); + if (i < args->catalog->len) { + c = '\''; + for (i = 0; i < args->catalog->len; i++) { + if (!args->catalog->item[i].param.len) + continue; + vary4nappend(&cmd, &c, 1); + c = ' '; + vary4vescape(&cmd, + &args->catalog->item[i].param); + } + vary4nappend(&cmd, "'", 1); + } + vary4nappend(&cmd, " ", 1); + } + + /* find length of library name. */ + for (i = 0; i < 10 && args->pgm[i] && args->pgm[i] != '/'; i++) + ; + + /* Store program name in command buffer. */ + vary4append(&cmd, "/QSYS.LIB/"); + vary4nappend(&cmd, args->pgm, i); + vary4append(&cmd, ".LIB/XMLCATALOG.PGM"); + + /* Map command arguments to standard xmlcatalog argument vector. */ + if (args->kind && args->kind->len) + vary4varg(&cmd, args->kind); + + if (args->superupd && args->superupd->len) + vary4varg(&cmd, args->superupd); + + if (args->verbose && args->verbose->len) + vary4varg(&cmd, args->verbose); + + if (args->delete) + for (i = 0; i < args->delete->len; i++) { + vary4arg(&cmd, "--del"); + vary4vargquote(&cmd, &args->delete->item[i].param); + } + + if (args->add) + for (i = 0; i < args->add->len; i++) { + aelp = OFFSETBY(addelement, + args->add, args->add->item[i].param); + vary4arg(&cmd, "--add"); + if (((vary2 *) &aelp->type)->len) { + vary4varg(&cmd, (vary2 *) &aelp->type); + vary4vargquote(&cmd, (vary2 *) &aelp->origin); + vary4vargquote(&cmd, (vary2 *) &aelp->replace); + } + else + vary4vargquote(&cmd, (vary2 *) &aelp->origin); + } + + /* Avoid INSTMF(*NEW) and OUTSMTF(*INSTMF). */ + if (args->outstmf && args->outstmf->len && !args->outstmf->string[0]) + if (args->instmf && args->instmf->len) + args->outstmf = args->instmf; + else + args->outstmf = NULL; + + /* If INSTMF(*NEW) and OUTSTMF(somepath), Use --create --noout and + somepath as (unexisting) input file. */ + if (args->outstmf && args->outstmf->len) + if (!args->instmf || !args->instmf->len) { + vary4arg(&cmd, "--create"); + vary4arg(&cmd, "--noout"); + args->instmf = args->outstmf; + args->outstmf = NULL; + } + + /* If output to input file, use --noout option. */ + if (args->instmf && args->outstmf && args->instmf->len && + args->instmf->len == args->outstmf->len && + !strncmp(args->instmf->string, args->outstmf->string, + args->instmf->len)) { + vary4arg(&cmd, "--noout"); + args->outstmf = NULL; + } + + /* If no input file create catalog, else specify the input file name. */ + /* Specify the input file name: my be a dummy one. */ + if (!args->instmf || !args->instmf->len) { + vary4arg(&cmd, "--create"); + vary4arg(&cmd, ".dmyxmlcatalog"); + } + else + vary4vargquote(&cmd, args->instmf); + + /* Query entities. */ + + if (args->resolve) + for (i = 0; i < args->resolve->len; i++) + vary4vargquote(&cmd, &args->resolve->item[i].param); + + /* Redirect output if requested. */ + if (args->outstmf && args->outstmf->len) { + vary4arg(&cmd, ">"); + vary4vargquote(&cmd, args->outstmf); + } + + /* Execute the shell command. */ + qshell(&cmd); + + /* Terminate. */ + exit(0); +}