Imported Upstream version 2.2.5
[platform/upstream/expat.git] / xmlwf / xmlwf.c
index 6801e37..82d028e 100644 (file)
@@ -30,6 +30,7 @@
    USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include "xmltchar.h"
 
 #ifdef _MSC_VER
-#include <crtdbg.h>
+# include <crtdbg.h>
 #endif
 
+#ifdef XML_UNICODE
+# include <wchar.h>
+#endif
+
+/* Structures for handler user data */
+typedef struct NotationList {
+  struct NotationList *next;
+  const XML_Char *notationName;
+  const XML_Char *systemId;
+  const XML_Char *publicId;
+} NotationList;
+
+typedef struct xmlwfUserData {
+  FILE *fp;
+  NotationList *notationListHead;
+  const XML_Char *currentDoctypeName;
+} XmlwfUserData;
+
+
 /* This ensures proper sorting. */
 
 #define NSSEP T('\001')
@@ -52,7 +72,7 @@
 static void XMLCALL
 characterData(void *userData, const XML_Char *s, int len)
 {
-  FILE *fp = (FILE *)userData;
+  FILE *fp = ((XmlwfUserData *)userData)->fp;
   for (; len > 0; --len, ++s) {
     switch (*s) {
     case T('&'):
@@ -90,6 +110,7 @@ attributeValue(FILE *fp, const XML_Char *s)
 {
   puttc(T('='), fp);
   puttc(T('"'), fp);
+  assert(s);
   for (;;) {
     switch (*s) {
     case 0:
@@ -147,7 +168,7 @@ startElement(void *userData, const XML_Char *name, const XML_Char **atts)
 {
   int nAtts;
   const XML_Char **p;
-  FILE *fp = (FILE *)userData;
+  FILE *fp = ((XmlwfUserData *)userData)->fp;
   puttc(T('<'), fp);
   fputts(name, fp);
 
@@ -169,7 +190,7 @@ startElement(void *userData, const XML_Char *name, const XML_Char **atts)
 static void XMLCALL
 endElement(void *userData, const XML_Char *name)
 {
-  FILE *fp = (FILE *)userData;
+  FILE *fp = ((XmlwfUserData *)userData)->fp;
   puttc(T('<'), fp);
   puttc(T('/'), fp);
   fputts(name, fp);
@@ -194,7 +215,7 @@ startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
   int nAtts;
   int nsi;
   const XML_Char **p;
-  FILE *fp = (FILE *)userData;
+  FILE *fp = ((XmlwfUserData *)userData)->fp;
   const XML_Char *sep;
   puttc(T('<'), fp);
 
@@ -240,7 +261,7 @@ startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
 static void XMLCALL
 endElementNS(void *userData, const XML_Char *name)
 {
-  FILE *fp = (FILE *)userData;
+  FILE *fp = ((XmlwfUserData *)userData)->fp;
   const XML_Char *sep;
   puttc(T('<'), fp);
   puttc(T('/'), fp);
@@ -260,7 +281,7 @@ static void XMLCALL
 processingInstruction(void *userData, const XML_Char *target,
                       const XML_Char *data)
 {
-  FILE *fp = (FILE *)userData;
+  FILE *fp = ((XmlwfUserData *)userData)->fp;
   puttc(T('<'), fp);
   puttc(T('?'), fp);
   fputts(target, fp);
@@ -270,6 +291,200 @@ processingInstruction(void *userData, const XML_Char *target,
   puttc(T('>'), fp);
 }
 
+
+static XML_Char *xcsdup(const XML_Char *s)
+{
+  XML_Char *result;
+  int count = 0;
+  int numBytes;
+
+  /* Get the length of the string, including terminator */
+  while (s[count++] != 0) {
+    /* Do nothing */
+  }
+  numBytes = count * sizeof(XML_Char);
+  result = malloc(numBytes);
+  if (result == NULL)
+    return NULL;
+  memcpy(result, s, numBytes);
+  return result;
+}
+
+static void XMLCALL
+startDoctypeDecl(void *userData,
+                 const XML_Char *doctypeName,
+                 const XML_Char *UNUSED_P(sysid),
+                 const XML_Char *UNUSED_P(publid),
+                 int UNUSED_P(has_internal_subset))
+{
+  XmlwfUserData *data = (XmlwfUserData *)userData;
+  data->currentDoctypeName = xcsdup(doctypeName);
+}
+
+static void
+freeNotations(XmlwfUserData *data)
+{
+  NotationList *notationListHead = data->notationListHead;
+
+  while (notationListHead != NULL) {
+    NotationList *next = notationListHead->next;
+    free((void *)notationListHead->notationName);
+    free((void *)notationListHead->systemId);
+    free((void *)notationListHead->publicId);
+    free(notationListHead);
+    notationListHead = next;
+  }
+  data->notationListHead = NULL;
+}
+
+static int xcscmp(const XML_Char *xs, const XML_Char *xt)
+{
+  while (*xs != 0 && *xt != 0) {
+    if (*xs < *xt)
+      return -1;
+    if (*xs > *xt)
+      return 1;
+    xs++;
+    xt++;
+  }
+  if (*xs < *xt)
+    return -1;
+  if (*xs > *xt)
+    return 1;
+  return 0;
+}
+
+static int
+notationCmp(const void *a, const void *b)
+{
+  const NotationList * const n1 = *(NotationList **)a;
+  const NotationList * const n2 = *(NotationList **)b;
+
+  return xcscmp(n1->notationName, n2->notationName);
+}
+
+static void XMLCALL
+endDoctypeDecl(void *userData)
+{
+  XmlwfUserData *data = (XmlwfUserData *)userData;
+  NotationList **notations;
+  int notationCount = 0;
+  NotationList *p;
+  int i;
+
+  /* How many notations do we have? */
+  for (p = data->notationListHead; p != NULL; p = p->next)
+    notationCount++;
+  if (notationCount == 0) {
+    /* Nothing to report */
+    free((void *)data->currentDoctypeName);
+    data->currentDoctypeName = NULL;
+    return;
+  }
+
+  notations = malloc(notationCount * sizeof(NotationList *));
+  if (notations == NULL) {
+    fprintf(stderr, "Unable to sort notations");
+    freeNotations(data);
+    return;
+  }
+
+  for (p = data->notationListHead, i = 0;
+       i < notationCount;
+       p = p->next, i++) {
+    notations[i] = p;
+  }
+  qsort(notations, notationCount, sizeof(NotationList *), notationCmp);
+
+  /* Output the DOCTYPE header */
+  fputts(T("<!DOCTYPE "), data->fp);
+  fputts(data->currentDoctypeName, data->fp);
+  fputts(T(" [\n"), data->fp);
+
+  /* Now the NOTATIONs */
+  for (i = 0; i < notationCount; i++) {
+    fputts(T("<!NOTATION "), data->fp);
+    fputts(notations[i]->notationName, data->fp);
+    if (notations[i]->publicId != NULL) {
+      fputts(T(" PUBLIC '"), data->fp);
+      fputts(notations[i]->publicId, data->fp);
+      puttc(T('\''), data->fp);
+      if (notations[i]->systemId != NULL) {
+        puttc(T(' '), data->fp);
+        puttc(T('\''), data->fp);
+        fputts(notations[i]->systemId, data->fp);
+        puttc(T('\''), data->fp);
+      }
+    }
+    else if (notations[i]->systemId != NULL) {
+      fputts(T(" SYSTEM '"), data->fp);
+      fputts(notations[i]->systemId, data->fp);
+      puttc(T('\''), data->fp);
+    }
+    puttc(T('>'), data->fp);
+    puttc(T('\n'), data->fp);
+  }
+
+  /* Finally end the DOCTYPE */
+  fputts(T("]>\n"), data->fp);
+
+  free(notations);
+  freeNotations(data);
+  free((void *)data->currentDoctypeName);
+  data->currentDoctypeName = NULL;
+}
+
+static void XMLCALL
+notationDecl(void *userData,
+             const XML_Char *notationName,
+             const XML_Char *UNUSED_P(base),
+             const XML_Char *systemId,
+             const XML_Char *publicId)
+{
+  XmlwfUserData *data = (XmlwfUserData *)userData;
+  NotationList *entry = malloc(sizeof(NotationList));
+  const char *errorMessage = "Unable to store NOTATION for output\n";
+
+  if (entry == NULL) {
+    fputs(errorMessage, stderr);
+    return; /* Nothing we can really do about this */
+  }
+  entry->notationName = xcsdup(notationName);
+  if (entry->notationName == NULL) {
+    fputs(errorMessage, stderr);
+    free(entry);
+    return;
+  }
+  if (systemId != NULL) {
+    entry->systemId = xcsdup(systemId);
+    if (entry->systemId == NULL) {
+      fputs(errorMessage, stderr);
+      free((void *)entry->notationName);
+      free(entry);
+      return;
+    }
+  }
+  else {
+    entry->systemId = NULL;
+  }
+  if (publicId != NULL) {
+    entry->publicId = xcsdup(publicId);
+    if (entry->publicId == NULL) {
+      fputs(errorMessage, stderr);
+      free((void *)entry->systemId); /* Safe if it's NULL */
+      free((void *)entry->notationName);
+      free(entry);
+      return;
+    }
+  }
+  else {
+    entry->publicId = NULL;
+  }
+
+  entry->next = data->notationListHead;
+  data->notationListHead = entry;
+}
+
 #endif /* not W3C14N */
 
 static void XMLCALL
@@ -322,7 +537,7 @@ nopProcessingInstruction(void *UNUSED_P(userData), const XML_Char *UNUSED_P(targ
 static void XMLCALL
 markup(void *userData, const XML_Char *s, int len)
 {
-  FILE *fp = (FILE *)XML_GetUserData((XML_Parser) userData);
+  FILE *fp = ((XmlwfUserData *)XML_GetUserData((XML_Parser) userData))->fp;
   for (; len > 0; --len, ++s)
     puttc(*s, fp);
 }
@@ -331,11 +546,14 @@ static void
 metaLocation(XML_Parser parser)
 {
   const XML_Char *uri = XML_GetBase(parser);
+  FILE *fp = ((XmlwfUserData *)XML_GetUserData(parser))->fp;
   if (uri)
-    ftprintf((FILE *)XML_GetUserData(parser), T(" uri=\"%s\""), uri);
-  ftprintf((FILE *)XML_GetUserData(parser),
-           T(" byte=\"%" XML_FMT_INT_MOD "d\" nbytes=\"%d\" \
-                        line=\"%" XML_FMT_INT_MOD "u\" col=\"%" XML_FMT_INT_MOD "u\""),
+    ftprintf(fp, T(" uri=\"%s\""), uri);
+  ftprintf(fp,
+           T(" byte=\"%") T(XML_FMT_INT_MOD) T("d\"")
+             T(" nbytes=\"%d\"")
+             T(" line=\"%") T(XML_FMT_INT_MOD) T("u\"")
+             T(" col=\"%") T(XML_FMT_INT_MOD) T("u\""),
            XML_GetCurrentByteIndex(parser),
            XML_GetCurrentByteCount(parser),
            XML_GetCurrentLineNumber(parser),
@@ -345,13 +563,15 @@ metaLocation(XML_Parser parser)
 static void
 metaStartDocument(void *userData)
 {
-  fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
+  fputts(T("<document>\n"),
+         ((XmlwfUserData *)XML_GetUserData((XML_Parser) userData))->fp);
 }
 
 static void
 metaEndDocument(void *userData)
 {
-  fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
+  fputts(T("</document>\n"),
+         ((XmlwfUserData *)XML_GetUserData((XML_Parser) userData))->fp);
 }
 
 static void XMLCALL
@@ -359,7 +579,8 @@ metaStartElement(void *userData, const XML_Char *name,
                  const XML_Char **atts)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   const XML_Char **specifiedAttsEnd
     = atts + XML_GetSpecifiedAttributeCount(parser);
   const XML_Char **idAttPtr;
@@ -368,14 +589,14 @@ metaStartElement(void *userData, const XML_Char *name,
     idAttPtr = 0;
   else
     idAttPtr = atts + idAttIndex;
-    
+
   ftprintf(fp, T("<starttag name=\"%s\""), name);
   metaLocation(parser);
   if (*atts) {
     fputts(T(">\n"), fp);
     do {
       ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
-      characterData(fp, atts[1], (int)tcslen(atts[1]));
+      characterData(data, atts[1], (int)tcslen(atts[1]));
       if (atts >= specifiedAttsEnd)
         fputts(T("\" defaulted=\"yes\"/>\n"), fp);
       else if (atts == idAttPtr)
@@ -393,7 +614,8 @@ static void XMLCALL
 metaEndElement(void *userData, const XML_Char *name)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   ftprintf(fp, T("<endtag name=\"%s\""), name);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -404,9 +626,10 @@ metaProcessingInstruction(void *userData, const XML_Char *target,
                           const XML_Char *data)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = usrData->fp;
   ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
-  characterData(fp, data, (int)tcslen(data));
+  characterData(usrData, data, (int)tcslen(data));
   puttc(T('"'), fp);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -416,9 +639,10 @@ static void XMLCALL
 metaComment(void *userData, const XML_Char *data)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = usrData->fp;
   fputts(T("<comment data=\""), fp);
-  characterData(fp, data, (int)tcslen(data));
+  characterData(usrData, data, (int)tcslen(data));
   puttc(T('"'), fp);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -428,7 +652,8 @@ static void XMLCALL
 metaStartCdataSection(void *userData)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   fputts(T("<startcdata"), fp);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -438,7 +663,8 @@ static void XMLCALL
 metaEndCdataSection(void *userData)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   fputts(T("<endcdata"), fp);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -448,9 +674,10 @@ static void XMLCALL
 metaCharacterData(void *userData, const XML_Char *s, int len)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   fputts(T("<chars str=\""), fp);
-  characterData(fp, s, len);
+  characterData(data, s, len);
   puttc(T('"'), fp);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -464,7 +691,8 @@ metaStartDoctypeDecl(void *userData,
                      int UNUSED_P(has_internal_subset))
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -474,7 +702,8 @@ static void XMLCALL
 metaEndDoctypeDecl(void *userData)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   fputts(T("<enddoctype"), fp);
   metaLocation(parser);
   fputts(T("/>\n"), fp);
@@ -488,13 +717,14 @@ metaNotationDecl(void *userData,
                  const XML_Char *publicId)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   ftprintf(fp, T("<notation name=\"%s\""), notationName);
   if (publicId)
     ftprintf(fp, T(" public=\"%s\""), publicId);
   if (systemId) {
     fputts(T(" system=\""), fp);
-    characterData(fp, systemId, (int)tcslen(systemId));
+    characterData(data, systemId, (int)tcslen(systemId));
     puttc(T('"'), fp);
   }
   metaLocation(parser);
@@ -514,13 +744,14 @@ metaEntityDecl(void *userData,
                const XML_Char *notationName)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
 
   if (value) {
     ftprintf(fp, T("<entity name=\"%s\""), entityName);
     metaLocation(parser);
     puttc(T('>'), fp);
-    characterData(fp, value, value_length);
+    characterData(data, value, value_length);
     fputts(T("</entity/>\n"), fp);
   }
   else if (notationName) {
@@ -528,7 +759,7 @@ metaEntityDecl(void *userData,
     if (publicId)
       ftprintf(fp, T(" public=\"%s\""), publicId);
     fputts(T(" system=\""), fp);
-    characterData(fp, systemId, (int)tcslen(systemId));
+    characterData(data, systemId, (int)tcslen(systemId));
     puttc(T('"'), fp);
     ftprintf(fp, T(" notation=\"%s\""), notationName);
     metaLocation(parser);
@@ -539,7 +770,7 @@ metaEntityDecl(void *userData,
     if (publicId)
       ftprintf(fp, T(" public=\"%s\""), publicId);
     fputts(T(" system=\""), fp);
-    characterData(fp, systemId, (int)tcslen(systemId));
+    characterData(data, systemId, (int)tcslen(systemId));
     puttc(T('"'), fp);
     metaLocation(parser);
     fputts(T("/>\n"), fp);
@@ -552,13 +783,14 @@ metaStartNamespaceDecl(void *userData,
                        const XML_Char *uri)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   fputts(T("<startns"), fp);
   if (prefix)
     ftprintf(fp, T(" prefix=\"%s\""), prefix);
   if (uri) {
     fputts(T(" ns=\""), fp);
-    characterData(fp, uri, (int)tcslen(uri));
+    characterData(data, uri, (int)tcslen(uri));
     fputts(T("\"/>\n"), fp);
   }
   else
@@ -569,7 +801,8 @@ static void XMLCALL
 metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
 {
   XML_Parser parser = (XML_Parser) userData;
-  FILE *fp = (FILE *)XML_GetUserData(parser);
+  XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
+  FILE *fp = data->fp;
   if (!prefix)
     fputts(T("<endns/>\n"), fp);
   else
@@ -659,10 +892,15 @@ static void
 usage(const XML_Char *prog, int rc)
 {
   ftprintf(stderr,
-           T("usage: %s [-s] [-n] [-p] [-x] [-e encoding] [-w] [-d output-dir] [-c] [-m] [-r] [-t] [file ...]\n"), prog);
+           T("usage: %s [-s] [-n] [-p] [-x] [-e encoding] [-w] [-d output-dir] [-c] [-m] [-r] [-t] [-N] [file ...]\n"), prog);
   exit(rc);
 }
 
+#if defined(__MINGW32__) && defined(XML_UNICODE)
+/* Silence warning about missing prototype */
+int wmain(int argc, XML_Char **argv);
+#endif
+
 int
 tmain(int argc, XML_Char **argv)
 {
@@ -674,9 +912,11 @@ tmain(int argc, XML_Char **argv)
   int outputType = 0;
   int useNamespaces = 0;
   int requireStandalone = 0;
+  int requiresNotations = 0;
   enum XML_ParamEntityParsing paramEntityParsing = 
     XML_PARAM_ENTITY_PARSING_NEVER;
   int useStdin = 0;
+  XmlwfUserData userData = { NULL, NULL, NULL };
 
 #ifdef _MSC_VER
   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
@@ -731,6 +971,10 @@ tmain(int argc, XML_Char **argv)
       outputType = 't';
       j++;
       break;
+    case T('N'):
+      requiresNotations = 1;
+      j++;
+      break;
     case T('d'):
       if (argv[i][j + 1] == T('\0')) {
         if (++i == argc)
@@ -776,7 +1020,6 @@ tmain(int argc, XML_Char **argv)
     i--;
   }
   for (; i < argc; i++) {
-    FILE *fp = 0;
     XML_Char *outName = 0;
     int result;
     XML_Parser parser;
@@ -786,7 +1029,7 @@ tmain(int argc, XML_Char **argv)
       parser = XML_ParserCreate(encoding);
 
     if (! parser) {
-      tperror("Could not instantiate parser");
+      tperror(T("Could not instantiate parser"));
       exit(1);
     }
 
@@ -825,16 +1068,16 @@ tmain(int argc, XML_Char **argv)
       tcscpy(outName, outputDir);
       tcscat(outName, delim);
       tcscat(outName, file);
-      fp = tfopen(outName, T("wb"));
-      if (!fp) {
+      userData.fp = tfopen(outName, T("wb"));
+      if (!userData.fp) {
         tperror(outName);
         exit(1);
       }
-      setvbuf(fp, NULL, _IOFBF, 16384);
+      setvbuf(userData.fp, NULL, _IOFBF, 16384);
 #ifdef XML_UNICODE
-      puttc(0xFEFF, fp);
+      puttc(0xFEFF, userData.fp);
 #endif
-      XML_SetUserData(parser, fp);
+      XML_SetUserData(parser, &userData);
       switch (outputType) {
       case 'm':
         XML_UseParserAsHandlerArg(parser);
@@ -868,6 +1111,10 @@ tmain(int argc, XML_Char **argv)
         XML_SetCharacterDataHandler(parser, characterData);
 #ifndef W3C14N
         XML_SetProcessingInstructionHandler(parser, processingInstruction);
+        if (requiresNotations) {
+          XML_SetDoctypeDeclHandler(parser, startDoctypeDecl, endDoctypeDecl);
+          XML_SetNotationDeclHandler(parser, notationDecl);
+        }
 #endif /* not W3C14N */
         break;
       }
@@ -878,7 +1125,7 @@ tmain(int argc, XML_Char **argv)
     if (outputDir) {
       if (outputType == 'm')
         metaEndDocument(parser);
-      fclose(fp);
+      fclose(userData.fp);
       if (!result) {
         tremove(outName);
         exit(2);