[xiph-commits] r3387 - liboggz/trunk/src/tools

conrad at svn.annodex.net conrad at svn.annodex.net
Fri Jan 25 19:46:11 PST 2008


Author: conrad
Date: 2008-01-25 19:46:10 -0800 (Fri, 25 Jan 2008)
New Revision: 3387

Modified:
   liboggz/trunk/src/tools/oggz-comment.c
Log:
modify oggz-comment to copy data pages verbatim, rather than running the
entire file through oggz_write(). (Similar to modify-headers example).


Modified: liboggz/trunk/src/tools/oggz-comment.c
===================================================================
--- liboggz/trunk/src/tools/oggz-comment.c	2008-01-26 03:29:24 UTC (rev 3386)
+++ liboggz/trunk/src/tools/oggz-comment.c	2008-01-26 03:46:10 UTC (rev 3387)
@@ -1,5 +1,5 @@
 /*
-   Copyright (C) 2007 Annodex Association
+   Copyright (C) 2008 Annodex Association
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
@@ -30,20 +30,40 @@
 */
 
 /* Kangyuan Niu: original version (Aug 2007) */
+/* Conrad Parker: modified based on modify-headers example (January 2008) */
 
-#include "config.h"
-
-#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <strings.h>
+#include <assert.h> /* , ja */
+#include <errno.h>
+#include <getopt.h>
 
 #include <oggz/oggz.h>
+
 #include "oggz_tools.h"
 
-/* #define DEBUG */
+#define ID_WRITE_DIRECT
+/* define USE_FLUSH_NEXT */
 
+#ifdef USE_FLUSH_NEXT
+static int flush_next = 0;
+#endif
+
+#define S_SERIALNO 0x7
+
+typedef struct {
+  int do_delete;
+  int do_all;
+  OGGZ * reader;
+  OGGZ * writer;
+  OGGZ * storer; /* Just used for storing comments from commandline */
+  FILE * outfile;
+  OggzTable * seen_tracks;
+  OggzTable * serialno_table;
+  OggzTable * content_types_table;
+} OCData;
+
 static char * progname;
 
 static void
@@ -52,7 +72,7 @@
   printf ("Usage: %s filename [options] tagname=tagvalue ...\n", progname);
   printf ("List or edit comments in an Ogg file.\n");
   printf ("\nOutput options\n");
-  printf ("  -l, --list            List the comments in the given file.\n");
+  printf ("  -l, --list             List the comments in the given file.\n");
   printf ("\nEditing options\n");
   printf ("  -o filename, --output filename\n");
   printf ("                         Specify output filename\n");
@@ -71,263 +91,422 @@
   printf ("Please report bugs to <ogg-dev at xiph.org>\n");
 }
 
