upload tizen1.0 source
[external/libxml2.git] / xmlcatalog.c
1 /*
2  * xmlcatalog.c : a small utility program to handle XML catalogs
3  *
4  * See Copyright for the status of this software.
5  *
6  * daniel@veillard.com
7  */
8
9 #include "libxml.h"
10
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14
15 #ifdef HAVE_STDLIB_H
16 #include <stdlib.h>
17 #endif
18
19 #ifdef HAVE_LIBREADLINE
20 #include <readline/readline.h>
21 #ifdef HAVE_LIBHISTORY
22 #include <readline/history.h>
23 #endif
24 #endif
25
26 #include <libxml/xmlmemory.h>
27 #include <libxml/uri.h>
28 #include <libxml/catalog.h>
29 #include <libxml/parser.h>
30 #include <libxml/globals.h>
31
32 #if defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
33 static int shell = 0;
34 static int sgml = 0;
35 static int noout = 0;
36 static int create = 0;
37 static int add = 0;
38 static int del = 0;
39 static int convert = 0;
40 static int no_super_update = 0;
41 static int verbose = 0;
42 static char *filename = NULL;
43
44
45 #ifndef XML_SGML_DEFAULT_CATALOG
46 #define XML_SGML_DEFAULT_CATALOG "/etc/sgml/catalog"
47 #endif
48
49 /************************************************************************
50  *                                                                      *
51  *                      Shell Interface                                 *
52  *                                                                      *
53  ************************************************************************/
54 /**
55  * xmlShellReadline:
56  * @prompt:  the prompt value
57  *
58  * Read a string
59  * 
60  * Returns a pointer to it or NULL on EOF the caller is expected to
61  *     free the returned string.
62  */
63 static char *
64 xmlShellReadline(const char *prompt) {
65 #ifdef HAVE_LIBREADLINE
66     char *line_read;
67
68     /* Get a line from the user. */
69     line_read = readline (prompt);
70
71     /* If the line has any text in it, save it on the history. */
72     if (line_read && *line_read)
73         add_history (line_read);
74
75     return (line_read);
76 #else
77     char line_read[501];
78     char *ret;
79     int len;
80
81     if (prompt != NULL)
82         fprintf(stdout, "%s", prompt);
83     if (!fgets(line_read, 500, stdin))
84         return(NULL);
85     line_read[500] = 0;
86     len = strlen(line_read);
87     ret = (char *) malloc(len + 1);
88     if (ret != NULL) {
89         memcpy (ret, line_read, len + 1);
90     }
91     return(ret);
92 #endif
93 }
94
95 static void usershell(void) {
96     char *cmdline = NULL, *cur;
97     int nbargs;
98     char command[100];
99     char arg[400];
100     char *argv[20];
101     int i, ret;
102     xmlChar *ans;
103
104     while (1) {
105         cmdline = xmlShellReadline("> ");
106         if (cmdline == NULL)
107             return;
108
109         /*
110          * Parse the command itself
111          */
112         cur = cmdline;
113         nbargs = 0;
114         while ((*cur == ' ') || (*cur == '\t')) cur++;
115         i = 0;
116         while ((*cur != ' ') && (*cur != '\t') &&
117                (*cur != '\n') && (*cur != '\r')) {
118             if (*cur == 0)
119                 break;
120             command[i++] = *cur++;
121         }
122         command[i] = 0;
123         if (i == 0) {
124             free(cmdline);
125             continue;
126         }
127
128         /*
129          * Parse the argument string
130          */
131         memset(arg, 0, sizeof(arg));
132         while ((*cur == ' ') || (*cur == '\t')) cur++;
133         i = 0;
134         while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
135             if (*cur == 0)
136                 break;
137             arg[i++] = *cur++;
138         }
139         arg[i] = 0;
140
141         /*
142          * Parse the arguments
143          */
144         i = 0;
145         nbargs = 0;
146         cur = arg;
147         memset(argv, 0, sizeof(argv));
148         while (*cur != 0) {
149             while ((*cur == ' ') || (*cur == '\t')) cur++;
150             if (*cur == '\'') {
151                 cur++;
152                 argv[i] = cur;
153                 while ((*cur != 0) && (*cur != '\'')) cur++;
154                 if (*cur == '\'') {
155                     *cur = 0;
156                     nbargs++;
157                     i++;
158                     cur++;
159                 }
160             } else if (*cur == '"') { 
161                 cur++;
162                 argv[i] = cur;
163                 while ((*cur != 0) && (*cur != '"')) cur++;
164                 if (*cur == '"') {
165                     *cur = 0;
166                     nbargs++;
167                     i++;
168                     cur++;
169                 }
170             } else {
171                 argv[i] = cur;
172                 while ((*cur != 0) && (*cur != ' ') && (*cur != '\t'))
173                     cur++;
174                 *cur = 0;
175                 nbargs++;
176                 i++;
177                 cur++;
178             }
179         }
180
181         /*
182          * start interpreting the command
183          */
184         if (!strcmp(command, "exit"))
185             break;
186         if (!strcmp(command, "quit"))
187             break;
188         if (!strcmp(command, "bye"))
189             break;
190         if (!strcmp(command, "public")) {
191             if (nbargs != 1) {
192                 printf("public requires 1 arguments\n");
193             } else {
194                 ans = xmlCatalogResolvePublic((const xmlChar *) argv[0]);
195                 if (ans == NULL) {
196                     printf("No entry for PUBLIC %s\n", argv[0]);
197                 } else {
198                     printf("%s\n", (char *) ans);
199                     xmlFree(ans);
200                 }
201             }
202         } else if (!strcmp(command, "system")) {
203             if (nbargs != 1) {
204                 printf("system requires 1 arguments\n");
205             } else {
206                 ans = xmlCatalogResolveSystem((const xmlChar *) argv[0]);
207                 if (ans == NULL) {
208                     printf("No entry for SYSTEM %s\n", argv[0]);
209                 } else {
210                     printf("%s\n", (char *) ans);
211                     xmlFree(ans);
212                 }
213             }
214         } else if (!strcmp(command, "add")) {
215             if (sgml) {
216                 if ((nbargs != 3) && (nbargs != 2)) {
217                     printf("add requires 2 or 3 arguments\n");
218                 } else {
219                     if (argv[2] == NULL)
220                         ret = xmlCatalogAdd(BAD_CAST argv[0], NULL,
221                                             BAD_CAST argv[1]);
222                     else
223                         ret = xmlCatalogAdd(BAD_CAST argv[0], BAD_CAST argv[1],
224                                             BAD_CAST argv[2]);
225                     if (ret != 0)
226                         printf("add command failed\n");
227                 }
228             } else {
229                 if ((nbargs != 3) && (nbargs != 2)) {
230                     printf("add requires 2 or 3 arguments\n");
231                 } else {
232                     if (argv[2] == NULL)
233                         ret = xmlCatalogAdd(BAD_CAST argv[0], NULL,
234                                             BAD_CAST argv[1]);
235                     else
236                         ret = xmlCatalogAdd(BAD_CAST argv[0], BAD_CAST argv[1],
237                                             BAD_CAST argv[2]);
238                     if (ret != 0)
239                         printf("add command failed\n");
240                 }
241             }
242         } else if (!strcmp(command, "del")) {
243             if (nbargs != 1) {
244                 printf("del requires 1\n");
245             } else {
246                 ret = xmlCatalogRemove(BAD_CAST argv[0]);
247                 if (ret <= 0)
248                     printf("del command failed\n");
249
250             }
251         } else if (!strcmp(command, "resolve")) {
252             if (nbargs != 2) {
253                 printf("resolve requires 2 arguments\n");
254             } else {
255                 ans = xmlCatalogResolve(BAD_CAST argv[0],
256                                         BAD_CAST argv[1]);
257                 if (ans == NULL) {
258                     printf("Resolver failed to find an answer\n");
259                 } else {
260                     printf("%s\n", (char *) ans);
261                     xmlFree(ans);
262                 }
263             }
264         } else if (!strcmp(command, "dump")) {
265             if (nbargs != 0) {
266                 printf("dump has no arguments\n");
267             } else {
268                 xmlCatalogDump(stdout);
269             }
270         } else if (!strcmp(command, "debug")) {
271             if (nbargs != 0) {
272                 printf("debug has no arguments\n");
273             } else {
274                 verbose++;
275                 xmlCatalogSetDebug(verbose);
276             }
277         } else if (!strcmp(command, "quiet")) {
278             if (nbargs != 0) {
279                 printf("quiet has no arguments\n");
280             } else {
281                 if (verbose > 0)
282                     verbose--;
283                 xmlCatalogSetDebug(verbose);
284             }
285         } else {
286             if (strcmp(command, "help")) {
287                 printf("Unrecognized command %s\n", command);
288             }
289             printf("Commands available:\n");
290             printf("\tpublic PublicID: make a PUBLIC identifier lookup\n");
291             printf("\tsystem SystemID: make a SYSTEM identifier lookup\n");
292             printf("\tresolve PublicID SystemID: do a full resolver lookup\n");
293             printf("\tadd 'type' 'orig' 'replace' : add an entry\n");
294             printf("\tdel 'values' : remove values\n");
295             printf("\tdump: print the current catalog state\n");
296             printf("\tdebug: increase the verbosity level\n");
297             printf("\tquiet: decrease the verbosity level\n");
298             printf("\texit:  quit the shell\n");
299         } 
300         free(cmdline); /* not xmlFree here ! */
301     }
302 }
303
304 /************************************************************************
305  *                                                                      *
306  *                      Main                                            *
307  *                                                                      *
308  ************************************************************************/
309 static void usage(const char *name) {
310     /* split into 2 printf's to avoid overly long string (gcc warning) */
311     printf("\
312 Usage : %s [options] catalogfile entities...\n\
313 \tParse the catalog file and query it for the entities\n\
314 \t--sgml : handle SGML Super catalogs for --add and --del\n\
315 \t--shell : run a shell allowing interactive queries\n\
316 \t--create : create a new catalog\n\
317 \t--add 'type' 'orig' 'replace' : add an XML entry\n\
318 \t--add 'entry' : add an SGML entry\n", name);
319     printf("\
320 \t--del 'values' : remove values\n\
321 \t--noout: avoid dumping the result on stdout\n\
322 \t         used with --add or --del, it saves the catalog changes\n\
323 \t         and with --sgml it automatically updates the super catalog\n\
324 \t--no-super-update: do not update the SGML super catalog\n\
325 \t-v --verbose : provide debug informations\n");
326 }
327 int main(int argc, char **argv) {
328     int i;
329     int ret;
330     int exit_value = 0;
331
332
333     if (argc <= 1) {
334         usage(argv[0]);
335         return(1);
336     }
337
338     LIBXML_TEST_VERSION
339     for (i = 1; i < argc ; i++) {
340         if (!strcmp(argv[i], "-"))
341             break;
342
343         if (argv[i][0] != '-')
344             break;
345         if ((!strcmp(argv[i], "-verbose")) ||
346             (!strcmp(argv[i], "-v")) ||
347             (!strcmp(argv[i], "--verbose"))) {
348             verbose++;
349             xmlCatalogSetDebug(verbose);
350         } else if ((!strcmp(argv[i], "-noout")) ||
351             (!strcmp(argv[i], "--noout"))) {
352             noout = 1;
353         } else if ((!strcmp(argv[i], "-shell")) ||
354             (!strcmp(argv[i], "--shell"))) {
355             shell++;
356             noout = 1;
357         } else if ((!strcmp(argv[i], "-sgml")) ||
358             (!strcmp(argv[i], "--sgml"))) {
359             sgml++;
360         } else if ((!strcmp(argv[i], "-create")) ||
361             (!strcmp(argv[i], "--create"))) {
362             create++;
363         } else if ((!strcmp(argv[i], "-convert")) ||
364             (!strcmp(argv[i], "--convert"))) {
365             convert++;
366         } else if ((!strcmp(argv[i], "-no-super-update")) ||
367             (!strcmp(argv[i], "--no-super-update"))) {
368             no_super_update++;
369         } else if ((!strcmp(argv[i], "-add")) ||
370             (!strcmp(argv[i], "--add"))) {
371             if (sgml)
372                 i += 2;
373             else
374                 i += 3;
375             add++;
376         } else if ((!strcmp(argv[i], "-del")) ||
377             (!strcmp(argv[i], "--del"))) {
378             i += 1;
379             del++;
380         } else {
381             fprintf(stderr, "Unknown option %s\n", argv[i]);
382             usage(argv[0]);
383             return(1);
384         }
385     }
386
387     for (i = 1; i < argc; i++) {
388         if ((!strcmp(argv[i], "-add")) ||
389             (!strcmp(argv[i], "--add"))) {
390             if (sgml)
391                 i += 2;
392             else
393                 i += 3;
394             continue;
395         } else if ((!strcmp(argv[i], "-del")) ||
396             (!strcmp(argv[i], "--del"))) {
397             i += 1;
398
399             /* No catalog entry specified */
400             if (i == argc || (sgml && i + 1 == argc)) {
401                 fprintf(stderr, "No catalog entry specified to remove from\n");
402                 usage (argv[0]);
403                 return(1);
404             }
405
406             continue;
407         } else if (argv[i][0] == '-')
408             continue;
409         filename = argv[i];
410             ret = xmlLoadCatalog(argv[i]);
411             if ((ret < 0) && (create)) {
412                 xmlCatalogAdd(BAD_CAST "catalog", BAD_CAST argv[i], NULL);
413             }
414         break;
415     }
416
417     if (convert)
418         ret = xmlCatalogConvert();
419
420     if ((add) || (del)) {
421         for (i = 1; i < argc ; i++) {
422             if (!strcmp(argv[i], "-"))
423                 break;
424
425             if (argv[i][0] != '-')
426                 continue;
427             if (strcmp(argv[i], "-add") && strcmp(argv[i], "--add") &&
428                 strcmp(argv[i], "-del") && strcmp(argv[i], "--del"))
429                 continue;
430
431             if (sgml) {
432                 /*
433                  * Maintenance of SGML catalogs.
434                  */
435                 xmlCatalogPtr catal = NULL;
436                 xmlCatalogPtr super = NULL;
437
438                 catal = xmlLoadSGMLSuperCatalog(argv[i + 1]);
439
440                 if ((!strcmp(argv[i], "-add")) ||
441                     (!strcmp(argv[i], "--add"))) {
442                     if (catal == NULL)
443                         catal = xmlNewCatalog(1);
444                     xmlACatalogAdd(catal, BAD_CAST "CATALOG",
445                                          BAD_CAST argv[i + 2], NULL);
446
447                     if (!no_super_update) {
448                         super = xmlLoadSGMLSuperCatalog(XML_SGML_DEFAULT_CATALOG);
449                         if (super == NULL)
450                             super = xmlNewCatalog(1);
451
452                         xmlACatalogAdd(super, BAD_CAST "CATALOG",
453                                              BAD_CAST argv[i + 1], NULL);
454                     }
455                 } else {
456                     if (catal != NULL)
457                         ret = xmlACatalogRemove(catal, BAD_CAST argv[i + 2]);
458                     else
459                         ret = -1;
460                     if (ret < 0) {
461                         fprintf(stderr, "Failed to remove entry from %s\n",
462                                 argv[i + 1]);
463                         exit_value = 1;
464                     }
465                     if ((!no_super_update) && (noout) && (catal != NULL) &&
466                         (xmlCatalogIsEmpty(catal))) {
467                         super = xmlLoadSGMLSuperCatalog(
468                                    XML_SGML_DEFAULT_CATALOG);
469                         if (super != NULL) {
470                             ret = xmlACatalogRemove(super,
471                                     BAD_CAST argv[i + 1]);
472                             if (ret < 0) {
473                                 fprintf(stderr,
474                                         "Failed to remove entry from %s\n",
475                                         XML_SGML_DEFAULT_CATALOG);
476                                 exit_value = 1;
477                             }
478                         }
479                     }
480                 }
481                 if (noout) {
482                     FILE *out;
483
484                     if (xmlCatalogIsEmpty(catal)) {
485                         remove(argv[i + 1]);
486                     } else {
487                         out = fopen(argv[i + 1], "w");
488                         if (out == NULL) {
489                             fprintf(stderr, "could not open %s for saving\n",
490                                     argv[i + 1]);
491                             exit_value = 2;
492                             noout = 0;
493                         } else {
494                             xmlACatalogDump(catal, out);
495                             fclose(out);
496                         }
497                     }
498                     if (!no_super_update && super != NULL) {
499                         if (xmlCatalogIsEmpty(super)) {
500                             remove(XML_SGML_DEFAULT_CATALOG);
501                         } else {
502                             out = fopen(XML_SGML_DEFAULT_CATALOG, "w");
503                             if (out == NULL) {
504                                 fprintf(stderr,
505                                         "could not open %s for saving\n",
506                                         XML_SGML_DEFAULT_CATALOG);
507                                 exit_value = 2;
508                                 noout = 0;
509                             } else {
510                                 
511                                 xmlACatalogDump(super, out);
512                                 fclose(out);
513                             }
514                         }
515                     }
516                 } else {
517                     xmlACatalogDump(catal, stdout);
518                 }
519                 i += 2;
520             } else {
521                 if ((!strcmp(argv[i], "-add")) ||
522                     (!strcmp(argv[i], "--add"))) {
523                         if ((argv[i + 3] == NULL) || (argv[i + 3][0] == 0))
524                             ret = xmlCatalogAdd(BAD_CAST argv[i + 1], NULL,
525                                                 BAD_CAST argv[i + 2]);
526                         else
527                             ret = xmlCatalogAdd(BAD_CAST argv[i + 1],
528                                                 BAD_CAST argv[i + 2],
529                                                 BAD_CAST argv[i + 3]);
530                         if (ret != 0) {
531                             printf("add command failed\n");
532                             exit_value = 3;
533                         }
534                         i += 3;
535                 } else if ((!strcmp(argv[i], "-del")) ||
536                     (!strcmp(argv[i], "--del"))) {
537                     ret = xmlCatalogRemove(BAD_CAST argv[i + 1]);
538                     if (ret < 0) {
539                         fprintf(stderr, "Failed to remove entry %s\n",
540                                 argv[i + 1]);
541                         exit_value = 1;
542                     }
543                     i += 1;
544                 }
545             }
546         }
547         
548     } else if (shell) {
549         usershell();
550     } else {
551         for (i++; i < argc; i++) {
552             xmlURIPtr uri;
553             xmlChar *ans;
554             
555             uri = xmlParseURI(argv[i]);
556             if (uri == NULL) {
557                 ans = xmlCatalogResolvePublic((const xmlChar *) argv[i]);
558                 if (ans == NULL) {
559                     printf("No entry for PUBLIC %s\n", argv[i]);
560                     exit_value = 4;
561                 } else {
562                     printf("%s\n", (char *) ans);
563                     xmlFree(ans);
564                 }
565             } else {
566                 xmlFreeURI(uri);
567                 ans = xmlCatalogResolveSystem((const xmlChar *) argv[i]);
568                 if (ans == NULL) {
569                     printf("No entry for SYSTEM %s\n", argv[i]);
570                     ans = xmlCatalogResolveURI ((const xmlChar *) argv[i]);
571                     if (ans == NULL) {
572                         printf ("No entry for URI %s\n", argv[i]);
573                         exit_value = 4;
574                     } else {
575                         printf("%s\n", (char *) ans);
576                         xmlFree (ans);
577                     }
578                 } else {
579                     printf("%s\n", (char *) ans);
580                     xmlFree(ans);
581                 }
582             }
583         }
584     }
585     if ((!sgml) && ((add) || (del) || (create) || (convert))) {
586         if (noout && filename && *filename) {
587             FILE *out;
588
589             out = fopen(filename, "w");
590             if (out == NULL) {
591                 fprintf(stderr, "could not open %s for saving\n", filename);
592                 exit_value = 2;
593                 noout = 0;
594             } else {
595                 xmlCatalogDump(out);
596             }
597         } else {
598             xmlCatalogDump(stdout);
599         }
600     }
601
602     /*
603      * Cleanup and check for memory leaks
604      */
605     xmlCleanupParser();
606     xmlMemoryDump();
607     return(exit_value);
608 }
609 #else
610 int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
611     fprintf(stderr, "libxml was not compiled with catalog and output support\n");
612     return(1);
613 }
614 #endif