1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <ctype.h>
22: #include <error.h>
23: #include <locale.h>
24: #include <stdio.h>
25: #include <stdlib.h>
26: #include <string.h>
27:
28:
29: struct lines
30: {
31: char *xfrm;
32: char *line;
33: };
34:
35: static int xstrcmp (const void *, const void *);
36:
37: int
38: main (int argc, char *argv[])
39: {
40: int result = 0;
41: size_t nstrings, nstrings_max;
42: struct lines *strings;
43: char *line = NULL;
44: size_t len = 0;
45: size_t n;
46:
47: if (argc < 2)
48: error (1, 0, "usage: %s <random seed>", argv[0]);
49:
50: setlocale (LC_ALL, "");
51:
52: nstrings_max = 100;
53: nstrings = 0;
54: strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines));
55: if (strings == NULL)
56: {
57: perror (argv[0]);
58: exit (1);
59: }
60:
61: while (1)
62: {
63: char saved, *newp;
64: int needed;
65: int l;
66: if (getline (&line, &len, stdin) < 0)
67: break;
68:
69: if (nstrings == nstrings_max)
70: {
71: strings = (struct lines *) realloc (strings,
72: (nstrings_max *= 2)
73: * sizeof (*strings));
74: if (strings == NULL)
75: {
76: perror (argv[0]);
77: exit (1);
78: }
79: }
80: strings[nstrings].line = strdup (line);
81: l = strcspn (line, ":(;");
82: while (l > 0 && isspace (line[l - 1]))
83: --l;
84:
85: saved = line[l];
86: line[l] = '\0';
87: needed = strxfrm (NULL, line, 0);
88: newp = malloc (needed + 1);
89: strxfrm (newp, line, needed + 1);
90: strings[nstrings].xfrm = newp;
91: line[l] = saved;
92: ++nstrings;
93: }
94: free (line);
95:
96:
97: srandom (atoi (argv[1]));
98: for (n = 0; n < 10 * nstrings; ++n)
99: {
100: int r1, r2, r;
101: size_t idx1 = random () % nstrings;
102: size_t idx2 = random () % nstrings;
103: struct lines tmp = strings[idx1];
104: strings[idx1] = strings[idx2];
105: strings[idx2] = tmp;
106:
107:
108: r1 = strcmp (strings[idx1].xfrm, strings[idx2].xfrm);
109: r2 = strcmp (strings[idx2].xfrm, strings[idx1].xfrm);
110: r = -(r1 ^ r2);
111: if (r)
112: r /= abs (r1 ^ r2);
113:
114: if (r < 0 || (r == 0 && (r1 != 0 || r2 != 0))
115: || (r > 0 && (r1 ^ r2) >= 0))
116: printf ("collate wrong: %d vs. %d\n", r1, r2);
117: }
118:
119:
120: qsort (strings, nstrings, sizeof (struct lines), xstrcmp);
121:
122:
123: for (n = 0; n < nstrings; ++n)
124: {
125: fputs (strings[n].line, stdout);
126: free (strings[n].line);
127: free (strings[n].xfrm);
128: }
129: free (strings);
130:
131: return result;
132: }
133:
134:
135: static int
136: xstrcmp (ptr1, ptr2)
137: const void *ptr1;
138: const void *ptr2;
139: {
140: const struct lines *l1 = (const struct lines *) ptr1;
141: const struct lines *l2 = (const struct lines *) ptr2;
142:
143: return strcmp (l1->xfrm, l2->xfrm);
144: }