-int copy_replace_comments(OGGZ *oggz,
-                         ogg_packet *op,
-                         long serialno,
-                         void *user_data) {
-  OGGZ *oggz_write = (OGGZ *)user_data;
-  int flush;
-  if(op->granulepos == -1)
-    flush = 0;
-  else
-    flush = OGGZ_FLUSH_AFTER;
-  if(op->packetno == 1) {
-    oggz_write_feed(oggz_write,
-                   oggz_comment_generate(oggz_write, serialno,
-                                         oggz_stream_get_content(oggz, serialno),
-                                         0),
-                   serialno, flush, NULL);
-  } else
-    oggz_write_feed(oggz_write, op, serialno, flush, NULL);
-  return 0;
+static OCData *
+ocdata_new ()
+{
+  OCData *ocdata = malloc (sizeof (OCData));
+  assert (ocdata != NULL);
+  memset (ocdata, 0, sizeof (OCData));
+
+  ocdata->do_all = 1;
+
+  ocdata->storer = oggz_new (OGGZ_WRITE);
+  
+  ocdata->seen_tracks = oggz_table_new ();
+  assert (ocdata->seen_tracks != NULL);
+
+  ocdata->serialno_table = oggz_table_new();
+  assert (ocdata->serialno_table != NULL);
+
+  ocdata->content_types_table = oggz_table_new();
+  assert (ocdata->content_types_table != NULL);
+  
+  return ocdata;
 }
 
-int copy_comments(OGGZ *oggz,
-                 ogg_packet *op,
-                 long serialno,
-                 void *user_data) {
-  OGGZ *oggz_write = (OGGZ *)user_data;
-  OggzComment * comment;
-  if(op->packetno == 1) {
-    oggz_comment_set_vendor(oggz_write, serialno,
-                           oggz_comment_get_vendor(oggz, serialno));
-    for(comment = oggz_comment_first(oggz, serialno); comment;
-       comment = oggz_comment_next(oggz, serialno, comment))
-      oggz_comment_add(oggz_write, serialno, comment);
-  }
+static void 
+ocdata_delete (OCData *ocdata)
+{
+  oggz_table_delete (ocdata->seen_tracks);
+  oggz_table_delete (ocdata->serialno_table);
+  oggz_table_delete (ocdata->content_types_table);
+  
+  if (ocdata->reader)
+    oggz_close (ocdata->reader);
+  if (ocdata->storer)
+    oggz_close (ocdata->storer);
+  if (ocdata->outfile)
+    fclose (ocdata->outfile);
+  
+  free (ocdata);
+}
+
+static int
+filter_stream_p (const OCData *ocdata, long serialno)
+{
+  if (ocdata->do_all)
+    return 1;
+
+  if (oggz_table_lookup (ocdata->serialno_table, serialno) != NULL)
+    return 1;
+
   return 0;
 }
 
-int list_comments(OGGZ *oggz,
-                 ogg_packet *op, 
-                 long serialno,
-                 void *user_data) {
-  const OggzComment * comment;
-  if(op->packetno == 1) {
-    printf("%s (serial = %ld):\n",
-          oggz_stream_get_content_type(oggz, serialno), serialno);
-    printf("\tVendor: %s\n", oggz_comment_get_vendor(oggz, serialno));
-    for (comment = oggz_comment_first(oggz, serialno); comment;
-        comment = oggz_comment_next(oggz, serialno, comment))
-      printf ("\t%s: %s\n", comment->name, comment->value);
+static int
+read_bos (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  OCData * ocdata = (OCData *)user_data;
+  const char * ident;
+  int i, n;
+
+  if (!ogg_page_bos ((ogg_page *)og))
+    return OGGZ_CONTINUE;
+
+  /* Record this track in the seen_tracks table. We don't need to store any
+   * information about the track, just the fact that it exists.
+   * Store a dummy value (as NULL is not allowed in an OggzTable).
+   */
+  oggz_table_insert (ocdata->seen_tracks, serialno, (void *)0x01);
+
+  ident = ot_page_identify (oggz, og, NULL);
+  if (ident != NULL) {
+    n = oggz_table_size (ocdata->content_types_table);
+    for (i = 0; i < n; i++) {
+      char * c = oggz_table_nth (ocdata->content_types_table, i, NULL);
+      if (strcasecmp (c, ident) == 0) {
+        oggz_table_insert (ocdata->serialno_table, serialno, (void *)0x7);
+      }
+    }
   }
-  return 0;
+
+  return OGGZ_CONTINUE;
 }
 
-int get_stream_types(OGGZ *oggz,
-                    ogg_packet *op,
-                    long serialno,
-                    void *user_data) {
-  OggzTable *table = (OggzTable *)user_data;
-  OggzStreamContent *content = malloc(sizeof(OggzStreamContent));
-  if(oggz_table_lookup(table, serialno) == NULL) {
-    *content = oggz_stream_get_content(oggz, serialno);
-    oggz_table_insert(table, serialno, content);
+static int
+more_headers (OCData * ocdata, ogg_packet * op, long serialno)
+{
+  /* Determine if we're finished processing headers */
+  if (op->packetno+1 >= oggz_stream_get_numheaders (ocdata->reader, serialno)) {
+    /* If this was the last header for this track, remove it from the
+       track list */
+    oggz_table_remove (ocdata->seen_tracks, serialno);
+
+    /* If no more tracks are left in the track list, then we have processed
+     * all the headers; stop processing of packets. */
+    if (oggz_table_size (ocdata->seen_tracks) == 0) {
+      return OGGZ_STOP_ERR;
+    }
   }
-  return 0;
+
+  return OGGZ_CONTINUE;
 }
 
-void edit_comments(OGGZ *oggz,
-                  long serialno,
-                  OggzComment *comments) {
-  int i;
-  for(i = 0; strcmp(comments[i].name, "0"); i++) {
-    oggz_comment_remove_byname(oggz, serialno, comments[i].name);
-    oggz_comment_add(oggz, serialno, &comments[i]);
+static int
+read_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  OCData * ocdata = (OCData *)user_data;
+
+  fwrite (og->header, 1, og->header_len, ocdata->outfile);
+  fwrite (og->body, 1, og->body_len, ocdata->outfile);
+
+  return OGGZ_CONTINUE;
+}
+
+static int
+read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
+{
+  OCData * ocdata = (OCData *)user_data;
+  const char * vendor;
+  int flush;
+  int ret;
+
+#ifdef USE_FLUSH_NEXT
+  flush = flush_next;
+  if (op->granulepos == -1) {
+    flush_next = 0;
+  } else {
+    flush_next = OGGZ_FLUSH_BEFORE;
   }
+#else
+  if (op->granulepos == -1) {
+    flush = 0;
+  } else {
+    flush = OGGZ_FLUSH_AFTER;
+  }
+#endif
+
+  /* Edit the packet data if required */
+  if (filter_stream_p (ocdata, serialno) && op->packetno == 1) {
+    vendor = oggz_comment_get_vendor (ocdata->reader, serialno);
+
+    /* Copy across the comments, unless "delete comments before editing" */
+    if (!ocdata->do_delete)
+      oggz_comments_copy (ocdata->reader, serialno, ocdata->writer, serialno);
+
+    /* Add stored comments from commandline */
+    oggz_comments_copy (ocdata->storer, S_SERIALNO, ocdata->writer, serialno);
+
+    /* Ensure the original vendor is preserved */
+    oggz_comment_set_vendor (ocdata->writer, serialno, vendor);
+
+    /* Generate the replacement comments packet */
+    op = oggz_comments_generate (ocdata->writer, serialno, 0);
+  }
+
+  /* Feed the packet into the writer */
+  if ((ret = oggz_write_feed (ocdata->writer, op, serialno, flush, NULL)) != 0) 
+    fprintf (stderr, "oggz_write_feed: %d\n", ret);
+
+  return more_headers (ocdata, op, serialno);
 }
 
-int comment_table_insert(OggzTable *type_table,
-                        OggzTable *comment_table,
-                        long serialno,
-                        OggzComment *comments) {
-  OggzStreamContent type;
-  long type_serialno;
-  int i;
-  if(!strcmp(comments[0].name, "0"))
-    return 0;
-  if(serialno > 0) {
-    oggz_table_insert(comment_table, serialno, comments);
-  } else if(serialno > -11) {
-    for(i = 0; i < oggz_table_size(type_table); i++) {
-      type = *(OggzStreamContent *)oggz_table_nth(type_table, i, &type_serialno);
-      if(type == serialno * -1)
-       oggz_table_insert(comment_table, type_serialno, comments);
-    }
+static int
+edit_comments (OCData * ocdata, char * outfilename)
+{
+  unsigned char buf[1024];
+  long n;
+
+  if (outfilename == NULL) {
+    ocdata->outfile = stdout;
   } else {
-    for(i = 0; i < oggz_table_size(type_table); i++) {
-      oggz_table_nth(type_table, i, &type_serialno);
-      oggz_table_insert(comment_table, type_serialno, comments);
+    ocdata->outfile = fopen (outfilename, "wb");
+    if (ocdata->outfile == NULL) {
+      fprintf (stderr, "%s: unable to open output file %s\n",
+	       progname, outfilename);
+      return -1;
     }
   }
-  return 1;
+
+  /* Set up writer, filling in ocdata for callbacks */
+  if ((ocdata->writer = oggz_new (OGGZ_WRITE)) == NULL) {
+    printf ("Unable to create new writer\n");
+  }
+  ocdata->outfile = fopen (outfilename, "w");
+
+  /* Set a page reader to process bos pages */
+  oggz_set_read_page (ocdata->reader, -1, read_bos, ocdata);
+
+  /* First, process headers packet-by-packet. */
+  oggz_set_read_callback (ocdata->reader, -1, read_packet, ocdata);
+  while ((n = oggz_read (ocdata->reader, 1024)) > 0) {
+    while (oggz_write_output (ocdata->writer, buf, n) > 0) {
+      fwrite (buf, 1, n, ocdata->outfile);
+    }
+  }
+
+  /* We actually don't use the writer any more from here, so close it */
+  oggz_close (ocdata->writer);
+
+  /* Now, the headers are processed. We deregister the packet reading
+   * callback. */
+  oggz_set_read_callback (ocdata->reader, -1, NULL, NULL);
+
+  /* We deal with the rest of the file as pages. */
+  /* Register a callback that copies page data directly across to outfile */
+  oggz_set_read_page (ocdata->reader, -1, read_page, ocdata);
+
+  if (oggz_run (ocdata->reader) == OGGZ_ERR_OK)
+    return 0;
+  else
+    return 1;
 }
 
-OggzComment parse_comment_field(char *arg) {
-  int i;
-  char *c;
-  OggzComment comment;
-  comment.name = strcpy(calloc(strlen(arg) + 1, sizeof(char)), arg);
-  c = strchr(comment.name, '=');
-  *c = '\0';
-  for(i = 0; comment.name[i]; i++)
-    if(islower(arg[i]))
-      comment.name[i] = toupper(arg[i]);
-  comment.value = c + 1;
-  return comment;
+static int
+read_comments(OGGZ *oggz, ogg_packet *op, long serialno, void *user_data)
+{
+  OCData * ocdata = (OCData *)user_data;
+  const OggzComment * comment;
+  const char * codec_name;
+
+  if (filter_stream_p (ocdata, serialno) && op->packetno == 1) {
+    codec_name = oggz_stream_get_content_type(oggz, serialno);
+    if (codec_name) {
+      printf ("%s: serialno %010ld\n", codec_name, serialno);
+    } else {
+      printf ("???: serialno %010ld\n", serialno);
+    }
+
+    printf("\tVendor: %s\n", oggz_comment_get_vendor(oggz, serialno));
+
+    for (comment = oggz_comment_first(oggz, serialno); comment;
+         comment = oggz_comment_next(oggz, serialno, comment))
+      printf ("\t%s: %s\n", comment->name, comment->value);
+  }
+
+  return more_headers (ocdata, op, serialno);
 }
 
-OggzStreamContent strto_oggz_content(char *type) {
-  if(!strcasecmp(type, "theora"))
-    return OGGZ_CONTENT_THEORA;
-  if(!strcasecmp(type, "vorbis"))
-    return OGGZ_CONTENT_VORBIS;
-  if(!strcasecmp(type, "speex"))
-    return OGGZ_CONTENT_SPEEX;
-  if(!strcasecmp(type, "pcm"))
-    return OGGZ_CONTENT_PCM;
-  if(!strcasecmp(type, "cmml"))
-    return OGGZ_CONTENT_CMML;
-  if(!strcasecmp(type, "anx2"))
-    return OGGZ_CONTENT_ANX2;
-  if(!strcasecmp(type, "skeleton"))
-    return OGGZ_CONTENT_SKELETON;
-  if(!strcasecmp(type, "flac0"))
-    return OGGZ_CONTENT_FLAC0;
-  if(!strcasecmp(type, "flac"))
-    return OGGZ_CONTENT_FLAC;
-  if(!strcasecmp(type, "anxdata"))
-    return OGGZ_CONTENT_ANXDATA;
-  return OGGZ_CONTENT_UNKNOWN;
+static int
+list_comments (OCData * ocdata)
+{
+  /* Set a page reader to process bos pages */
+  oggz_set_read_page (ocdata->reader, -1, read_bos, ocdata);
+
+  /* First, process headers packet-by-packet. */
+  oggz_set_read_callback (ocdata->reader, -1, read_comments, ocdata);
+
+  if (oggz_run (ocdata->reader) == OGGZ_ERR_STOP_OK)
+    return 0;
+  else
+    return 1;
 }
 
-void version() {
-  printf ("%s version " VERSION "\n", progname);
+static void
+store_comment (OCData * ocdata, char * s)
+{
+  char * c, * name, * value;
+
+  c = strchr (s, '=');
+  *c = '\0';
+
+  name = s;
+  value = c+1;
+
+  oggz_comment_add_byname (ocdata->storer, S_SERIALNO, name, value);
 }
 
+int
+main (int argc, char ** argv)
+{
+  char * infilename = NULL, * outfilename = NULL;
+  OCData * ocdata;
 
-int main(int argc, char *argv[]) {
-  int i, temp, clear = 0;
-  long n, serialno = -11;
-  char *out_file;
-  OGGZ *oggz_in;
-  OGGZ *oggz_out;
-  OggzComment *comments;
-  OggzTable *type_table = oggz_table_new();
-  OggzTable *comment_table = oggz_table_new();
+  int filter_serialnos = 0;
+  int filter_content_types = 0;
 
+  int show_version = 0;
+  int show_help = 0;
+  int do_list = 0;
+
+  long serialno;
+  long n;
+  int i = 1;
+
   progname = argv[0];
 
-  if(argc < 2) {
+  if (argc < 3) {
     usage (progname);
-    return 1;
+    return (1);
   }
 
-  if(strcmp(argv[1], "--version") == 0
-     || strcmp(argv[1], "-v") == 0) {
-    version();
-    return 0;
-  } else if(strcmp(argv[1], "--help") == 0
-           || strcmp(argv[1], "-h") == 0) {
-    usage(progname);
-    return 0;
-  } else {
-    oggz_in = oggz_open(argv[1], OGGZ_READ);
-    out_file = argv[1];
+  ocdata = ocdata_new ();
+
+  while (1) {
+    char * optstring = "lo:dac:s:hv";
+
+#ifdef HAVE_GETOPT_LONG
+    static struct option long_options[] = {
+      {"list",     no_argument, 0, 'l'},
+      {"output",   required_argument, 0, 'o'},
+      {"delete",   no_argument, 0, 'd'},
+      {"all",      no_argument, 0, 'a'},
+      {"content-type", required_argument, 0, 'c'},
+      {"serialno", required_argument, 0, 's'},
+      {"help",     no_argument, 0, 'h'},
+      {"version",  no_argument, 0, 'v'},
+      {0,0,0,0}
+    };
+
+    i = getopt_long(argc, argv, optstring, long_options, NULL);
+#else
+    i = getopt (argc, argv, optstring);
+#endif
+    if (i == -1) break;
+    if (i == ':') {
+      usage (progname);
+      goto exit_err;
+    }
+
+    switch (i) {
+    case 'l': /* list */
+      do_list = 1;
+      break;
+    case 'd': /* delete */
+      ocdata->do_delete = 1;
+      break;
+    case 'a': /* all */
+      ocdata->do_all = 1;
+      break;
+    case 's': /* serialno */
+      filter_serialnos = 1;
+      ocdata->do_all = 0;
+      serialno = atol (optarg);
+      oggz_table_insert (ocdata->serialno_table, serialno, (void *)0x7);
+      break;
+    case 'c': /* content-type */
+      filter_content_types = 1;
+      ocdata->do_all = 0;
+      n = oggz_table_size (ocdata->content_types_table);
+      oggz_table_insert (ocdata->content_types_table, n, optarg);
+      break;
+    case 'h': /* help */
+      show_help = 1;
+      break;
+    case 'v': /* version */
+      show_version = 1;
+      break;
+    case 'o': /* output */
+      outfilename = optarg;
+      break;
+    default:
+      break;
+    }
   }
 
-  oggz_set_read_callback(oggz_in, -1, get_stream_types, type_table);
-  oggz_run(oggz_in);
-  comments = calloc(argc - 1, sizeof(OggzComment));
-  comments[temp = 0].name = "0";
-  for(i = 2; i < argc; i++) {
-    if(!strcmp(argv[i], "-o"))
-      out_file = argv[++i];
-    else if(!strcmp(argv[i], "-d")
-           || !strcmp(argv[i], "--delete"))
-      clear = 1;
-    else if(!strcmp(argv[i], "-l")
-           || !strcmp(argv[i], "--list")) {
-      oggz_seek(oggz_in, 0, SEEK_SET);
-      oggz_set_read_callback(oggz_in, -1, list_comments, NULL);
-      oggz_run(oggz_in);
-    } else if(strchr(argv[i], '=') != NULL) {
-      comments[temp] = parse_comment_field(argv[i]);
-      comments[++temp].name = "0";
-    } else if(!strcmp(argv[i], "-a")) {
-      if(comment_table_insert(type_table, comment_table, serialno, comments)) {
-       comments = calloc(argc - 2, sizeof(OggzComment));
-       comments[temp = 0].name = "0";
-      }
-      serialno = -11;
-    } else if(!strcmp(argv[i], "-c")
-           || !strcmp(argv[i], "--content-type")) {
-      if(comment_table_insert(type_table, comment_table, serialno, comments)) {
-       comments = calloc(argc - 2, sizeof(OggzComment));
-       comments[temp = 0].name = "0";
-      }
-      serialno = strto_oggz_content(argv[++i]) * -1;
-    } else if(!strcmp(argv[i], "-s")
-           || !strcmp(argv[i], "--serialno")) {
-      if(comment_table_insert(type_table, comment_table, serialno, comments)) {
-       comments = calloc(argc - 2, sizeof(OggzComment));
-       comments[temp = 0].name = "0";
-      }
-      serialno = strtol(argv[++i], NULL, 10);
+  if (show_version) {
+    printf ("%s version " VERSION "\n", progname);
+  }
+
+  if (show_help) {
+    usage (progname);
+  }
+
+  if (show_version || show_help) {
+    goto exit_ok;
+  }
+
+  if (optind >= argc) {
+    usage (progname);
+    goto exit_err;
+  }
+
+  /* Parse out new comments and infilename */
+  for (; optind < argc; optind++) {
+    char * s = argv[optind];
+
+    if(strchr(s, '=') != NULL) {
+      if (!do_list) store_comment (ocdata, s);
     } else {
-      printf("Error: option or field \"");
-      printf(argv[i]);
-      printf("\" unrecognized.\n");
-      return 0;
+      infilename = s;
     }
   }
-  comment_table_insert(type_table, comment_table, serialno, comments);
 
-  if(oggz_table_size(comment_table)) {
-    temp = 0;
-    if(!strcmp(out_file, argv[1])) {
-      out_file = tmpnam(NULL);
-      temp = 1;
-    }
-    oggz_out = oggz_open(out_file, OGGZ_WRITE);
-    if(!clear) {
-      oggz_seek(oggz_in, 0, SEEK_SET);
-      oggz_set_read_callback(oggz_in, -1, copy_comments, oggz_out);
-      oggz_run(oggz_in);
-    }
-    for(i = 0; i < oggz_table_size(comment_table); i++) {
-      comments = oggz_table_nth(comment_table, i, &serialno);
-      edit_comments(oggz_out, serialno, comments);
-    }
-    oggz_seek(oggz_in, 0, SEEK_SET);
-    oggz_set_read_callback(oggz_in, -1, copy_replace_comments, oggz_out);
-    while((n = oggz_read(oggz_in, 1024)) > 0)
-      while(oggz_write(oggz_out, n) > 0);
-    if(temp) {
-      remove(argv[1]);
-      rename(out_file, argv[1]);
-    }
-    oggz_close(oggz_out);
-  } else if(oggz_in) {
-    oggz_seek(oggz_in, 0, SEEK_SET);
-    oggz_set_read_callback(oggz_in, -1, list_comments, NULL);
-    oggz_run(oggz_in);
+  /* Set up reader */
+  if (infilename == NULL || strcmp (infilename, "-") == 0) {
+    ocdata->reader = oggz_open_stdio (stdin, OGGZ_READ|OGGZ_AUTO);
   } else {
-    printf("Error: file \"");
-    printf(argv[1]);
-    printf("\" could not be opened.\n");
+    ocdata->reader = oggz_open (infilename, OGGZ_READ|OGGZ_AUTO);
   }
 
-  oggz_close(oggz_in);
-  return 0;
+  if (ocdata->reader == NULL) {
+    if (errno == 0) {
+      fprintf (stderr, "%s: %s: error opening input file\n",
+	      progname, infilename);
+    } else {
+      fprintf (stderr, "%s: %s: %s\n",
+	       progname, infilename, strerror (errno));
+    }
+    goto exit_err;
+  }
+
+  if (do_list) {
+    if (list_comments (ocdata) == 0)
+      goto exit_ok;
+    else
+      goto exit_err;
+  }
+
+  if (edit_comments (ocdata, outfilename) == 0)
+    goto exit_ok;
+  else
+    goto exit_err;
+
+exit_ok:
+  ocdata_delete (ocdata);
+  exit (0);
+
+exit_err:
+  ocdata_delete (ocdata);
+  exit (1);
 }



More information about the commits mailing list