]> granicus.if.org Git - libexpat/commitdiff
Sort notations by name in xmlwf for conformance tests
authorRhodri James <rhodri@kynesim.co.uk>
Wed, 5 Jul 2017 14:56:10 +0000 (15:56 +0100)
committerSebastian Pipping <sebastian@pipping.org>
Tue, 22 Aug 2017 20:21:10 +0000 (22:21 +0200)
expat/xmlwf/xmlwf.c

index 1f63b3411cbd6ea19acad218e91b1fa3033a26ad..93a22f57f7204eaa2fcf53b43328e43f31093c02 100644 (file)
@@ -307,49 +307,108 @@ startDoctypeDecl(void *UNUSED_P(userData),
   currentDoctypeName = xmlCharDup(doctypeName);
 }
 
+static void
+freeNotations(void)
+{
+  while (notationListHead != NULL) {
+    NotationList *next = notationListHead->next;
+    free((void *)notationListHead->notationName);
+    free((void *)notationListHead->systemId);
+    free((void *)notationListHead->publicId);
+    free(notationListHead);
+    notationListHead = next;
+  }
+}
+
+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)
 {
   FILE *fp = (FILE *)userData;
+  NotationList **notations;
+  int notationCount = 0;
+  NotationList *p;
+  int i;
 
-  if (notationListHead != NULL) {
-    /* Output the DOCTYPE header */
-    fputts(T("<!DOCTYPE "), fp);
-    fputts(currentDoctypeName, fp);
-    fputts(T(" [\n"), fp);
-
-    /* Now the NOTATIONs */
-    while (notationListHead != NULL) {
-      NotationList *next = notationListHead->next;
-      fputts(T("<!NOTATION "), fp);
-      fputts(notationListHead->notationName, fp);
-      if (notationListHead->publicId != NULL) {
-        fputts(T(" PUBLIC '"), fp);
-        fputts(notationListHead->publicId, fp);
+  /* How many notations do we have? */
+  for (p = notationListHead; p != NULL; p = p->next)
+    notationCount++;
+  if (notationCount == 0)
+    return; /* Nothing to report */
+
+  notations = malloc(notationCount * sizeof(NotationList *));
+  if (notations == NULL) {
+    fprintf(stderr, "Unable to sort notations");
+    freeNotations();
+    return;
+  }
+
+  for (p = 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 "), fp);
+  fputts(currentDoctypeName, fp);
+  fputts(T(" [\n"), fp);
+
+  /* Now the NOTATIONs */
+  for (i = 0; i < notationCount; i++) {
+    fputts(T("<!NOTATION "), fp);
+    fputts(notations[i]->notationName, fp);
+    if (notations[i]->publicId != NULL) {
+      fputts(T(" PUBLIC '"), fp);
+      fputts(notations[i]->publicId, fp);
+      puttc(T('\''), fp);
+      if (notations[i]->systemId != NULL) {
+        puttc(T(' '), fp);
         puttc(T('\''), fp);
-        if (notationListHead->systemId != NULL) {
-            puttc(T(' '), fp);
-            puttc(T('\''), fp);
-            fputts(notationListHead->systemId, fp);
-            puttc(T('\''), fp);
-        }
-      }
-      else if (notationListHead->systemId != NULL) {
-        fputts(T(" SYSTEM '"), fp);
-        fputts(notationListHead->systemId, fp);
+        fputts(notations[i]->systemId, fp);
         puttc(T('\''), fp);
       }
-      puttc(T('>'), fp);
-      puttc(T('\n'), fp);
-      free((void *)notationListHead->notationName);
-      free((void *)notationListHead->systemId);
-      free((void *)notationListHead->publicId);
-      free(notationListHead);
-      notationListHead = next;
     }
-    /* Finally end the DOCTYPE */
-    fputts(T("]>\n"), fp);
+    else if (notations[i]->systemId != NULL) {
+      fputts(T(" SYSTEM '"), fp);
+      fputts(notations[i]->systemId, fp);
+      puttc(T('\''), fp);
+    }
+    puttc(T('>'), fp);
+    puttc(T('\n'), fp);
   }
+
+  /* Finally end the DOCTYPE */
+  fputts(T("]>\n"), fp);
+
+  free(notations);
+  freeNotations();
   free((void *)currentDoctypeName);
   currentDoctypeName = NULL;
 }