1/** 2*** XMLCATALOG command response program. 3*** 4*** See Copyright for the status of this software. 5*** 6*** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A. 7**/ 8 9#include <stdio.h> 10#include <stdlib.h> 11#include <string.h> 12#include <qshell.h> 13 14 15/* Variable-length string, with 16-bit length. */ 16typedef struct { 17 short len; 18 char string[5000]; 19} vary2; 20 21 22/* Variable-length string, with 32-bit length. */ 23typedef struct { 24 int len; 25 char string[5000]; 26} vary4; 27 28 29/* Multiple occurrence parameter list. */ 30#define paramlist(itemsize, itemtype) \ 31 _Packed struct { \ 32 short len; \ 33 _Packed union { \ 34 char _pad[itemsize]; \ 35 itemtype param; \ 36 } item[1]; \ 37 } 38 39/* Add element list structure. */ 40typedef struct { 41 short elcount; /* Element count (=3). */ 42 paramlist(16, char) type; /* vary2(16). */ 43 paramlist(256, char) origin; /* vary2(256). */ 44 paramlist(256, char) replace; /* vary2(256). */ 45} addelement; 46 47/* SGML add element list structure. */ 48typedef struct { 49 short elcount; /* Element count (=3). */ 50 paramlist(256, char) catalog; /* vary2(256). */ 51 paramlist(256, char) ident; /* vary2(256). */ 52} sgmladdelement; 53 54 55/* Arguments from CL command. */ 56typedef struct { 57 char * pgm; /* Program name. */ 58 vary2 * instmf; /* Input catalog file name. */ 59 vary2 * kind; /* Catalog kind. */ 60 vary2 * outstmf; /* Output catalog file name. */ 61 vary2 * convert; /* Convert SGML to XML. */ 62 vary2 * superupd; /* --no-super-update. */ 63 vary2 * verbose; /* Verbose output. */ 64 paramlist(256 + 2, vary2) * delete; /* Identifiers to delete. */ 65 paramlist(2, unsigned short) * add; /* Items to add. */ 66 paramlist(2, unsigned short) * sgmladd; /* SGML items to add. */ 67 paramlist(256 + 2, vary2) * resolve; /* Identifiers to resolve. */ 68 paramlist(5000 + 2, vary2) * catalog; /* Additional catalog files. */ 69} arguments; 70 71 72/* Definition of QSHELL program. */ 73extern void qshell(vary4 * cmd); 74#pragma linkage(qshell, OS) 75#pragma map(qshell, "QSHELL/QZSHQSHC") 76 77/* Macro to handle displacements. */ 78#define OFFSETBY(t, p, n) ((t *) (((char *) (p)) + (n))) 79 80 81static void 82vary4nappend(vary4 * dst, const char * src, size_t len) 83 84{ 85 if (len > sizeof(dst->string) - dst->len) 86 len = sizeof(dst->string) - dst->len; 87 88 if (len) { 89 memcpy(dst->string + dst->len, src, len); 90 dst->len += len; 91 } 92} 93 94 95static void 96vary4append(vary4 * dst, const char * src) 97 98{ 99 vary4nappend(dst, src, strlen(src)); 100} 101 102 103static void 104vary4arg(vary4 * dst, const char * arg) 105 106{ 107 vary4nappend(dst, " ", 1); 108 vary4append(dst, arg); 109} 110 111 112static void 113vary4varg(vary4 * dst, vary2 * arg) 114 115{ 116 vary4nappend(dst, " ", 1); 117 vary4nappend(dst, arg->string, arg->len); 118} 119 120 121static void 122vary4vescape(vary4 * dst, vary2 * arg) 123 124{ 125 int i; 126 127 for (i = 0; i < arg->len; i++) 128 if (arg->string[i] == '\'') 129 vary4nappend(dst, "'\"'\"'", 5); 130 else 131 vary4nappend(dst, arg->string + i, 1); 132} 133 134 135static void 136vary4vargquote(vary4 * dst, vary2 * arg) 137 138{ 139 vary4nappend(dst, " '", 2); 140 vary4vescape(dst, arg); 141 vary4nappend(dst, "'", 1); 142} 143 144 145int 146main(int argsc, arguments * args) 147 148{ 149 vary4 cmd; 150 int i; 151 char c; 152 addelement * aelp; 153 sgmladdelement * saelp; 154 155 /* Specify additional catalogs. */ 156 cmd.len = 0; 157 if (args->catalog->len) { 158 for (i = 0; i < args->catalog->len && 159 !args->catalog->item[i].param.len; i++) 160 ; 161 162 vary4append(&cmd, "XML_CATALOG_FILES="); 163 if (i < args->catalog->len) { 164 c = '\''; 165 for (i = 0; i < args->catalog->len; i++) { 166 if (!args->catalog->item[i].param.len) 167 continue; 168 vary4nappend(&cmd, &c, 1); 169 c = ' '; 170 vary4vescape(&cmd, 171 &args->catalog->item[i].param); 172 } 173 vary4nappend(&cmd, "'", 1); 174 } 175 vary4nappend(&cmd, " ", 1); 176 } 177 178 /* find length of library name. */ 179 for (i = 0; i < 10 && args->pgm[i] && args->pgm[i] != '/'; i++) 180 ; 181 182 /* Store program name in command buffer. */ 183 vary4append(&cmd, "/QSYS.LIB/"); 184 vary4nappend(&cmd, args->pgm, i); 185 vary4append(&cmd, ".LIB/XMLCATALOG.PGM"); 186 187 /* Map command arguments to standard xmlcatalog argument vector. */ 188 if (args->kind && args->kind->len) 189 vary4varg(&cmd, args->kind); 190 191 if (args->verbose && args->verbose->len) 192 vary4varg(&cmd, args->verbose); 193 194 if (args->delete) 195 for (i = 0; i < args->delete->len; i++) { 196 vary4arg(&cmd, "--del"); 197 vary4vargquote(&cmd, &args->delete->item[i].param); 198 } 199 200 if (args->kind && args->kind->len) { 201 /* Process SGML-specific parameters. */ 202 if (args->superupd && args->superupd->len) 203 vary4varg(&cmd, args->superupd); 204 205 if (args->sgmladd) 206 for (i = 0; i < args->sgmladd->len; i++) { 207 saelp = OFFSETBY(sgmladdelement, args->sgmladd, 208 args->sgmladd->item[i].param); 209 if (!((vary2 *) &saelp->catalog)->len) 210 continue; 211 vary4arg(&cmd, "--add"); 212 vary4vargquote(&cmd, (vary2 *) &saelp->catalog); 213 vary4vargquote(&cmd, (vary2 *) &saelp->ident); 214 } 215 } 216 else { 217 /* Process XML-specific parameters. */ 218 if (args->convert && args->convert->len) 219 vary4varg(&cmd, args->convert); 220 221 if (args->add) 222 for (i = 0; i < args->add->len; i++) { 223 aelp = OFFSETBY(addelement, args->add, 224 args->add->item[i].param); 225 if (!((vary2 *) &aelp->origin)->len) 226 continue; 227 vary4arg(&cmd, "--add"); 228 vary4varg(&cmd, (vary2 *) &aelp->type); 229 vary4vargquote(&cmd, (vary2 *) &aelp->origin); 230 vary4vargquote(&cmd, (vary2 *) &aelp->replace); 231 } 232 } 233 234 /* Avoid INSTMF(*NEW) and OUTSMTF(*INSTMF). */ 235 if (args->outstmf && args->outstmf->len && !args->outstmf->string[0]) 236 if (args->instmf && args->instmf->len) 237 args->outstmf = args->instmf; 238 else 239 args->outstmf = NULL; 240 241 /* If INSTMF(*NEW) and OUTSTMF(somepath), Use --create --noout and 242 somepath as (unexisting) input file. */ 243 if (args->outstmf && args->outstmf->len) 244 if (!args->instmf || !args->instmf->len) { 245 vary4arg(&cmd, "--create"); 246 vary4arg(&cmd, "--noout"); 247 args->instmf = args->outstmf; 248 args->outstmf = NULL; 249 } 250 251 /* If output to input file, use --noout option. */ 252 if (args->instmf && args->outstmf && args->instmf->len && 253 args->instmf->len == args->outstmf->len && 254 !strncmp(args->instmf->string, args->outstmf->string, 255 args->instmf->len)) { 256 vary4arg(&cmd, "--noout"); 257 args->outstmf = NULL; 258 } 259 260 /* If no input file create catalog, else specify the input file name. */ 261 /* Specify the input file name: my be a dummy one. */ 262 if (!args->instmf || !args->instmf->len) { 263 vary4arg(&cmd, "--create -"); 264 vary4arg(&cmd, ".dmyxmlcatalog"); 265 } 266 else { 267 vary4arg(&cmd, "-"); 268 vary4vargquote(&cmd, args->instmf); 269 } 270 271 /* Query entities. */ 272 273 if (args->resolve) 274 for (i = 0; i < args->resolve->len; i++) 275 vary4vargquote(&cmd, &args->resolve->item[i].param); 276 277 /* Redirect output if requested. */ 278 if (args->outstmf && args->outstmf->len) { 279 vary4arg(&cmd, ">"); 280 vary4vargquote(&cmd, args->outstmf); 281 } 282 283 /* Execute the shell command. */ 284 qshell(&cmd); 285 286 /* Terminate. */ 287 exit(0); 288} 289