another update from CVS HEAD, for QA
[alioth/jupp.git] / blocks.c
1 /*
2  *      Fast block move/copy subroutines
3  *      Copyright
4  *              (C) 1992 Joseph H. Allen
5  *
6  *      This file is part of JOE (Joe's Own Editor)
7  */
8 #include "config.h"
9
10 __RCSID("$MirOS: contrib/code/jupp/blocks.c,v 1.6 2017/12/02 02:07:23 tg Exp $");
11
12 /* This module requires ALIGNED and SIZEOF_INT to be defined correctly */
13
14 #include "blocks.h"
15
16 #define BITS 8
17
18 #if SIZEOF_INT == 8
19 #  define SHFT 3
20 #elif SIZEOF_INT == 4
21 #  define SHFT 2
22 #elif SIZEOF_INT == 2
23 #  define SHFT 1
24 #endif
25
26 /* Set 'sz' 'int's beginning at 'd' to the value 'c' */
27 /* Returns address of block.  Does nothing if 'sz' equals zero */
28
29 int *msetI(void *dest, int c, int sz)
30 {
31         int     *d = dest;
32         int     *orgd = dest;
33
34         while (sz >= 16) {
35                 d[0] = c;
36                 d[1] = c;
37                 d[2] = c;
38                 d[3] = c;
39                 d[4] = c;
40                 d[5] = c;
41                 d[6] = c;
42                 d[7] = c;
43                 d[8] = c;
44                 d[9] = c;
45                 d[10] = c;
46                 d[11] = c;
47                 d[12] = c;
48                 d[13] = c;
49                 d[14] = c;
50                 d[15] = c;
51                 d += 16;
52                 sz -= 16;
53         }
54         switch (sz) {
55         case 15:        d[14] = c;      /* FALLTHROUGH */
56         case 14:        d[13] = c;      /* FALLTHROUGH */
57         case 13:        d[12] = c;      /* FALLTHROUGH */
58         case 12:        d[11] = c;      /* FALLTHROUGH */
59         case 11:        d[10] = c;      /* FALLTHROUGH */
60         case 10:        d[9] = c;       /* FALLTHROUGH */
61         case 9:         d[8] = c;       /* FALLTHROUGH */
62         case 8:         d[7] = c;       /* FALLTHROUGH */
63         case 7:         d[6] = c;       /* FALLTHROUGH */
64         case 6:         d[5] = c;       /* FALLTHROUGH */
65         case 5:         d[4] = c;       /* FALLTHROUGH */
66         case 4:         d[3] = c;       /* FALLTHROUGH */
67         case 3:         d[2] = c;       /* FALLTHROUGH */
68         case 2:         d[1] = c;       /* FALLTHROUGH */
69         case 1:         d[0] = c;       /* FALLTHROUGH */
70         case 0:         /* do nothing */;
71         }
72         return orgd;
73 }
74
75 /* Set 'sz' 'int's beginning at 'd' to the value 'c' */
76 /* Returns address of block.  Does nothing if 'sz' equals zero */
77
78 void **msetP(void **d, void *c, int sz)
79 {
80         void    **orgd = d;
81
82         while (sz >= 16) {
83                 d[0] = c;
84                 d[1] = c;
85                 d[2] = c;
86                 d[3] = c;
87                 d[4] = c;
88                 d[5] = c;
89                 d[6] = c;
90                 d[7] = c;
91                 d[8] = c;
92                 d[9] = c;
93                 d[10] = c;
94                 d[11] = c;
95                 d[12] = c;
96                 d[13] = c;
97                 d[14] = c;
98                 d[15] = c;
99                 d += 16;
100                 sz -= 16;
101         }
102         switch (sz) {
103         case 15:        d[14] = c;      /* FALLTHROUGH */
104         case 14:        d[13] = c;      /* FALLTHROUGH */
105         case 13:        d[12] = c;      /* FALLTHROUGH */
106         case 12:        d[11] = c;      /* FALLTHROUGH */
107         case 11:        d[10] = c;      /* FALLTHROUGH */
108         case 10:        d[9] = c;       /* FALLTHROUGH */
109         case 9:         d[8] = c;       /* FALLTHROUGH */
110         case 8:         d[7] = c;       /* FALLTHROUGH */
111         case 7:         d[6] = c;       /* FALLTHROUGH */
112         case 6:         d[5] = c;       /* FALLTHROUGH */
113         case 5:         d[4] = c;       /* FALLTHROUGH */
114         case 4:         d[3] = c;       /* FALLTHROUGH */
115         case 3:         d[2] = c;       /* FALLTHROUGH */
116         case 2:         d[1] = c;       /* FALLTHROUGH */
117         case 1:         d[0] = c;       /* FALLTHROUGH */
118         case 0:         /* do nothing */;
119         }
120         return orgd;
121 }
122
123 /* Set 'sz' 'char's beginning at 'd' to the value 'c' */
124 /* Returns address of block.  Does nothing if 'sz' equals zero */
125
126 unsigned char *mset(void *dest, unsigned char c, int sz)
127 {
128         unsigned char   *d = dest;
129         unsigned char   *orgd = dest;
130
131         if (sz < 16) {
132                 switch (sz) {
133                 case 15:        d[14] = c;      /* FALLTHROUGH */
134                 case 14:        d[13] = c;      /* FALLTHROUGH */
135                 case 13:        d[12] = c;      /* FALLTHROUGH */
136                 case 12:        d[11] = c;      /* FALLTHROUGH */
137                 case 11:        d[10] = c;      /* FALLTHROUGH */
138                 case 10:        d[9] = c;       /* FALLTHROUGH */
139                 case 9:         d[8] = c;       /* FALLTHROUGH */
140                 case 8:         d[7] = c;       /* FALLTHROUGH */
141                 case 7:         d[6] = c;       /* FALLTHROUGH */
142                 case 6:         d[5] = c;       /* FALLTHROUGH */
143                 case 5:         d[4] = c;       /* FALLTHROUGH */
144                 case 4:         d[3] = c;       /* FALLTHROUGH */
145                 case 3:         d[2] = c;       /* FALLTHROUGH */
146                 case 2:         d[1] = c;       /* FALLTHROUGH */
147                 case 1:         d[0] = c;       /* FALLTHROUGH */
148                 case 0:         /* do nothing */;
149                 }
150         } else {
151                 unsigned z = SIZEOF_INT - ((unsigned long)d & (SIZEOF_INT - 1));
152
153                 if (z != SIZEOF_INT) {
154                         switch (z) {
155                         case 7:         d[6] = c;       /* FALLTHROUGH */
156                         case 6:         d[5] = c;       /* FALLTHROUGH */
157                         case 5:         d[4] = c;       /* FALLTHROUGH */
158                         case 4:         d[3] = c;       /* FALLTHROUGH */
159                         case 3:         d[2] = c;       /* FALLTHROUGH */
160                         case 2:         d[1] = c;       /* FALLTHROUGH */
161                         case 1:         d[0] = c;       /* FALLTHROUGH */
162                         case 0:         /* do nothing */;
163                         }
164                         d += z;
165                         sz -= z;
166                 }
167                 msetI(d,
168 #if SIZEOF_INT >= 8
169                       (c << (BITS * 7)) + (c << (BITS * 6)) + (c << (BITS * 5)) + (c << (BITS * 4)) +
170 #endif
171 #if SIZEOF_INT >= 4
172                       (c << (BITS * 3)) + (c << (BITS * 2)) +
173 #endif
174 #if SIZEOF_INT >= 2
175                       (c << BITS) +
176 #endif
177                       c, sz >> SHFT);
178                 d += sz & ~(SIZEOF_INT - 1);
179                 switch (sz & (SIZEOF_INT - 1)) {
180                 case 7:         d[6] = c;       /* FALLTHROUGH */
181                 case 6:         d[5] = c;       /* FALLTHROUGH */
182                 case 5:         d[4] = c;       /* FALLTHROUGH */
183                 case 4:         d[3] = c;       /* FALLTHROUGH */
184                 case 3:         d[2] = c;       /* FALLTHROUGH */
185                 case 2:         d[1] = c;       /* FALLTHROUGH */
186                 case 1:         d[0] = c;       /* FALLTHROUGH */
187                 case 0:         /* do nothing */;
188                 }
189         }
190         return orgd;
191 }
192
193 /* Copy a block of integers */
194 /* Copy from highest address to lowest */
195
196 static int *mbkwdI(void *dest, const void *src, int sz)
197 {
198         int     *d = dest;
199         const int *s = src;
200
201         if (d == s)
202                 return d;
203         d += sz;
204         s += sz;
205         while (sz >= 16) {
206                 d -= 16;
207                 s -= 16;
208                 d[15] = s[15];
209                 d[14] = s[14];
210                 d[13] = s[13];
211                 d[12] = s[12];
212                 d[11] = s[11];
213                 d[10] = s[10];
214                 d[9] = s[9];
215                 d[8] = s[8];
216                 d[7] = s[7];
217                 d[6] = s[6];
218                 d[5] = s[5];
219                 d[4] = s[4];
220                 d[3] = s[3];
221                 d[2] = s[2];
222                 d[1] = s[1];
223                 d[0] = s[0];
224                 sz -= 16;
225         }
226         d -= sz;
227         s -= sz;
228         switch (sz) {
229         case 15:        d[14] = s[14];  /* FALLTHROUGH */
230         case 14:        d[13] = s[13];  /* FALLTHROUGH */
231         case 13:        d[12] = s[12];  /* FALLTHROUGH */
232         case 12:        d[11] = s[11];  /* FALLTHROUGH */
233         case 11:        d[10] = s[10];  /* FALLTHROUGH */
234         case 10:        d[9] = s[9];    /* FALLTHROUGH */
235         case 9:         d[8] = s[8];    /* FALLTHROUGH */
236         case 8:         d[7] = s[7];    /* FALLTHROUGH */
237         case 7:         d[6] = s[6];    /* FALLTHROUGH */
238         case 6:         d[5] = s[5];    /* FALLTHROUGH */
239         case 5:         d[4] = s[4];    /* FALLTHROUGH */
240         case 4:         d[3] = s[3];    /* FALLTHROUGH */
241         case 3:         d[2] = s[2];    /* FALLTHROUGH */
242         case 2:         d[1] = s[1];    /* FALLTHROUGH */
243         case 1:         d[0] = s[0];    /* FALLTHROUGH */
244         case 0:         /* do nothing */;
245         }
246         return d;
247 }
248
249 /* Copy a block of 'int's.  Copy from lowest address to highest */
250
251 static int *mfwrdI(void *dest, const void *src, int sz)
252 {
253         int     *d = dest;
254         const int *s = src;
255         int     *od = d;
256
257         if (s == d)
258                 return d;
259         while (sz >= 16) {
260                 d[0] = s[0];
261                 d[1] = s[1];
262                 d[2] = s[2];
263                 d[3] = s[3];
264                 d[4] = s[4];
265                 d[5] = s[5];
266                 d[6] = s[6];
267                 d[7] = s[7];
268                 d[8] = s[8];
269                 d[9] = s[9];
270                 d[10] = s[10];
271                 d[11] = s[11];
272                 d[12] = s[12];
273                 d[13] = s[13];
274                 d[14] = s[14];
275                 d[15] = s[15];
276                 s += 16;
277                 d += 16;
278                 sz -= 16;
279         }
280         s -= 15 - sz;
281         d -= 15 - sz;
282         switch (sz) {
283         case 15:        d[0] = s[0];    /* FALLTHROUGH */
284         case 14:        d[1] = s[1];    /* FALLTHROUGH */
285         case 13:        d[2] = s[2];    /* FALLTHROUGH */
286         case 12:        d[3] = s[3];    /* FALLTHROUGH */
287         case 11:        d[4] = s[4];    /* FALLTHROUGH */
288         case 10:        d[5] = s[5];    /* FALLTHROUGH */
289         case 9:         d[6] = s[6];    /* FALLTHROUGH */
290         case 8:         d[7] = s[7];    /* FALLTHROUGH */
291         case 7:         d[8] = s[8];    /* FALLTHROUGH */
292         case 6:         d[9] = s[9];    /* FALLTHROUGH */
293         case 5:         d[10] = s[10];  /* FALLTHROUGH */
294         case 4:         d[11] = s[11];  /* FALLTHROUGH */
295         case 3:         d[12] = s[12];  /* FALLTHROUGH */
296         case 2:         d[13] = s[13];  /* FALLTHROUGH */
297         case 1:         d[14] = s[14];  /* FALLTHROUGH */
298         case 0:         /* do nothing */;
299         }
300         return od;
301 }
302
303 /* Copy the block of 'sz' bytes beginning at 's' to 'd'.  If 'sz' is zero or
304  * if 's'=='d', nothing happens.  The bytes at the highest address ('s'+'sz'-1)
305  * are copied before the ones at the lowest ('s') are.
306  */
307
308 static unsigned char *mbkwd(register unsigned char *d, register const unsigned char *s, register int sz)
309 {
310         if (s == d)
311                 return d;
312         s += sz;
313         d += sz;
314 #ifdef ALIGNED
315         if (sz >= 16)
316 #else
317         if (((unsigned long)s & (SIZEOF_INT - 1)) == ((unsigned long)d & (SIZEOF_INT - 1)) && sz >= 16)
318 #endif
319         {
320                 unsigned z = ((unsigned long) s & (SIZEOF_INT - 1));
321
322                 s -= z;
323                 d -= z;
324                 switch (z) {
325                 case 7:         d[6] = s[6];    /* FALLTHROUGH */
326                 case 6:         d[5] = s[5];    /* FALLTHROUGH */
327                 case 5:         d[4] = s[4];    /* FALLTHROUGH */
328                 case 4:         d[3] = s[3];    /* FALLTHROUGH */
329                 case 3:         d[2] = s[2];    /* FALLTHROUGH */
330                 case 2:         d[1] = s[1];    /* FALLTHROUGH */
331                 case 1:         d[0] = s[0];    /* FALLTHROUGH */
332                 case 0:         /* do nothing */;
333                 }
334                 sz -= z;
335                 mbkwdI(d - (sz & ~(SIZEOF_INT - 1)), s - (sz & ~(SIZEOF_INT - 1)), sz >> SHFT);
336                 d -= sz;
337                 s -= sz;
338                 switch (sz & (SIZEOF_INT - 1)) {
339                 case 7:         d[6] = s[6];    /* FALLTHROUGH */
340                 case 6:         d[5] = s[5];    /* FALLTHROUGH */
341                 case 5:         d[4] = s[4];    /* FALLTHROUGH */
342                 case 4:         d[3] = s[3];    /* FALLTHROUGH */
343                 case 3:         d[2] = s[2];    /* FALLTHROUGH */
344                 case 2:         d[1] = s[1];    /* FALLTHROUGH */
345                 case 1:         d[0] = s[0];    /* FALLTHROUGH */
346                 case 0:         /* do nothing */;
347                 }
348         } else {
349                 while (sz >= 16) {
350                         d -= 16;
351                         s -= 16;
352                         d[15] = s[15];
353                         d[14] = s[14];
354                         d[13] = s[13];
355                         d[12] = s[12];
356                         d[11] = s[11];
357                         d[10] = s[10];
358                         d[9] = s[9];
359                         d[8] = s[8];
360                         d[7] = s[7];
361                         d[6] = s[6];
362                         d[5] = s[5];
363                         d[4] = s[4];
364                         d[3] = s[3];
365                         d[2] = s[2];
366                         d[1] = s[1];
367                         d[0] = s[0];
368                         sz -= 16;
369                 }
370                 d -= sz;
371                 s -= sz;
372                 switch (sz) {
373                 case 15:        d[14] = s[14];  /* FALLTHROUGH */
374                 case 14:        d[13] = s[13];  /* FALLTHROUGH */
375                 case 13:        d[12] = s[12];  /* FALLTHROUGH */
376                 case 12:        d[11] = s[11];  /* FALLTHROUGH */
377                 case 11:        d[10] = s[10];  /* FALLTHROUGH */
378                 case 10:        d[9] = s[9];    /* FALLTHROUGH */
379                 case 9:         d[8] = s[8];    /* FALLTHROUGH */
380                 case 8:         d[7] = s[7];    /* FALLTHROUGH */
381                 case 7:         d[6] = s[6];    /* FALLTHROUGH */
382                 case 6:         d[5] = s[5];    /* FALLTHROUGH */
383                 case 5:         d[4] = s[4];    /* FALLTHROUGH */
384                 case 4:         d[3] = s[3];    /* FALLTHROUGH */
385                 case 3:         d[2] = s[2];    /* FALLTHROUGH */
386                 case 2:         d[1] = s[1];    /* FALLTHROUGH */
387                 case 1:         d[0] = s[0];    /* FALLTHROUGH */
388                 case 0:         /* do nothing */;
389                 }
390         }
391         return d;
392 }
393
394 /* Copy the block of 'sz' bytes beginning at 's' to 'd'.  If 'sz' is zero or
395  * if 's'=='d', nothing happens.  The bytes at the lowest address ('s')
396  * are copied before the ones at the highest ('s'+'sz'-1) are.
397  */
398
399 static unsigned char *mfwrd(register unsigned char *d, register const unsigned char *s, register int sz)
400 {
401         unsigned char *od = d;
402
403         if (d == s)
404                 return d;
405 #ifdef ALIGNED
406         if (sz >= 16)
407 #else
408         if (((unsigned long)d & (SIZEOF_INT - 1)) == ((unsigned long)s & (SIZEOF_INT - 1)) && sz >= 16)
409 #endif
410         {
411                 unsigned z = ((unsigned long)s & (SIZEOF_INT - 1));
412
413                 if (z) {
414                         s -= z;
415                         d -= z;
416                         switch (SIZEOF_INT - z) {
417 #if SIZEOF_INT == 8
418                         case 7:         d[1] = s[1];    /* FALLTHROUGH */
419                         case 6:         d[2] = s[2];    /* FALLTHROUGH */
420                         case 5:         d[3] = s[3];    /* FALLTHROUGH */
421                         case 4:         d[4] = s[4];    /* FALLTHROUGH */
422                         case 3:         d[5] = s[5];    /* FALLTHROUGH */
423                         case 2:         d[6] = s[6];    /* FALLTHROUGH */
424                         case 1:         d[7] = s[7];    /* FALLTHROUGH */
425                         case 0:         /* do nothing */;
426 #else
427 #if SIZEOF_INT == 4
428                         case 3:         d[1] = s[1];    /* FALLTHROUGH */
429                         case 2:         d[2] = s[2];    /* FALLTHROUGH */
430                         case 1:         d[3] = s[3];    /* FALLTHROUGH */
431                         case 0:         /* do nothing */;
432 #else
433 #if SIZEOF_INT == 2
434                         case 1:         d[1] = s[1];    /* FALLTHROUGH */
435                         case 0:         /* do nothing */;
436 #endif
437 #endif
438 #endif
439                         }
440                         s += SIZEOF_INT;
441                         d += SIZEOF_INT;
442                         sz -= SIZEOF_INT - z;
443                 }
444                 mfwrdI(d, s, sz >> SHFT);
445                 s += sz - (SIZEOF_INT - 1);
446                 d += sz - (SIZEOF_INT - 1);
447                 switch (sz & (SIZEOF_INT - 1)) {
448 #if SIZEOF_INT == 8
449                 case 7:         d[0] = s[0];    /* FALLTHROUGH */
450                 case 6:         d[1] = s[1];    /* FALLTHROUGH */
451                 case 5:         d[2] = s[2];    /* FALLTHROUGH */
452                 case 4:         d[3] = s[3];    /* FALLTHROUGH */
453                 case 3:         d[4] = s[4];    /* FALLTHROUGH */
454                 case 2:         d[5] = s[5];    /* FALLTHROUGH */
455                 case 1:         d[6] = s[6];    /* FALLTHROUGH */
456                 case 0:         /* do nothing */;
457 #else
458 #if SIZEOF_INT == 4
459                 case 3:         d[0] = s[0];    /* FALLTHROUGH */
460                 case 2:         d[1] = s[1];    /* FALLTHROUGH */
461                 case 1:         d[2] = s[2];    /* FALLTHROUGH */
462                 case 0:         /* do nothing */;
463 #else
464 #if SIZEOF_INT == 2
465                 case 1:         d[0] = s[0];    /* FALLTHROUGH */
466                 case 0:         /* do nothing */;
467 #endif
468 #endif
469 #endif
470                 }
471         } else {
472                 while (sz >= 16) {
473                         d[0] = s[0];
474                         d[1] = s[1];
475                         d[2] = s[2];
476                         d[3] = s[3];
477                         d[4] = s[4];
478                         d[5] = s[5];
479                         d[6] = s[6];
480                         d[7] = s[7];
481                         d[8] = s[8];
482                         d[9] = s[9];
483                         d[10] = s[10];
484                         d[11] = s[11];
485                         d[12] = s[12];
486                         d[13] = s[13];
487                         d[14] = s[14];
488                         d[15] = s[15];
489                         s += 16;
490                         d += 16;
491                         sz -= 16;
492                 }
493                 s -= 15 - sz;
494                 d -= 15 - sz;
495                 switch (sz) {
496                 case 15:        d[0] = s[0];    /* FALLTHROUGH */
497                 case 14:        d[1] = s[1];    /* FALLTHROUGH */
498                 case 13:        d[2] = s[2];    /* FALLTHROUGH */
499                 case 12:        d[3] = s[3];    /* FALLTHROUGH */
500                 case 11:        d[4] = s[4];    /* FALLTHROUGH */
501                 case 10:        d[5] = s[5];    /* FALLTHROUGH */
502                 case 9:         d[6] = s[6];    /* FALLTHROUGH */
503                 case 8:         d[7] = s[7];    /* FALLTHROUGH */
504                 case 7:         d[8] = s[8];    /* FALLTHROUGH */
505                 case 6:         d[9] = s[9];    /* FALLTHROUGH */
506                 case 5:         d[10] = s[10];  /* FALLTHROUGH */
507                 case 4:         d[11] = s[11];  /* FALLTHROUGH */
508                 case 3:         d[12] = s[12];  /* FALLTHROUGH */
509                 case 2:         d[13] = s[13];  /* FALLTHROUGH */
510                 case 1:         d[14] = s[14];  /* FALLTHROUGH */
511                 case 0:         /* do nothing */;
512                 }
513         }
514         return od;
515 }
516
517 void *mmove(void *d, const void *s, int sz)
518 {
519         if (d > s)
520                 mbkwd(d, s, sz);
521         else
522                 mfwrd(d, s, sz);
523         return d;
524 }
525
526 /* Utility to count number of lines within a segment */
527
528 int mcnt(register unsigned char *blk, register unsigned char c, int size)
529 {
530         register int nlines = 0;
531
532         while (size >= 16) {
533                 if (blk[0] == c) ++nlines;
534                 if (blk[1] == c) ++nlines;
535                 if (blk[2] == c) ++nlines;
536                 if (blk[3] == c) ++nlines;
537                 if (blk[4] == c) ++nlines;
538                 if (blk[5] == c) ++nlines;
539                 if (blk[6] == c) ++nlines;
540                 if (blk[7] == c) ++nlines;
541                 if (blk[8] == c) ++nlines;
542                 if (blk[9] == c) ++nlines;
543                 if (blk[10] == c) ++nlines;
544                 if (blk[11] == c) ++nlines;
545                 if (blk[12] == c) ++nlines;
546                 if (blk[13] == c) ++nlines;
547                 if (blk[14] == c) ++nlines;
548                 if (blk[15] == c) ++nlines;
549                 blk += 16;
550                 size -= 16;
551         }
552         switch (size) {
553         case 15:        if (blk[14] == c) ++nlines;     /* FALLTHROUGH */
554         case 14:        if (blk[13] == c) ++nlines;     /* FALLTHROUGH */
555         case 13:        if (blk[12] == c) ++nlines;     /* FALLTHROUGH */
556         case 12:        if (blk[11] == c) ++nlines;     /* FALLTHROUGH */
557         case 11:        if (blk[10] == c) ++nlines;     /* FALLTHROUGH */
558         case 10:        if (blk[9] == c) ++nlines;      /* FALLTHROUGH */
559         case 9:         if (blk[8] == c) ++nlines;      /* FALLTHROUGH */
560         case 8:         if (blk[7] == c) ++nlines;      /* FALLTHROUGH */
561         case 7:         if (blk[6] == c) ++nlines;      /* FALLTHROUGH */
562         case 6:         if (blk[5] == c) ++nlines;      /* FALLTHROUGH */
563         case 5:         if (blk[4] == c) ++nlines;      /* FALLTHROUGH */
564         case 4:         if (blk[3] == c) ++nlines;      /* FALLTHROUGH */
565         case 3:         if (blk[2] == c) ++nlines;      /* FALLTHROUGH */
566         case 2:         if (blk[1] == c) ++nlines;      /* FALLTHROUGH */
567         case 1:         if (blk[0] == c) ++nlines;      /* FALLTHROUGH */
568         case 0:         /* do nothing */;
569         }
570         return nlines;
571 }