/ libxml2 / os400 / xmllintcl.c
xmllintcl.c
  1  /**
  2  ***     XMLLINT 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. */
 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  }