1 /** 2 *** XMLLINT 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 union { \ 34 char _pad[itemsize]; \ 35 itemtype param; \ 36 } item[1]; \ 37 } 38 39 40 /* Arguments from CL command. */ 41 typedef struct { 42 char * pgm; /* Program name. */ 43 vary2 * stmf; /* XML file name or URL. */ 44 vary2 * dtd; /* DTD location or public identifier. */ 45 char * dtdvalid; /* *DTDURL or *DTDFPI. */ 46 vary2 * schema; /* Schema file name or URL. */ 47 vary2 * schemakind; /* --schema/--relaxng/--schematron. */ 48 vary2 * outstmf; /* Output stream file name. */ 49 vary2 * xpath; /* XPath filter. */ 50 vary2 * pattern; /* Reader filter pattern. */ 51 paramlist(5000 + 2, vary2) * path; /* Path for resources. */ 52 vary2 * pretty; /* Pretty-print style. */ 53 unsigned long * maxmem; /* Maximum dynamic memory. */ 54 vary2 * encoding; /* Output encoding. */ 55 paramlist(20 + 2, vary2) * options; /* Other options. */ 56 } arguments; 57 58 59 /* Definition of QSHELL program. */ 60 extern void qshell(vary4 * cmd); 61 #pragma linkage(qshell, OS) 62 #pragma map(qshell, "QSHELL/QZSHQSHC") 63 64 65 static void 66 vary4nappend(vary4 * dst, const char * src, size_t len) 67 68 { 69 if (len > sizeof(dst->string) - dst->len) 70 len = sizeof(dst->string) - dst->len; 71 72 if (len) { 73 memcpy(dst->string + dst->len, src, len); 74 dst->len += len; 75 } 76 } 77 78 79 static void 80 vary4append(vary4 * dst, const char * src) 81 82 { 83 vary4nappend(dst, src, strlen(src)); 84 } 85 86 87 static void 88 vary4arg(vary4 * dst, const char * arg) 89 90 { 91 vary4nappend(dst, " ", 1); 92 vary4append(dst, arg); 93 } 94 95 96 static void 97 vary4varg(vary4 * dst, vary2 * arg) 98 99 { 100 vary4nappend(dst, " ", 1); 101 vary4nappend(dst, arg->string, arg->len); 102 } 103 104 105 static void 106 vary4vescape(vary4 * dst, vary2 * arg) 107 108 { 109 int i; 110 111 for (i = 0; i < arg->len; i++) 112 if (arg->string[i] == '\'') 113 vary4nappend(dst, "'\"'\"'", 5); 114 else 115 vary4nappend(dst, arg->string + i, 1); 116 } 117 118 119 static void 120 vary4vargquote(vary4 * dst, vary2 * arg) 121 122 { 123 vary4nappend(dst, " '", 2); 124 vary4vescape(dst, arg); 125 vary4nappend(dst, "'", 1); 126 } 127 128 129 int 130 main(int argsc, arguments * args) 131 132 { 133 vary4 cmd; 134 int i; 135 char textbuf[20]; 136 char * lang; 137 138 /* find length of library name. */ 139 for (i = 0; i < 10 && args->pgm[i] && args->pgm[i] != '/'; i++) 140 ; 141 142 /* Store program name in command buffer. */ 143 cmd.len = 0; 144 vary4append(&cmd, "/QSYS.LIB/"); 145 vary4nappend(&cmd, args->pgm, i); 146 vary4append(&cmd, ".LIB/XMLLINT.PGM"); 147 148 /* Map command arguments to standard xmllint argument vector. */ 149 150 if (args->dtd && args->dtd->len) { 151 if (args->dtdvalid && args->dtdvalid[4] == 'F') 152 vary4arg(&cmd, "--dtdvalidfpi"); 153 else 154 vary4arg(&cmd, "--dtdvalid"); 155 156 vary4vargquote(&cmd, args->dtd); 157 } 158 159 if (args->schema && args->schema->len) { 160 vary4varg(&cmd, args->schemakind); 161 vary4vargquote(&cmd, args->schema); 162 } 163 164 if (args->outstmf && args->outstmf->len) { 165 vary4arg(&cmd, "--output"); 166 vary4vargquote(&cmd, args->outstmf); 167 168 if (args->encoding && args->encoding->len) { 169 vary4arg(&cmd, "--encoding"); 170 vary4vargquote(&cmd, args->encoding); 171 } 172 } 173 174 if (args->xpath && args->xpath->len) { 175 vary4arg(&cmd, "--xpath"); 176 vary4vargquote(&cmd, args->xpath); 177 } 178 179 if (args->pattern && args->pattern->len) { 180 vary4arg(&cmd, "--pattern"); 181 vary4vargquote(&cmd, args->pattern); 182 } 183 184 if (args->path && args->path->len) { 185 vary4arg(&cmd, "--path '"); 186 vary4vescape(&cmd, &args->path->item[0].param); 187 for (i = 1; i < args->path->len; i++) { 188 vary4nappend(&cmd, ":", 1); 189 vary4vescape(&cmd, &args->path->item[i].param); 190 } 191 vary4nappend(&cmd, "'", 1); 192 } 193 194 if (args->pretty && args->pretty->len && 195 args->pretty->string[0] != '0') { 196 vary4arg(&cmd, "--pretty"); 197 vary4varg(&cmd, args->pretty); 198 } 199 200 if (args->maxmem && *args->maxmem) { 201 snprintf(textbuf, sizeof textbuf, "%lu", *args->maxmem); 202 vary4arg(&cmd, "--maxmem"); 203 vary4arg(&cmd, textbuf); 204 } 205 206 for (i = 0; i < args->options->len; i++) 207 vary4varg(&cmd, &args->options->item[i].param); 208 209 vary4vargquote(&cmd, args->stmf); 210 211 /* Execute the shell command. */ 212 qshell(&cmd); 213 214 /* Terminate. */ 215 exit(0); 216 } 217