File: | dmake/unix/arlib.c |
Location: | line 521, column 21 |
Description: | Result of 'malloc' is converted to a pointer of type 'struct mem', which is incompatible with sizeof operand type 'char' |
1 | /* |
2 | -- |
3 | -- SYNOPSIS |
4 | -- Unix archive manipulation code. |
5 | -- |
6 | -- DESCRIPTION |
7 | -- Originally this code was provided by Eric Gisin of MKS. I took |
8 | -- his code and completely rewrote it adding cacheing of lib members |
9 | -- and other various optimizations. I kept the overal functional |
10 | -- idea of the library routines as they are similar to those in GNU |
11 | -- make and felt it advantageous to maintain a similar interface. |
12 | -- |
13 | -- AUTHOR |
14 | -- Dennis Vadura, dvadura@dmake.wticorp.com |
15 | -- |
16 | -- WWW |
17 | -- http://dmake.wticorp.com/ |
18 | -- |
19 | -- COPYRIGHT |
20 | -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved. |
21 | -- |
22 | -- This program is NOT free software; you can redistribute it and/or |
23 | -- modify it under the terms of the Software License Agreement Provided |
24 | -- in the file <distribution-root>/readme/license.txt. |
25 | -- |
26 | -- LOG |
27 | -- Use cvs log to obtain detailed change logs. |
28 | */ |
29 | |
30 | /* Sun unix on 386i's has a broken ar.h that does not assume PORTAR format |
31 | * by default, so we fix it here. */ |
32 | #if defined(i3861) || defined(__DGUX__) |
33 | #define PORTAR1 1 |
34 | #endif |
35 | |
36 | #if !defined (COHERENT) && !defined(__COHERENT__) |
37 | #include <ar.h> |
38 | #else |
39 | #include <arcoff.h> |
40 | #endif /* COHERENT, __COHERENT__ */ |
41 | #include "extern.h" |
42 | #include "sysintf.h" |
43 | |
44 | /* By defining the defines below it is possible to configure the library |
45 | * code for library cacheing/non-cacheing, ASCII archive headers, and a full |
46 | * decode of the ar_hdr fields in the scan_ar function. */ |
47 | |
48 | #ifndef ASCARCH1 |
49 | #define ASCARCH1 1 /* ASCII time stored in archive */ |
50 | #endif |
51 | |
52 | #ifndef LC1 |
53 | #define LC1 1 /* Turn on library cacheing */ |
54 | #endif |
55 | |
56 | #ifndef CHECKELF1 |
57 | #define CHECKELF1 1 /* Enable Elf long member names */ |
58 | #endif |
59 | |
60 | #ifndef DECODE_ALL_AR_FIELDS0 |
61 | #define DECODE_ALL_AR_FIELDS0 0 /* decode only fields make needs*/ |
62 | #endif |
63 | |
64 | #ifndef AR_TRUNCATE_MEMBER_NAMES0 |
65 | #define AR_TRUNCATE_MEMBER_NAMES0 0 /* truncate member names for */ |
66 | #endif /* comparison. */ |
67 | |
68 | #if LC1 |
69 | # define FOUND_MEMBER0 FALSE0 |
70 | #else |
71 | # define FOUND_MEMBER0 TRUE1 |
72 | # define _cache_member(a, b, c) |
73 | # define _check_cache(a, b, c, d) FALSE0 |
74 | #endif |
75 | |
76 | #define MAXFNAME255 255 /* Max length of member name */ |
77 | #define MAXMNAME8 8 /* Max module name < MAXFNAME */ |
78 | |
79 | |
80 | /* This struct is used to pass the library and member inrmation about the |
81 | * routines that perform the library seeking/cacheing */ |
82 | struct ar_args { |
83 | char *lib; |
84 | char *member; |
85 | time_t time; |
86 | }; |
87 | |
88 | |
89 | typedef struct AR { |
90 | char ar_name[MAXFNAME255+1]; /* File name */ |
91 | long ar_size; /* Size in bytes */ |
92 | time_t ar_time; /* Modification time */ |
93 | |
94 | #ifdef DOS |
95 | char ar_modname[MAXMNAME8+1]; /* DOS module name */ |
96 | #endif |
97 | |
98 | #if DECODE_ALL_AR_FIELDS0 |
99 | uint16 ar_mode; /* File mode */ |
100 | uint16 ar_uid; /* File owner */ |
101 | uint16 ar_gid; /* File group owner */ |
102 | #endif |
103 | } AR, *ARPTR; |
104 | |
105 | |
106 | static int ar_scan ANSI((FILE *,(FILE *, int (*) (FILE *, struct AR *,struct ar_args *), struct ar_args *) |
107 | int (*) ANSI((FILE *, struct AR *,struct ar_args *)),(FILE *, int (*) (FILE *, struct AR *,struct ar_args *), struct ar_args *) |
108 | struct ar_args *))(FILE *, int (*) (FILE *, struct AR *,struct ar_args *), struct ar_args *); |
109 | static int ar_touch ANSI(( FILE *, time_t ))( FILE *, time_t ); |
110 | static int time_function ANSI(( FILE *, struct AR *, struct ar_args * ))( FILE *, struct AR *, struct ar_args * ); |
111 | static int touch_function ANSI(( FILE *, struct AR *, struct ar_args * ))( FILE *, struct AR *, struct ar_args * ); |
112 | static int ar_name_equal ANSI((char *, char *))(char *, char *); |
113 | |
114 | #if LC1 |
115 | static int _cache_member ANSI((char *, char *, time_t))(char *, char *, time_t); |
116 | static int _check_cache ANSI((char *, char *, time_t *, int))(char *, char *, time_t *, int); |
117 | #endif |
118 | |
119 | /* decoded archive header */ |
120 | static AR _ar; |
121 | static off_t arhdroffset; /* member seek offset */ |
122 | |
123 | |
124 | PUBLIC time_t |
125 | seek_arch(name, lib)/* |
126 | ====================== |
127 | Look for module 'name' inside 'lib'. If compiled with cacheing then first |
128 | check to see if the specified lib is cached. If so then return that time |
129 | stamp instead of looking into the library. */ |
130 | char *name; |
131 | char *lib; |
132 | { |
133 | FILE *f; |
134 | int rv; |
135 | time_t mtime; |
136 | struct ar_args args; |
137 | |
138 | /* Check the cache first (if there is a cache) */ |
139 | if( _check_cache(name, lib, &mtime, FALSE0) ) return( mtime ); |
140 | |
141 | /* Open the lib file and perform the scan of the members, looking |
142 | * for our particular member. If cacheing is enabled it will be |
143 | * taken care of automatically during the scan. */ |
144 | |
145 | args.lib = lib; |
146 | args.member = name; |
147 | args.time = (time_t)0L; |
148 | |
149 | if( (f = fopen(lib, "r")) == NIL(FILE)((FILE*)((void*)0)) ) return( (time_t)0L ); |
150 | rv = ar_scan(f, time_function, &args ); |
151 | fclose( f ); |
152 | |
153 | if( rv < 0 ) Fatal("(%s): Invalid library format", lib); |
154 | |
155 | return( args.time ); |
156 | } |
157 | |
158 | |
159 | PUBLIC int |
160 | touch_arch(name, lib)/* |
161 | ======================= |
162 | Look for module 'name' inside 'lib'. If compiled with cacheing then first |
163 | check to see if the specified lib is cached. If so then set that time |
164 | stamp and write it into the library. Returns 0 on success, non-zero |
165 | on failure. */ |
166 | char *name; |
167 | char *lib; |
168 | { |
169 | FILE *f; |
170 | int rv; |
171 | struct ar_args args; |
172 | |
173 | /* Open the lib file and perform the scan of the members, looking |
174 | * for our particular member. If cacheing is enabled it will be |
175 | * taken care of automatically during the scan. */ |
176 | |
177 | args.lib = lib; |
178 | args.member = name; |
179 | args.time = (time_t)0L; |
180 | |
181 | if( (f = fopen(lib, "r+")) == NIL(FILE)((FILE*)((void*)0)) ) return( (time_t)1L ); |
182 | rv = ar_scan(f, touch_function, &args ); |
183 | fclose( f ); |
184 | |
185 | if( rv < 0 ) Fatal("(%s): Invalid library format", lib); |
186 | |
187 | return( 0 ); |
188 | } |
189 | |
190 | |
191 | |
192 | static int |
193 | time_function(f, arp, argp)/* |
194 | ============================= |
195 | get library member's time, if it matches than return it in argp, if |
196 | cacheing is enabled than cache the library members also. */ |
197 | FILE *f; /* library file */ |
198 | struct AR *arp; /* library member header */ |
199 | struct ar_args *argp; |
200 | { |
201 | int rv = _cache_member( arp->ar_name, argp->lib, arp->ar_time ); |
202 | |
203 | if( ar_name_equal (argp->member, arp->ar_name)) { |
204 | argp->time = arp->ar_time; |
205 | |
206 | if( arp->ar_time == 0 && !(Glob_attr & A_SILENT0x00002) ) |
207 | Warning( "(%s): Can't extract library member timestamp; using EPOCH", |
208 | argp->member); |
209 | |
210 | return( rv ); /* 1 => no cacheing, 0 => cacheing */ |
211 | } |
212 | |
213 | return( FALSE0 ); /* continue scan */ |
214 | } |
215 | |
216 | |
217 | |
218 | static int |
219 | touch_function(f, arp, argp)/* |
220 | ============================== |
221 | Update library member's time stamp, and write new time value into cache |
222 | if required. */ |
223 | FILE *f; /* library file */ |
224 | struct AR *arp; /* library member header */ |
225 | struct ar_args *argp; |
226 | { |
227 | extern time_t time ANSI(( time_t * ))( time_t * ); |
228 | time_t now = time((time_t*) NULL((void*)0)); /* Current time. */ |
229 | |
230 | if( ar_name_equal(argp->member, arp->ar_name) ) { |
231 | _check_cache( argp->member, argp->lib, &now, TRUE1 ); |
232 | ar_touch(f, now ); |
233 | |
234 | return( TRUE1 ); |
235 | } |
236 | |
237 | return( FALSE0 ); /* continue scan */ |
238 | } |
239 | |
240 | |
241 | static int |
242 | ar_name_equal (char * name1, char * name2) |
243 | { |
244 | int equal; |
245 | |
246 | #if AR_TRUNCATE_MEMBER_NAMES0 |
247 | struct ar_hdr hdr; |
248 | |
249 | equal = !strncmp (name1, name2, sizeof (hdr.ar_name)-1); |
250 | #else |
251 | equal = !strcmp (name1, name2); |
252 | #endif |
253 | |
254 | return equal; |
255 | } |
256 | |
257 | |
258 | static int |
259 | ar_scan(f, function, arg)/* |
260 | =========================== |
261 | Scan the opened archive, and call the given function for each member found. |
262 | The function will be called with the file positioned at the beginning of |
263 | the member and it can read up to arp->ar_size bytes of the archive member. |
264 | If the function returns 1, we stop and return 1. We return 0 at the end |
265 | of the archive, or -1 if the archive has invalid format. This interface |
266 | is more general than required by "make", but it can be used by other |
267 | utilities. */ |
268 | register FILE *f; |
269 | int (*function) ANSI((FILE *, struct AR *, struct ar_args *))(FILE *, struct AR *, struct ar_args *); |
270 | struct ar_args *arg; |
271 | { |
272 | extern long atol (); |
273 | register char *p; |
274 | struct ar_hdr arhdr; /* archive member header */ |
275 | long nsize; /* size of member name */ |
276 | long arind=0; /* archive index offset */ |
277 | int process; |
278 | #if defined(_AIX) |
279 | struct fl_hdr flhdr; /* archive file header */ |
280 | char magic[SAIAMAG]; /* size of magic string */ |
281 | #else |
282 | #if ASCARCH1 |
283 | char magic[SARMAG8]; |
284 | #else |
285 | unsigned short word; |
286 | #endif |
287 | #endif |
288 | |
289 | fseek( f, 0L, 0 ); /* Start at the beginning of the archive file */ |
290 | |
291 | #if ASCARCH1 |
292 | #if defined(_AIX) |
293 | fread( (char *)&flhdr, sizeof(flhdr), 1, f ); |
294 | if( strncmp(flhdr.fl_magic,AIAMAG, SAIAMAG) != 0 ) return(-1); |
295 | fseek(f, atol(flhdr.fl_fstmoff), 0 ); /* postition to first member */ |
296 | #else |
297 | fread( magic, sizeof(magic), 1, f ); |
298 | if( strncmp(magic, ARMAG"!<arch>\n", SARMAG8) != 0 ) return( -1 ); |
299 | #endif |
300 | #else |
301 | fread( (char*)&word, sizeof(word), 1, f ); |
302 | if( word != ARMAG"!<arch>\n" ) return( -1 ); |
303 | #endif |
304 | |
305 | /* scan the library, calling `function' for each member |
306 | */ |
307 | while( 1 ) { |
308 | arhdroffset = ftell(f); |
309 | #if defined(_AIX) |
310 | if( fread((char*)&arhdr,sizeof(arhdr)-sizeof(arhdr._ar_name),1,f)!=1) |
311 | break; |
312 | nsize = atoi(arhdr.ar_namlen); |
313 | fseek(f, arhdroffset+(unsigned long)(((struct ar_hdr *)0)->_ar_name.ar_name), 0); |
314 | if( fread((char*)_ar.ar_name,nsize,1,f)!=1) |
315 | break; |
316 | _ar.ar_name[nsize]='\0'; |
317 | #else |
318 | if( fread((char*) &arhdr, sizeof(arhdr), 1, f) != 1 ) break; |
319 | strncpy(_ar.ar_name, arhdr.ar_name, nsize = sizeof(arhdr.ar_name)); |
320 | #endif |
321 | |
322 | for( p = &_ar.ar_name[nsize]; |
323 | --p >= _ar.ar_name && *p == ' ';); |
324 | |
325 | p[1] = '\0'; |
326 | if( *p == '/' ) *p = 0; /* SysV has trailing '/' */ |
327 | |
328 | /* check to see if this is an archive index using SsysV Index scheme. |
329 | * see ar(4) man page for more info */ |
330 | #if CHECKELF1 |
331 | if( _ar.ar_name[0] == '/' && _ar.ar_name[1] == '\0' ) { |
332 | arind = arhdroffset+sizeof(arhdr); |
333 | process = 0; |
334 | } |
335 | else |
336 | #endif |
337 | process = 1; |
338 | |
339 | #if !defined(_AIX) |
340 | #if ASCARCH1 |
341 | if( strncmp(arhdr.ar_fmag, ARFMAG"`\n", sizeof(arhdr.ar_fmag)) != 0 ) |
342 | return( -1 ); |
343 | _ar.ar_time = atol(arhdr.ar_date); |
344 | _ar.ar_size = atol(arhdr.ar_size); |
345 | #else |
346 | _ar.ar_time = arhdr.ar_date; |
347 | _ar.ar_size = arhdr.ar_size; |
348 | #endif |
349 | #if CHECKELF1 |
350 | /* check for names of the form /xxxx where xxxx is an offset into the |
351 | * name table pointed at by arind. */ |
352 | if(arind && _ar.ar_name[0] == '/') { |
353 | long offset = atol(_ar.ar_name+1); |
354 | long here = ftell(f); |
355 | int c; |
356 | |
357 | fseek(f, arind+offset, 0); |
358 | p = _ar.ar_name; |
359 | while((c=fgetc(f)) != EOF(-1)) { |
360 | *p++ = c; |
361 | if(c == '/') { |
362 | p[-1] = '\0'; |
363 | break; |
364 | } |
365 | } |
366 | |
367 | if (c==EOF(-1)) return(-1); /* 'c' should never be EOF */ |
368 | fseek(f, here, 0); |
369 | } |
370 | #endif |
371 | #else |
372 | #if ASCARCH1 |
373 | _ar.ar_time = atol(arhdr.ar_date); |
374 | _ar.ar_size = atol(arhdr.ar_nxtmem); |
375 | #else |
376 | _ar.ar_time = arhdr.ar_date; |
377 | _ar.ar_size = arhdr.ar_nxtmem; |
378 | #endif |
379 | #endif |
380 | |
381 | |
382 | #if DECODE_ALL_AR_FIELDS0 |
383 | #if ASCARCH1 |
384 | _ar.ar_mode = atoi(arhdr.ar_mode); |
385 | _ar.ar_uid = atoi(arhdr.ar_uid); |
386 | _ar.ar_gid = atoi(arhdr.ar_gid); |
387 | #else |
388 | _ar.ar_mode = arhdr.ar_mode; |
389 | _ar.ar_uid = arhdr.ar_uid; |
390 | _ar.ar_gid = arhdr.ar_gid; |
391 | #endif |
392 | #endif |
393 | if( process && (*function)(f, &_ar, arg) ) return( 1 ); |
394 | |
395 | #if defined(_AIX) |
396 | if( _ar.ar_size == 0L ) break; |
397 | fseek( f, (long) _ar.ar_size, 0 ); |
398 | #else |
399 | fseek( f, arhdroffset + sizeof(arhdr) + ((_ar.ar_size+1) & ~1L), 0 ); |
400 | #endif |
401 | } |
402 | |
403 | #if !defined(_AIX) |
404 | if( !feof(f) ) return( -1 ); |
405 | #endif |
406 | return 0; |
407 | } |
408 | |
409 | |
410 | |
411 | static int |
412 | ar_touch( f, now )/* |
413 | ==================== |
414 | touch module header timestamp. */ |
415 | FILE *f; |
416 | time_t now; |
417 | { |
418 | |
419 | fseek(f, arhdroffset + (unsigned long)(((struct ar_hdr *)0)->ar_date), 0); |
420 | |
421 | #if ASCARCH1 |
422 | fprintf(f, "%lu", now); |
423 | #else |
424 | fwrite((char *)now, sizeof(now), 1, f); |
425 | #endif |
426 | |
427 | return( ferror(f) ? 0 : 1 ); |
428 | } |
429 | |
430 | |
431 | #if LC1 |
432 | typedef struct mem { |
433 | time_t m_time; /* modify time of member*/ |
434 | struct mem *m_next; /* next member in lib */ |
435 | char m_valid; /* valid cache entry */ |
436 | char m_name[1]; /* lib member name */ |
437 | } MEM, *MEMPTR; |
438 | |
439 | typedef struct lib { |
440 | struct lib *lb_next; /* next library in list */ |
441 | struct mem *lb_members; /* list of lib members */ |
442 | char lb_valid; /* valid cache entry */ |
443 | char *lb_name; /* library name */ |
444 | } LIB, *LIBPTR; |
445 | |
446 | static LIBPTR _cache = NIL(LIB)((LIB*)((void*)0)); |
447 | static MEMPTR _find_member ANSI(( LIBPTR, char * ))( LIBPTR, char * ); |
448 | |
449 | static int |
450 | _check_cache( name, lib, pmtime, touch )/* |
451 | ========================================== |
452 | Check to see if we have cached member in lib, if so return time in pmtime |
453 | and return TRUE, otherwise return FALSE, if touch is TRUE then touch |
454 | the archive member instead. */ |
455 | char *name; |
456 | char *lib; |
457 | time_t *pmtime; |
458 | int touch; |
459 | { |
460 | register MEMPTR mp; |
461 | register LIBPTR lp; |
462 | |
463 | for( lp=_cache; lp != NIL(LIB)((LIB*)((void*)0)) && lp->lb_name != lib; lp=lp->lb_next ); |
464 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) return( FALSE0 ); |
465 | |
466 | mp = _find_member( lp, name ); |
467 | if( mp == NIL(MEM)((MEM*)((void*)0)) || !mp->m_valid ) return( FALSE0 ); |
468 | |
469 | if( touch == TRUE1 ) |
470 | { |
471 | mp->m_time = *pmtime; |
472 | mp->m_valid = 1; |
473 | } |
474 | else |
475 | *pmtime = mp->m_time; |
476 | |
477 | lp->lb_valid = 1; |
478 | lp->lb_members = mp; |
479 | |
480 | return( TRUE1 ); |
481 | } |
482 | |
483 | |
484 | |
485 | static int |
486 | _cache_member( name, lib, mtime )/* |
487 | =================================== |
488 | Cache name in lib along with it's time */ |
489 | char *name; |
490 | char *lib; |
491 | time_t mtime; |
492 | { |
493 | register MEMPTR mp; |
494 | register LIBPTR lp; |
495 | |
496 | for( lp=_cache; |
497 | lp != NIL(LIB)((LIB*)((void*)0)) && lp->lb_name != NIL(char)((char*)((void*)0)) && lp->lb_name != lib; |
498 | lp=lp->lb_next); |
499 | |
500 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) |
501 | { |
502 | lp = (LIBPTR) malloc(sizeof(LIB)); |
503 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) No_ram(); |
504 | |
505 | lp->lb_name = lib; |
506 | lp->lb_members = NIL(MEM)((MEM*)((void*)0)); |
507 | lp->lb_next = _cache; |
508 | lp->lb_valid = 0; |
509 | _cache = lp; |
510 | } |
511 | |
512 | /* On UNIX ar does not allow multiple copies of the same .o file to live |
513 | * in the same AR file. If this is not TRUE then use the commented out |
514 | * version to set the value of mp. */ |
515 | |
516 | /*mp = _find_member(lp, name);*/ |
517 | mp = NIL(MEM)((MEM*)((void*)0)); |
518 | |
519 | if( mp == NIL(MEM)((MEM*)((void*)0)) ) |
520 | { |
521 | mp = (MEMPTR) malloc(sizeof(char)*offsetof(MEM,m_name[strlen(name)+1])__builtin_offsetof(MEM, m_name[strlen(name)+1])); |
Result of 'malloc' is converted to a pointer of type 'struct mem', which is incompatible with sizeof operand type 'char' | |
522 | if( mp == NIL(MEM)((MEM*)((void*)0)) ) No_ram(); |
523 | |
524 | strcpy( mp->m_name, name ); |
525 | mp->m_time = mtime; |
526 | |
527 | if( lp->lb_members == NIL(MEM)((MEM*)((void*)0)) ) { |
528 | mp->m_next = mp; |
529 | lp->lb_members = mp; |
530 | } |
531 | else { |
532 | mp->m_next = lp->lb_members->m_next; |
533 | lp->lb_members->m_next = mp; |
534 | lp->lb_members = mp; |
535 | } |
536 | } |
537 | else |
538 | mp->m_time = mtime; |
539 | |
540 | mp->m_valid = 1; |
541 | |
542 | return( lp->lb_valid ); |
543 | } |
544 | |
545 | |
546 | static MEMPTR |
547 | _find_member( lp, name ) |
548 | LIBPTR lp; |
549 | char *name; |
550 | { |
551 | register MEMPTR mp = lp->lb_members; |
552 | |
553 | if( mp == NIL(MEM)((MEM*)((void*)0)) ) return(mp); |
554 | |
555 | do { |
556 | if( !strcmp(mp->m_name, name ) ) return( mp ); |
557 | mp = mp->m_next; |
558 | } |
559 | while( mp != lp->lb_members ); |
560 | |
561 | return( NIL(MEM)((MEM*)((void*)0)) ); |
562 | } |
563 | #endif |
564 | |
565 | |
566 | |
567 | PUBLIC void |
568 | void_lcache( lib, member )/* |
569 | ============================ |
570 | Void the library cache for lib. If member is NIL(char) then nuke all |
571 | of the members, if member is NOT NIL(char) then invalidate only that |
572 | member. */ |
573 | char *lib; |
574 | char *member; |
575 | { |
576 | #if LC1 |
577 | register LIBPTR lp; |
578 | register MEMPTR mp; |
579 | register MEMPTR tmp; |
580 | |
581 | for( lp=_cache; lp != NIL(LIB)((LIB*)((void*)0)) && lp->lb_name != lib; lp=lp->lb_next ); |
582 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) return; |
583 | |
584 | if( member == NIL(char)((char*)((void*)0)) ) { |
585 | mp = lp->lb_members; |
586 | do { |
587 | tmp = mp->m_next; |
588 | (void) free( mp ); |
589 | mp = tmp; |
590 | } while( mp != lp->lb_members ); |
591 | |
592 | lp->lb_valid = 0; |
593 | lp->lb_members = NIL(MEM)((MEM*)((void*)0)); |
594 | lp->lb_name = NIL(char)((char*)((void*)0)); |
595 | } |
596 | else { |
597 | mp=lp->lb_members; |
598 | do { |
599 | if( strcmp( member, mp->m_name) == 0 ) { |
600 | lp->lb_members = mp->m_next; |
601 | mp->m_valid = 0; |
602 | } |
603 | |
604 | mp=mp->m_next; |
605 | } while( mp != lp->lb_members ); |
606 | } |
607 | #endif |
608 | } |