Check Only Mode
Check whether the input files are in sorted order.
This does not sort any of the files.
Notes
Currently this also includes multiple file sort (in check()).
How should this be factored out?
This is a registered behavior:
register the functional behavior
register the parsing behavior
link the two behaviors together
- Define exit code for CheckMode
-
Constant definition
- Segment Source
-
63: /* Use this as exit status in case of error, not EXIT_FAILURE. This
64: is necessary because EXIT_FAILURE is usually 1 and POSIX requires
65: that sort exit with status 1 IFF invoked with -c and the input is
66: not properly sorted. Any other irregular exit must exit with a
67: status code greater than 1. */
68: #define SORT_FAILURE 2
69:
- Define check buffer allocation size (mergealloc)
- Constant definition
- Notes
-
The merge buffer size is reused in the CheckMode concern.
A separate and distinct constant might be more appropriate.
It would also be quite pendantic.
- Segment Source
-
169: /* Initial buffer size for in core merge buffers. Bear in mind that
170: up to NMERGE * mergealloc bytes may be allocated for merge buffers. */
171: static int mergealloc = 16 * 1024;
172:
- Define default line Length (linelength)
- Constant definition
- Segment Source
-
173: /* Guess of average line length. */
174: static int linelength = 30;
175:
- Insert user message text
-
Text insertion
- Segment Source
-
222: -c check if given files already sorted, do not sort\n\
- Define checkfp()
-
Function definition
- Segment Source
-
1206: /* Check that the lines read from the given FP come in order. Return
1207: 1 if they do and 0 if there is a disorder.
1208: FIXME: return number of first out-of-order line if not sorted. */
1209:
1210: static int
1211: checkfp (FILE *fp)
1212: {
1213: struct buffer buf; /* Input buffer. */
1214: struct lines lines; /* Lines scanned from the buffer. */
1215: struct line temp; /* Copy of previous line. */
1216: int cc; /* Character count. */
1217: int alloc, sorted = 1;
1218:
1219: initbuf (&buf, mergealloc);
1220: initlines (&lines, mergealloc / linelength + 1,
1221: LINEALLOC / ((NMERGE + NMERGE) * sizeof (struct line)));
1222: alloc = linelength;
1223: temp.text = xmalloc (alloc);
1224:
1225: cc = fillbuf (&buf, fp);
1226: if (cc == 0)
1227: goto finish;
1228:
1229: findlines (&buf, &lines);
1230:
1231: while (1)
1232: {
1233: struct line *prev_line; /* Pointer to previous line. */
1234: int cmp; /* Result of calling compare. */
1235: int i;
1236:
1237: /* Compare each line in the buffer with its successor. */
1238: for (i = 0; i < lines.used - 1; ++i)
1239: {
1240: cmp = compare (&lines.lines[i], &lines.lines[i + 1]);
1241: if ((unique && cmp >= 0) || (cmp > 0))
1242: {
1243: sorted = 0;
1244: goto finish;
1245: }
1246: }
1247:
1248: /* Save the last line of the buffer and refill the buffer. */
1249: prev_line = lines.lines + (lines.used - 1);
1250: if (prev_line->length + 1 > alloc)
1251: {
1252: do
1253: {
1254: alloc *= 2;
1255: }
1256: while (alloc < prev_line->length + 1);
1257: temp.text = xrealloc (temp.text, alloc);
1258: }
1259: assert (prev_line->length + 1 <= alloc);
1260: memcpy (temp.text, prev_line->text, prev_line->length + 1);
1261: temp.length = prev_line->length;
1262: temp.keybeg = temp.text + (prev_line->keybeg - prev_line->text);
1263: temp.keylim = temp.text + (prev_line->keylim - prev_line->text);
1264:
1265: cc = fillbuf (&buf, fp);
1266: if (cc == 0)
1267: break;
1268:
1269: findlines (&buf, &lines);
1270: /* Make sure the line saved from the old buffer contents is
1271: less than or equal to the first line of the new buffer. */
1272: cmp = compare (&temp, &lines.lines[0]);
1273: if ((unique && cmp >= 0) || (cmp > 0))
1274: {
1275: sorted = 0;
1276: break;
1277: }
1278: }
1279:
1280: finish:
1281: xfclose (fp);
1282: free (buf.buf);
1283: free ((char *) lines.lines);
1284: free (temp.text);
1285: return sorted;
1286: }
1287:
- Define check()
- Function definition
- Notes
-
Does this use ErrMsg:Disorder() or does it extend
ErrMsg to have Disorder support?
This primarily supports the SrcSpec concern.
It adds multiple file support to the basic check validation capability.
- Segment Source
-
1491: /* Check that each of the NFILES FILES is ordered.
1492: Return a count of disordered files. */
1493:
1494: static int
1495: check (char **files, int nfiles)
1496: {
1497: int i, disorders = 0;
1498: FILE *fp;
1499:
1500: for (i = 0; i < nfiles; ++i)
1501: {
1502: fp = xfopen (files[i], "r");
1503: if (!checkfp (fp))
1504: {
1505: fprintf (stderr, _("%s: disorder on %s\n"), program_name, files[i]);
1506: ++disorders;
1507: }
1508: }
1509: return disorders;
1510: }
1511:
- Define check only flag (checkonly)
-
Variable definition
- Segment Source
-
1721: int checkonly = 0, mergeonly = 0, nfiles = 0;
- Parse CheckOnly option (-c)
-
Code insertion
- Segment Source
-
1840: case 'c':
1841: checkonly = 1;
1842: break;
- Dispatch checkonly option
-
Code insertion
- Notes
-
It's quite a surprise that this code does not use the
manifest constants EXIT_SUCCESS and EXIT_FAILURE (or
the "should be declared" constant EXIT_DISORDER).
- Segment Source
- 2057: if (checkonly)
2058: {
2059: /* POSIX requires that sort return 1 IFF invoked with -c and the
2060: input is not properly sorted. */
2061: exit (check (files, nfiles) == 0 ? 0 : 1);
2062: }
2063: