1 /** 2 *** XMLCATALOG command response program. 3 *** 4 *** See Copyright for the status of this software. 5 *** 6 *** Author: Patrick Monnerat <pm (at) 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. */ 16 typedef struct { 17 short len; 18 char string[5000]; 19 } vary2; 20 21 22 /* Variable-length string, with 32-bit length. */ 23 typedef 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. */ 40 typedef 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. */ 48 typedef 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. */ 56 typedef 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. */ 73 extern 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 81 static void 82 vary4nappend(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 95 static void 96 vary4append(vary4 * dst, const char * src) 97 98 { 99 vary4nappend(dst, src, strlen(src)); 100 } 101 102 103 static void 104 vary4arg(vary4 * dst, const char * arg) 105 106 { 107 vary4nappend(dst, " ", 1); 108 vary4append(dst, arg); 109 } 110 111 112 static void 113 vary4varg(vary4 * dst, vary2 * arg) 114 115 { 116 vary4nappend(dst, " ", 1); 117 vary4nappend(dst, arg->string, arg->len); 118 } 119 120 121 static void 122 vary4vescape(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 135 static void 136 vary4vargquote(vary4 * dst, vary2 * arg) 137 138 { 139 vary4nappend(dst, " '", 2); 140 vary4vescape(dst, arg); 141 vary4nappend(dst, "'", 1); 142 } 143 144 145 int 146 main(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