Last Record Rollover
Last Record Rollover

Rollover the last record of each buffer for comparision to the first record of the refilled buffer. This ensures that files read with multiple buffers are treated as a continuous sequential stream.

Notes
This is complicated be the handling of input through multiple buffers. The roll-over cases from one buffer to the next consume a substantial amount of code.

Buffered IO Support in CheckMode
Notes
This code duplicates the last line of the input buffer. The checkfp() routines requires this to handle order validation in multi-buffer files. Since unique validation is an extension on order validation, it is also part of that process. A very similar behavior is also performed in mergefps() (lines 1355-1390). However, mergerfps() duplicates and tests the last line of an input buffer only to support the UniqueOpt feature. These two cases of last line duplication appear to be written by different people.
Segment Element
Variable declaration

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: 

Segment Element
Code insertion

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: 

Segment Element
Variable declaration

1233:       struct line *prev_line;   /* Pointer to previous line. */

Segment Element
Code insertion

Notes
This code duplicates the primary comparision logic at lines 1270-1277. This duplication is induced by large file support that uses multiple buffers.
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:         }