6f1e4ff4d053874563440709784c8b43d4244e91
[platform/upstream/libxml2.git] / os400 / xmlcatlgcl.c
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. */
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 }