00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "config.h"
00032
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <fcntl.h>
00036 #include <ctype.h>
00037 #include <string.h>
00038 #include <errno.h>
00039
00040 #ifndef WIN32
00041 #include <unistd.h>
00042 #endif
00043
00044 #ifdef HAVE_GETOPT_H
00045 #include <getopt.h>
00046 #endif
00047
00048 #include <cmml.h>
00049
00079 #define BUFSIZE 100000
00080
00081
00082
00083
00084
00088 static int verbose;
00089
00095 static void
00096 PrintUsage(char *prog) {
00097 fprintf(stderr, "Usage: %s [options] filename\n", prog);
00098 fprintf(stderr, "Validate a CMML file.\n\n");
00099 fprintf(stderr, "Possible options:\n");
00100 #ifdef HAVE_GETOPT_LONG
00101 fprintf(stderr, " -i clip_id, --id clip_id\n");
00102 fprintf(stderr, " Start parsing from the named clip.\n");
00103 fprintf(stderr, " -s seconds, --sec seconds\n");
00104 fprintf(stderr, " Start parsing from the given seconds offset\n");
00105 fprintf(stderr, " -u utc, --utc utc\n");
00106 fprintf(stderr, " Start parsing from the given utc time\n");
00107 fprintf(stderr, " -b, --verbose Output parsed file to stdout\n");
00108 fprintf(stderr, " -h, --help Display this help information\n");
00109 fprintf(stderr, " -v, --version Display version information\n");
00110 #else
00111 fprintf(stderr, " -i clip_id Start parsing from the named clip\n");
00112 fprintf(stderr, " -s seconds Start parsing from the given seconds offset\n");
00113 fprintf(stderr, " -u utc Start parsing from the given utc time\n");
00114 fprintf(stderr, " -b Output parsed file to stdout\n");
00115 fprintf(stderr, " -h Display this help information\n");
00116 fprintf(stderr, " -v Display version information\n");
00117 #endif
00118 fprintf(stderr, "\nPlease report bugs to <libcmml-devel@cmis.csiro.au>.\n");
00119 exit(1);
00120 }
00121
00132 static int
00133 read_stream (CMML * cmml, const CMML_Stream * stream, void * user_data) {
00134 char buf[BUFSIZE];
00135 CMML_Error * err;
00136 if ((err = cmml_get_last_error(cmml)) != NULL) {
00137 cmml_error_snprint(buf, BUFSIZE, err, cmml);
00138 fprintf(stderr, "cmml-validate: Parsing stream tag %s\n", buf);
00139 fprintf(stderr, "cmml-validate: Non-recoverable error\n");
00140 return -1;
00141 } else {
00142
00143 if (verbose) {
00144 cmml_stream_pretty_snprint (buf, BUFSIZE, (CMML_Stream *) stream);
00145 fprintf(stdout, "%s\n", buf);
00146 }
00147 } return 0;
00148 }
00149
00160 static int
00161 read_head (CMML * cmml, const CMML_Head * head, void * user_data) {
00162 char buf[BUFSIZE];
00163 CMML_Error * err;
00164 if ((err = cmml_get_last_error(cmml)) != NULL) {
00165 cmml_error_snprint(buf, BUFSIZE, err, cmml);
00166 fprintf(stderr, "cmml-validate: Parsing head tag %s\n", buf);
00167 fprintf(stderr, "cmml-validate: Non-recoverable error\n");
00168 return -1;
00169 } else {
00170 if (verbose) {
00171 cmml_head_pretty_snprint (buf, BUFSIZE, (CMML_Head *) head);
00172 fprintf(stdout, "%s\n", buf);
00173 }
00174 }
00175 return 0;
00176 }
00177
00188 static int
00189 read_clip (CMML * cmml, const CMML_Clip * clip, void * user_data) {
00190 char buf[BUFSIZE];
00191 CMML_Error * err;
00192 if ((err = cmml_get_last_error(cmml)) != NULL) {
00193 cmml_error_snprint(buf, BUFSIZE, err, cmml);
00194 fprintf(stderr, "cmml-validate: Parsing clip %s\n", buf);
00195 fprintf(stderr, "cmml-validate: Skipping clip\n\n");
00196 return -1;
00197 } else {
00198 if (verbose) {
00199 cmml_clip_pretty_snprint (buf, BUFSIZE, (CMML_Clip *) clip);
00200 fprintf(stdout, "%s\n", buf);
00201 }
00202 }
00203 return 0;
00204 }
00205
00212 int main(int argc, char *argv[])
00213 {
00214 char *pathfile = NULL;
00215 int i;
00216 char buf[BUFSIZE];
00217 CMML * doc;
00218 CMML_Error * err;
00219 CMML_Preamble * pre;
00220 long n = 0;
00221 char * clip_id = NULL;
00222 double secs = -1.0;
00223 char * utc = NULL;
00224 int sloppy = 0;
00225 verbose = 0;
00226
00227 while (1) {
00228 char * optstring = "hvbyi:s:u:";
00229
00230 #ifdef HAVE_GETOPT_LONG
00231 static struct option long_options[] = {
00232 {"help",no_argument,0,'h'},
00233 {"version",no_argument,0, 'v'},
00234 {"verbose",no_argument,0,'b'},
00235 {"sloppy",no_argument,0,'y'},
00236 {"id",required_argument,0,'i'},
00237 {"sec",required_argument,0,'s'},
00238 {"utc",required_argument,0,'u'},
00239 {0,0,0,0}
00240 };
00241
00242 i = getopt_long(argc, argv, optstring, long_options, NULL);
00243 #else
00244 i = getopt(argc, argv, optstring);
00245 #endif
00246
00247 if (i == -1) break;
00248 if (i == ':') PrintUsage(argv[0]);
00249
00250 switch (i) {
00251 case 'h':
00252 PrintUsage(argv[0]);
00253 break;
00254 case 'v':
00255 fprintf(stdout, "cmml-validate version " VERSION "\n");
00256 fprintf(stdout, "# cmml-validate, Copyright (C) 2003 CSIRO Australia www.csiro.au ; www.annodex.net\n");
00257 break;
00258 case 'i':
00259 clip_id = optarg;
00260 break;
00261 case 's':
00262 if (!isalpha(optarg[0])) {
00263 secs = atof(optarg);
00264 }
00265 break;
00266 case 'u':
00267 utc = optarg;
00268 break;
00269 case 'y':
00270 sloppy = 1;
00271 break;
00272 case 'b':
00273 verbose = 1;
00274 break;
00275 default:
00276 break;
00277 }
00278 }
00279
00280
00281 if (optind > argc) {
00282 PrintUsage(argv[0]);
00283 }
00284
00285
00286 if (optind == argc) {
00287 pathfile = "-";
00288 } else {
00289 pathfile = argv[optind++];
00290 }
00291
00292
00293 errno=0;
00294 if (strcmp (pathfile, "-") == 0) {
00295 doc = cmml_new (stdin);
00296 } else {
00297 doc = cmml_open (pathfile);
00298 }
00299
00300 if (doc == NULL) {
00301 if (errno == 0) {
00302 fprintf(stderr, "%s: %s: CMML error opening file\n", argv[0], pathfile);
00303 } else {
00304 fprintf(stderr, "%s: %s: %s\n", argv[0], pathfile, strerror(errno));
00305 }
00306 PrintUsage(argv[0]);
00307 }
00308
00309
00310 if (sloppy) {
00311 cmml_set_sloppy(doc, 1);
00312 }
00313
00314
00315 if (verbose) {
00316 pre = cmml_get_preamble(doc);
00317 cmml_preamble_snprint(buf, BUFSIZE, pre);
00318 fprintf(stdout, "%s\n", buf);
00319 }
00320
00321
00322 if (clip_id != NULL) {
00323
00324 cmml_set_read_callbacks (doc, read_stream, read_head, NULL, NULL);
00325 cmml_skip_to_id (doc, clip_id);
00326 }
00327
00328
00329 if (secs > 0 || utc != NULL) {
00330
00331 cmml_set_read_callbacks (doc, read_stream, read_head, NULL, NULL);
00332 if (secs > 0) {
00333 cmml_skip_to_secs (doc, secs);
00334 } else {
00335 cmml_skip_to_utc (doc, utc);
00336 }
00337 }
00338
00339
00340 cmml_set_read_callbacks (doc, read_stream, read_head, read_clip, NULL);
00341
00342
00343 while ((n = cmml_read (doc, BUFSIZE)) > 0) {
00344
00345 if ((err = cmml_get_last_error(doc)) != NULL && err->type != CMML_EOF) {
00346 char *filename;
00347 filename = (strrchr(pathfile, '/') == NULL ? pathfile
00348 : strrchr(pathfile, '/')+1);
00349 cmml_error_snprint(buf, BUFSIZE, err, doc);
00350 fprintf (stderr, "%s:%s\n", filename, buf);
00351 goto cleanup;
00352 }
00353 }
00354
00355 err = cmml_get_last_error(doc);
00356 if (err!=NULL && err->type != CMML_EOF) {
00357 char *filename;
00358 filename = (strrchr(pathfile, '/') == NULL ? pathfile
00359 : strrchr(pathfile, '/')+1);
00360 cmml_error_snprint(buf, BUFSIZE, err, doc);
00361 fprintf (stderr, "%s:%s\n", filename, buf);
00362 goto cleanup;
00363 }
00364
00365
00366 if (verbose) {
00367 fprintf(stdout, "</cmml>\n");
00368 }
00369
00370 cleanup:
00371
00372 cmml_close(doc);
00373
00374 return 0;
00375 }