1 | #include <unistd.h>
|
---|
2 | #include <stdlib.h>
|
---|
3 | #include <string.h>
|
---|
4 |
|
---|
5 | #include "machdefs.h"
|
---|
6 |
|
---|
7 | #ifndef IBMVM
|
---|
8 | #include <sys/types.h>
|
---|
9 | #include <unistd.h>
|
---|
10 | #endif
|
---|
11 |
|
---|
12 | #include "filecache.h"
|
---|
13 |
|
---|
14 | #ifdef RFIO
|
---|
15 | #include <shift.h>
|
---|
16 | #endif
|
---|
17 |
|
---|
18 | #ifdef __mac__
|
---|
19 | #include <stat.h>
|
---|
20 | #endif
|
---|
21 |
|
---|
22 | /*
|
---|
23 | ++
|
---|
24 | Module Buffered I/O (C)
|
---|
25 | Lib fsv
|
---|
26 | include filecache.h
|
---|
27 |
|
---|
28 | Les fonctions décrites ci-dessous permettent de lire et d'écrire
|
---|
29 | des fichiers avec une gestion de mémoire tampon, afin d'optimiser
|
---|
30 | le débit d'entrée-sortie en cas d'utilisation lourde du positionnement
|
---|
31 | dans le fichier (seek()). L'interface est similaire à celle des
|
---|
32 | fonctions d'entrée sortie standard C ("fopen(...)", "fread(...)", ...).
|
---|
33 | Au moment de l'ouverture du fichier (par zfopen()),
|
---|
34 | une liste chainée de zones mémoire, (des pages)
|
---|
35 | est créé. Ces pages sont destinées a contenir une
|
---|
36 | image mémoire des zones accédées du fichier au moment
|
---|
37 | des opérations de lecture et d'écriture, réduisant
|
---|
38 | ainsi le nombre des accés effectifs au fichier disque.
|
---|
39 | La taille et le nombre de page allouées sont contrôlés par
|
---|
40 | l'utilisateur.
|
---|
41 | --
|
---|
42 | */
|
---|
43 |
|
---|
44 | static int zf_prtlev = 0;
|
---|
45 | /* Nouvelle-Fonction */
|
---|
46 | void zfSetPrtLevel(int lev)
|
---|
47 | {
|
---|
48 | zf_prtlev = lev;
|
---|
49 | }
|
---|
50 |
|
---|
51 | int pgread(FILECACHE *fcp, long fr, long n, char *buff);
|
---|
52 | int pgwrite(FILECACHE *fcp, long fr, long n, char *buff);
|
---|
53 |
|
---|
54 | /*
|
---|
55 | ++
|
---|
56 | FILECACHE *zfopen(char *flnm, char *mode, int npg, int pgsiz)
|
---|
57 | Ouverture du fichier "flnm", en mode lecture seule ou
|
---|
58 | lecture-écriture. "npg" pages de tailles "pgsiz" sont
|
---|
59 | allouées pour la mémoire tampon. Les caractères "rw+"
|
---|
60 | peuvent être spécifié pour "mode". Si "npg <= 0",
|
---|
61 | les fonctions standard "fseek()", "fread()" et "fwrite()"
|
---|
62 | sont utilisées.
|
---|
63 |
|
---|
64 | void zfclose( FILECACHE *fcp )
|
---|
65 | Fermeture du fichier. Il est impératif d'appeler zfclose()
|
---|
66 | si le fichier a été ouvert en écriture.
|
---|
67 |
|
---|
68 | void zfSetPrtLevel(int lev)
|
---|
69 | Modification du niveau d'impression pour le debug.
|
---|
70 | si "lev > 2" des statistiques concernant l'utilisation
|
---|
71 | de la mémoire tampon sont imprimées à la fermeture du fichier.
|
---|
72 | --
|
---|
73 | */
|
---|
74 |
|
---|
75 |
|
---|
76 |
|
---|
77 | /* Nouvelle-Fonction */
|
---|
78 | FILECACHE *zfopen(char *flnm, char *mode, int npg, int pgsiz)
|
---|
79 |
|
---|
80 | {
|
---|
81 | FILE *fip;
|
---|
82 | FILECACHE *fcp;
|
---|
83 | int i,j;
|
---|
84 | DSKPAGE *first, *cur, *prev;
|
---|
85 |
|
---|
86 |
|
---|
87 | if ( (fip=fopen(flnm,mode)) == NULL )
|
---|
88 | {
|
---|
89 | puts("zfopen_Erreur - Erreur fopen !");
|
---|
90 | return(NULL);
|
---|
91 | }
|
---|
92 |
|
---|
93 |
|
---|
94 | if ( (fcp=malloc(sizeof(FILECACHE))) == NULL )
|
---|
95 | {
|
---|
96 | fclose(fip);
|
---|
97 | puts("zfopen_Erreur - Erreur malloc(fcp) !");
|
---|
98 | return(NULL);
|
---|
99 | }
|
---|
100 |
|
---|
101 | if ( npg < 0 ) { npg = DEF_NPAGE ; pgsiz = DEF_PGSIZE ; }
|
---|
102 |
|
---|
103 | fcp->fip = fip;
|
---|
104 |
|
---|
105 | #if defined(IBMVM)
|
---|
106 | fcp->fidesc = -1;
|
---|
107 | #elif defined(HPUX)
|
---|
108 | fcp->fidesc = (int)fip->__fileH*256+(int)fip->__fileL;
|
---|
109 | #elif defined(__MWERKS__)
|
---|
110 | //fcp->fidesc = (int)fip->_Handle; // ANSI ancien
|
---|
111 | fcp->fidesc = (int)fip->handle; // MSL
|
---|
112 | #elif defined(Linux)
|
---|
113 | fcp->fidesc = (int)fip->_fileno;
|
---|
114 | #else
|
---|
115 | fcp->fidesc = (int)fip->_file;
|
---|
116 | #endif
|
---|
117 |
|
---|
118 | fcp->fpos = 0;
|
---|
119 | fcp->nread = fcp->nwrite = 0;
|
---|
120 | fcp->totrd = fcp->totwr =0;
|
---|
121 | fseek(fip,0,SEEK_END);
|
---|
122 | fcp->fsz = ftell(fip);
|
---|
123 | fseek(fip,0,SEEK_SET);
|
---|
124 |
|
---|
125 | fcp->rwfg = 0;
|
---|
126 | for(i=0; i<strlen(mode); i++)
|
---|
127 | if ( ( *(mode+i) == 'w' ) || ( *(mode+i) == '+' ) ) fcp->rwfg = 1;
|
---|
128 |
|
---|
129 | fcp->memode = 0;
|
---|
130 | fcp->first = fcp->last = NULL;
|
---|
131 | fcp->pages = NULL;
|
---|
132 | fcp->npage = fcp->pgsize = 0;
|
---|
133 |
|
---|
134 | if (npg <= 0) return(fcp); /* Si pas d'option caching */
|
---|
135 |
|
---|
136 | if (pgsiz < MIN_PGSIZE) pgsiz = MIN_PGSIZE;
|
---|
137 | if (npg < MIN_NPAGE) npg = MIN_NPAGE;
|
---|
138 |
|
---|
139 | fcp->memode = 1;
|
---|
140 | fcp->npage = npg;
|
---|
141 | fcp->pgsize = pgsiz;
|
---|
142 |
|
---|
143 | if ( ( first = (DSKPAGE *)malloc(npg*sizeof(DSKPAGE)) ) == NULL )
|
---|
144 | {
|
---|
145 | fclose(fip); free(fcp);
|
---|
146 | puts("zfopen_Erreur: Pb malloc(DSKPAGE) !");
|
---|
147 | return(NULL);
|
---|
148 | }
|
---|
149 |
|
---|
150 | prev = NULL;
|
---|
151 | cur = first-1;
|
---|
152 | for(i=0; i<npg; i++)
|
---|
153 | {
|
---|
154 | cur++;
|
---|
155 | cur->wrfg = 0;
|
---|
156 | cur->pgno = -1;
|
---|
157 | if ( (cur->page=malloc(pgsiz)) == NULL)
|
---|
158 | {
|
---|
159 | for(j=0; j<i; j++)
|
---|
160 | free((first + j)->page);
|
---|
161 | free(first); free(fcp);
|
---|
162 | fclose(fip);
|
---|
163 | return(NULL);
|
---|
164 | }
|
---|
165 | memset((void *)cur->page, (int)('\0'), (size_t)pgsiz);
|
---|
166 | cur->next = cur+1;
|
---|
167 | cur->prev = prev;
|
---|
168 | prev = cur;
|
---|
169 | }
|
---|
170 |
|
---|
171 | cur->next = NULL;
|
---|
172 | fcp->last = cur;
|
---|
173 | fcp->first = first;
|
---|
174 | fcp->pages = first;
|
---|
175 |
|
---|
176 | if (zf_prtlev > 5)
|
---|
177 | {
|
---|
178 | printf("zfopen_Debug: NPage= %d , PgSize= %d \n", npg, pgsiz);
|
---|
179 | cur = fcp->first;
|
---|
180 | for (i=0; i<npg; i++)
|
---|
181 | {
|
---|
182 | printf("Pg[%d] *DskPg = %lx *page= %lx *Next= %lx \n",
|
---|
183 | (i+1), (unsigned long)cur, (unsigned long)cur->page, (unsigned long)cur->next);
|
---|
184 | cur = cur->next;
|
---|
185 | }
|
---|
186 | }
|
---|
187 |
|
---|
188 | return(fcp);
|
---|
189 | }
|
---|
190 |
|
---|
191 |
|
---|
192 |
|
---|
193 | /* Nouvelle-Fonction */
|
---|
194 | void zfclose( FILECACHE *fcp )
|
---|
195 | {
|
---|
196 | float effr,effw;
|
---|
197 | DSKPAGE *cur;
|
---|
198 | int_4 pgsiz;
|
---|
199 | long int fp;
|
---|
200 |
|
---|
201 | if (fcp == NULL) return;
|
---|
202 |
|
---|
203 |
|
---|
204 | pgsiz = fcp->pgsize;
|
---|
205 | cur = fcp->first;
|
---|
206 | while (cur != NULL)
|
---|
207 | {
|
---|
208 | if ( cur->wrfg && fcp->rwfg )
|
---|
209 | {
|
---|
210 | fp = cur->pgno*fcp->pgsize;
|
---|
211 | #ifdef IBMVM
|
---|
212 | fseek(fcp->fip, fp, SEEK_SET);
|
---|
213 | fwrite(cur->page, 1, pgsiz, fcp->fip);
|
---|
214 | #else
|
---|
215 | lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
|
---|
216 | write(fcp->fidesc, cur->page, pgsiz);
|
---|
217 | #endif
|
---|
218 | fcp->nwrite ++;
|
---|
219 | }
|
---|
220 | free(cur->page);
|
---|
221 | cur = cur->next;
|
---|
222 | }
|
---|
223 |
|
---|
224 | if (zf_prtlev > 2)
|
---|
225 | {
|
---|
226 | if (fcp->nread > 0)
|
---|
227 | effr = (float)(fcp->totrd)/(float)(fcp->nread*pgsiz);
|
---|
228 | else effr = 1.0;
|
---|
229 | if (fcp->nwrite > 0)
|
---|
230 | effw = (float)(fcp->totwr)/(float)(fcp->nwrite*pgsiz);
|
---|
231 | else effw = 1.0;
|
---|
232 | puts(" ================= Statistiques Memoire Cache =================");
|
---|
233 | printf(" NPage= %d PgSize= %d \n", fcp->npage, fcp->pgsize);
|
---|
234 | printf(" PgRead= %d TotRd= %ld TotRd/PgRead= %g \n",
|
---|
235 | fcp->nread, fcp->totrd, effr);
|
---|
236 | printf(" PgWrite= %d TotWr= %ld TotWr/PgWrite= %g \n",
|
---|
237 | fcp->nwrite, fcp->totwr, effw);
|
---|
238 | puts(" ==============================================================");
|
---|
239 | }
|
---|
240 |
|
---|
241 | /* fcp->first a tourne et ne pointe plus vers la 1ere structure des DSKPAGES* */
|
---|
242 | free(fcp->pages);
|
---|
243 | fclose(fcp->fip);
|
---|
244 | free(fcp);
|
---|
245 |
|
---|
246 | return;
|
---|
247 |
|
---|
248 | }
|
---|
249 |
|
---|
250 | /*
|
---|
251 | ++
|
---|
252 | int zfseek( FILECACHE *fcp, long int offset, int fg)
|
---|
253 | Positionnement dans le fichier. "fg" peut valoir
|
---|
254 | "SEEK_SET", "SEEK_CUR", "SEEK_END", pour
|
---|
255 | un positionnement avec décalage "offset" à partir
|
---|
256 | du début de fichier, de la position courante, ou
|
---|
257 | de la fin du fichier.
|
---|
258 |
|
---|
259 | size_t zfread( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
|
---|
260 | Lecture à partir de la position courante.
|
---|
261 |
|
---|
262 | size_t zfwrite( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
|
---|
263 | Ecriture à partir de la position courante.
|
---|
264 | --
|
---|
265 | */
|
---|
266 |
|
---|
267 | /* Nouvelle-Fonction */
|
---|
268 | int zfseek( FILECACHE *fcp, long int offset, int fg)
|
---|
269 | {
|
---|
270 | long int newpos;
|
---|
271 |
|
---|
272 | if (fcp == NULL) return(-2);
|
---|
273 | if ( !fcp->memode ) return ( fseek(fcp->fip, offset, fg) );
|
---|
274 |
|
---|
275 | newpos = offset;
|
---|
276 | if (fg == SEEK_SET) newpos = offset;
|
---|
277 | if (fg == SEEK_CUR) newpos = fcp->fpos + offset;
|
---|
278 | if (fg == SEEK_END) newpos = fcp->fsz - offset;
|
---|
279 |
|
---|
280 | if ( newpos < 0 ) return(-1);
|
---|
281 | if ( !fcp->rwfg && (newpos >= fcp->fsz) ) return(-1);
|
---|
282 | fcp->fpos = newpos;
|
---|
283 | return(0);
|
---|
284 |
|
---|
285 | }
|
---|
286 |
|
---|
287 |
|
---|
288 |
|
---|
289 | /* Nouvelle-Fonction */
|
---|
290 | size_t zfread( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
|
---|
291 | {
|
---|
292 | long int m,n;
|
---|
293 | long int fr,nr;
|
---|
294 |
|
---|
295 |
|
---|
296 | if (fcp == NULL) return(0);
|
---|
297 | if ( !fcp->memode ) return ( fread(buff, size, nitems, fcp->fip) );
|
---|
298 |
|
---|
299 | #ifdef DEBUG_FCACHE
|
---|
300 | printf(" Debug_zfread pos,size,nitem= %d %d %d\n",fcp->fpos,size,nitems);
|
---|
301 | #endif
|
---|
302 |
|
---|
303 | m = 0; n = size*nitems;
|
---|
304 | if ( fcp->fpos+n > fcp->fsz ) n = fcp->fsz-fcp->fpos;
|
---|
305 | if ( n <= 0) return(0);
|
---|
306 | fr = fcp->fpos;
|
---|
307 |
|
---|
308 | fcp->totrd += n; nr = n;
|
---|
309 |
|
---|
310 | while ((m < n) && (nr > 0))
|
---|
311 | {
|
---|
312 | #ifdef DEBUG_FCACHE
|
---|
313 | printf(" Debug_zfread_2 fr,n,m= %d %d %d\n",fr,n,m);
|
---|
314 | #endif
|
---|
315 | nr = pgread(fcp,fr,(n-m), ((char *)buff)+m);
|
---|
316 | m += nr; fr += nr;
|
---|
317 | }
|
---|
318 |
|
---|
319 | fcp->fpos += m;
|
---|
320 |
|
---|
321 | return(m);
|
---|
322 | }
|
---|
323 |
|
---|
324 |
|
---|
325 | /* Nouvelle-Fonction */
|
---|
326 | int pgread(FILECACHE *fcp, long fr, long n, char *buff)
|
---|
327 | {
|
---|
328 | long int pgnum, pg;
|
---|
329 | long int off, nr;
|
---|
330 |
|
---|
331 | long int fp;
|
---|
332 | DSKPAGE *cur;
|
---|
333 |
|
---|
334 | pgnum = fr / fcp->pgsize;
|
---|
335 |
|
---|
336 | /* On regarde si la page est en memoire */
|
---|
337 |
|
---|
338 | pg = -1;
|
---|
339 | cur = fcp->first;
|
---|
340 | while (cur != NULL)
|
---|
341 | {
|
---|
342 | if (cur->pgno < 0) break;
|
---|
343 | if (cur->pgno == pgnum) { pg = pgnum; break; }
|
---|
344 | cur = cur->next;
|
---|
345 | }
|
---|
346 |
|
---|
347 |
|
---|
348 | /* On la lit si elle n'y est pas */
|
---|
349 | if ( pg < 0)
|
---|
350 | {
|
---|
351 | cur = fcp->last;
|
---|
352 | /* On reecrit la derniere page si necessaire */
|
---|
353 | if ( cur->wrfg && fcp->rwfg )
|
---|
354 | {
|
---|
355 | fp = cur->pgno*fcp->pgsize;
|
---|
356 | #ifdef IBMVM
|
---|
357 | fseek(fcp->fip, fp, SEEK_SET);
|
---|
358 | fwrite(cur->page, 1, fcp->pgsize, fcp->fip);
|
---|
359 | #else
|
---|
360 | lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
|
---|
361 | write(fcp->fidesc, cur->page, fcp->pgsize);
|
---|
362 | #endif
|
---|
363 | fcp->nwrite ++;
|
---|
364 | }
|
---|
365 |
|
---|
366 | fp = pgnum*fcp->pgsize;
|
---|
367 | #ifdef IBMVM
|
---|
368 | fseek(fcp->fip, fp, SEEK_SET);
|
---|
369 | fread(cur->page, 1, fcp->pgsize, fcp->fip);
|
---|
370 | #else
|
---|
371 | lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
|
---|
372 | read(fcp->fidesc, cur->page, fcp->pgsize);
|
---|
373 | #endif
|
---|
374 | cur->pgno = pgnum;
|
---|
375 | cur->wrfg = 0;
|
---|
376 | fcp->nread ++;
|
---|
377 | }
|
---|
378 |
|
---|
379 | /* On reordonne les pages */
|
---|
380 | if ( cur != fcp->first )
|
---|
381 | {
|
---|
382 | if ( cur == fcp->last )
|
---|
383 | { fcp->last = cur->prev; (fcp->last)->next = NULL; }
|
---|
384 | else
|
---|
385 | { (cur->prev)->next = cur->next; (cur->next)->prev = cur->prev; }
|
---|
386 |
|
---|
387 | (fcp->first)->prev = cur;
|
---|
388 | cur->next = fcp->first;
|
---|
389 | cur->prev = NULL;
|
---|
390 | fcp->first = cur;
|
---|
391 | }
|
---|
392 |
|
---|
393 | /* Copie ds buffer utilisateur */
|
---|
394 | off = fr - pgnum*fcp->pgsize;
|
---|
395 | if ( (nr=fcp->pgsize-off) > n ) nr = n;
|
---|
396 | memcpy(buff, (cur->page)+off, nr);
|
---|
397 |
|
---|
398 | return(nr);
|
---|
399 | }
|
---|
400 |
|
---|
401 |
|
---|
402 |
|
---|
403 | /* Nouvelle-Fonction */
|
---|
404 | size_t zfwrite( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
|
---|
405 | {
|
---|
406 | long int m,n;
|
---|
407 | long int fr,nw;
|
---|
408 |
|
---|
409 |
|
---|
410 | if (fcp == NULL) return(-1);
|
---|
411 | if ( !fcp->rwfg ) return(-2);
|
---|
412 | if ( !fcp->memode ) return ( fwrite(buff, size, nitems, fcp->fip) );
|
---|
413 |
|
---|
414 |
|
---|
415 | m = 0; n = size*nitems;
|
---|
416 | if ( n <= 0) return(0);
|
---|
417 |
|
---|
418 | fr = fcp->fpos;
|
---|
419 | fcp->totwr += n; nw = n;
|
---|
420 |
|
---|
421 | while ((m < n) && (nw > 0))
|
---|
422 | {
|
---|
423 | nw = pgwrite(fcp,fr,(n-m), ((char*)buff)+m);
|
---|
424 | m += nw; fr += nw; }
|
---|
425 |
|
---|
426 | fcp->fpos += m;
|
---|
427 | if (fcp->fpos >= fcp->fsz) fcp->fsz = fcp->fpos+1;
|
---|
428 |
|
---|
429 | return(m);
|
---|
430 | }
|
---|
431 |
|
---|
432 |
|
---|
433 | /* Nouvelle-Fonction */
|
---|
434 |
|
---|
435 | int pgwrite(FILECACHE *fcp, long fr, long n, char *buff)
|
---|
436 |
|
---|
437 | {
|
---|
438 | long int pgnum, pg;
|
---|
439 | long int off, nw;
|
---|
440 |
|
---|
441 | long int fp;
|
---|
442 | DSKPAGE *cur;
|
---|
443 |
|
---|
444 | pgnum = fr / fcp->pgsize;
|
---|
445 |
|
---|
446 | /* On regarde si la page est en memoire */
|
---|
447 |
|
---|
448 | pg = -1;
|
---|
449 | cur = fcp->first;
|
---|
450 | while (cur != NULL)
|
---|
451 | {
|
---|
452 | if (cur->pgno < 0) break;
|
---|
453 | if ( cur->pgno == pgnum) { pg = pgnum; break; }
|
---|
454 | cur = cur->next;
|
---|
455 | }
|
---|
456 |
|
---|
457 |
|
---|
458 | /* On la lit si elle n'y est pas */
|
---|
459 | if ( pg < 0)
|
---|
460 | {
|
---|
461 |
|
---|
462 | cur = fcp->last;
|
---|
463 | /* On reecrit la derniere page si necessaire */
|
---|
464 | if ( cur->wrfg && fcp->rwfg)
|
---|
465 | {
|
---|
466 | fp = cur->pgno*fcp->pgsize;
|
---|
467 | #ifdef IBMVM
|
---|
468 | fseek(fcp->fip, fp, SEEK_SET);
|
---|
469 | fwrite(cur->page, 1, fcp->pgsize, fcp->fip);
|
---|
470 | #else
|
---|
471 | lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
|
---|
472 | write(fcp->fidesc, cur->page, fcp->pgsize);
|
---|
473 | #endif
|
---|
474 | fcp->nwrite ++;
|
---|
475 | }
|
---|
476 |
|
---|
477 | fp = pgnum*fcp->pgsize;
|
---|
478 | if ( (fp + fcp->pgsize) >= fcp->fsz ) /* remise a zero de la page */
|
---|
479 | memset((void *)cur->page, (int)('\0'), (size_t)fcp->pgsize);
|
---|
480 | #ifdef IBMVM
|
---|
481 | fseek(fcp->fip, fp, SEEK_SET);
|
---|
482 | fread(cur->page, 1, fcp->pgsize, fcp->fip);
|
---|
483 | #else
|
---|
484 | lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
|
---|
485 | read(fcp->fidesc, cur->page, fcp->pgsize);
|
---|
486 | #endif
|
---|
487 | cur->pgno = pgnum;
|
---|
488 | cur->wrfg = 0;
|
---|
489 | fcp->nread ++;
|
---|
490 | }
|
---|
491 |
|
---|
492 | /* On reordonne les pages */
|
---|
493 | if ( cur != fcp->first )
|
---|
494 | {
|
---|
495 | if ( cur == fcp->last )
|
---|
496 | { fcp->last = cur->prev; (fcp->last)->next = NULL; }
|
---|
497 | else
|
---|
498 | { (cur->prev)->next = cur->next; (cur->next)->prev = cur->prev; }
|
---|
499 |
|
---|
500 | (fcp->first)->prev = cur;
|
---|
501 | cur->next = fcp->first;
|
---|
502 | cur->prev = NULL;
|
---|
503 | fcp->first = cur;
|
---|
504 | }
|
---|
505 |
|
---|
506 | /* Copie ds buffer utilisateur */
|
---|
507 | off = fr - pgnum*fcp->pgsize;
|
---|
508 | if ( (nw=fcp->pgsize-off) > n ) nw = n;
|
---|
509 | memcpy((cur->page)+off, buff, nw);
|
---|
510 | cur->wrfg = 1;
|
---|
511 |
|
---|
512 | return(nw);
|
---|
513 | }
|
---|