/** *** 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; /* SGML add element list structure. */ typedef struct { short elcount; /* Element count (=3). */ paramlist(256, char) catalog; /* vary2(256). */ paramlist(256, char) ident; /* vary2(256). */ } sgmladdelement; /* 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 * convert; /* Convert SGML to XML. */ 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(2, unsigned short) * sgmladd; /* SGML 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; sgmladdelement * saelp; /* 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->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->kind && args->kind->len) { /* Process SGML-specific parameters. */ if (args->superupd && args->superupd->len) vary4varg(&cmd, args->superupd); if (args->sgmladd) for (i = 0; i < args->sgmladd->len; i++) { saelp = OFFSETBY(sgmladdelement, args->sgmladd, args->sgmladd->item[i].param); if (!((vary2 *) &saelp->catalog)->len) continue; vary4arg(&cmd, "--add"); vary4vargquote(&cmd, (vary2 *) &saelp->catalog); vary4vargquote(&cmd, (vary2 *) &saelp->ident); } } else { /* Process XML-specific parameters. */ if (args->convert && args->convert->len) vary4varg(&cmd, args->convert); if (args->add) for (i = 0; i < args->add->len; i++) { aelp = OFFSETBY(addelement, args->add, args->add->item[i].param); if (!((vary2 *) &aelp->origin)->len) continue; vary4arg(&cmd, "--add"); vary4varg(&cmd, (vary2 *) &aelp->type); vary4vargquote(&cmd, (vary2 *) &aelp->origin); vary4vargquote(&cmd, (vary2 *) &aelp->replace); } } /* 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 { vary4arg(&cmd, "-"); 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); }