Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: findinfile.c,v 1.4 2005/01/11 22:48:05 andreradke Exp $ */
3
4 /******************************************************************************
5
6 UserLand Frontier(tm) -- High performance Web content management,
7 object database, system-level and Internet scripting environment,
8 including source code editing and debugging.
9
10 Copyright (C) 1992-2004 UserLand Software, Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 ******************************************************************************/
27
28 #include "frontier.h"
29 #include "standard.h"
30
31 #include "error.h"
32 #include "memory.h"
33 #include "strings.h"
34 #include "file.h"
35 #include "lang.h"
36 #include "langinternal.h"
37
38
39
40 #define filebuffersize 1024
41
42
43 typedef struct tyopenfile {
44
45 tyfilespec fs; /*the file specifier*/
46
47 hdlfilenum fnum; /*the file refnum*/
48
49 Handle hbuffer; /*holds the file data*/
50
51 long ixbuffer; /*points at the next character in the file*/
52
53 long ctbufferbytes; /*number of valid chars in buffer*/
54
55 long ctbytesleft; /*number of valid characters left unread*/
56
57 long fpos; /*current file position*/
58
59 struct tyopenfile **nextfile;
60
61 long refcon;
62 } tyopenfile, *ptropenfile, **hdlopenfile;
63
64
65 hdlopenfile hfirstfile = nil; /*header of file list*/
66
67
68
69 static boolean loadbufferfromfile (hdlfilenum fnum, Handle hbuffer, long *ctbytes) {
70
71 boolean fl;
72 long ctread;
73
74 ctread = gethandlesize (hbuffer);
75
76 lockhandle (hbuffer);
77
78 fl = filereaddata (fnum, ctread, ctbytes, *hbuffer);
79
80 unlockhandle (hbuffer);
81
82 return (fl);
83 } /*loadbufferfromfile*/
84
85
86 static boolean backupfilepos (hdlfilenum fnum, long ctbytes) {
87
88 long origfpos, newfpos;
89 boolean fl;
90
91 filegetposition (fnum, &origfpos);
92
93 if (origfpos >= ctbytes)
94 newfpos = origfpos - ctbytes;
95 else
96 newfpos = 0L;
97
98 fl = filesetposition (fnum, newfpos);
99
100 /* filegetposition (fnum, &newfpos); */
101
102 return (fl);
103 } /*backupfilepos*/
104
105
106 static void lowercasehandle (Handle h) {
107
108 lowertext ((ptrbyte) *h, gethandlesize (h));
109 } /*lowercasehandle*/
110
111
112 static boolean findopenfile (const tyfilespec *fs, hdlopenfile *hfile, hdlopenfile *hprev) {
113
114 register hdlopenfile x = hfirstfile;
115
116 *hfile = nil;
117
118 *hprev = nil;
119
120 while (true) {
121
122 if (x == nil) /*fell off list*/
123 return (false);
124
125 if (equalfilespecs (fs, &(**x).fs)) {
126
127 *hfile = x;
128
129 return (true);
130 }
131
132 *hprev = x;
133
134 x = (**x).nextfile;
135 } /*while*/
136 } /*findopenfile*/
137
138
139 static void fifopenfileerror (const tyfilespec *fs) {
140
141 /*
142 5.0.1 dmb: new, additional error reporting
143 */
144
145 bigstring bsfile;
146
147 getfsfile (fs, bsfile);
148
149 lang2paramerror (filenotopenederror, bsfunctionname, bsfile);
150 } /*fifopenfileerror*/
151
152
153 #if 0
154 static OSErr openforkperm (const tyfilespec *fs, boolean flresource, short perm, hdlfilenum *fnum) {
155
156 OSErr errcode;
157
158 if (flresource)
159 errcode = FSpOpenRF (fs, perm, fnum);
160 else
161 errcode = FSpOpenDF (fs, perm, fnum);
162
163 return (errcode);
164 } /*openforkperm*/
165 #endif
166
167 static boolean fileopener (const tyfilespec *fs, hdlopenfile *hfile, hdlfilenum *fnum) {
168
169 /*
170 2/13/92 dmb: changed fldontclose logic to something that actually works;
171 we no longer ignore opWrErr errors. instead, we try to open read/write,
172 but settle for read only.
173
174 1/25/93 dmb: instead of using fldontclose boolean, we return the hdlopenfile
175 if found. the new filecloser uses this to restore things properly
176
177 2.1b6 dmb: generate an oserror when a file can't be opened
178 */
179
180 boolean fl;
181 hdlopenfile hprev;
182
183 if (findopenfile (fs, hfile, &hprev)) { /*file was already opened by us*/
184
185 register hdlopenfile hf = *hfile;
186 long position;
187
188 filegetposition ((**hf).fnum, &position);
189
190 (**hf).fpos = position;
191
192 *fnum = (**hf).fnum;
193
194 return (true);
195 }
196
197 *hfile = nil;
198
199 disablelangerror ();
200
201 fl = openfile (fs, fnum, false);
202
203 enablelangerror();
204
205 if (!fl)
206 fl = openfile (fs, fnum, true);
207
208 #ifdef NEWFILESPECTYPE
209 setoserrorparam ((ptrstring) (*fs).fullSpecifier);
210 #else
211 setoserrorparam ((ptrstring) (*fs).name);
212 #endif
213
214 return (fl);
215 } /*fileopener*/
216
217
218 static boolean fileloadbuffer (hdlopenfile hf) {
219
220 /*
221 5.1.4 dmb: broke this out of fifread
222 */
223
224 long ctbytes;
225
226 if (!loadbufferfromfile ((**hf).fnum, (**hf).hbuffer, &ctbytes)) { /*non-EOF error*/
227
228 (**hf).ctbytesleft = 0;
229
230 return (false);
231 }
232
233 (**hf).ctbufferbytes = ctbytes;
234
235 (**hf).ixbuffer = 0;
236
237 return (true);
238 } /*fileloadbuffer*/
239
240
241 static void filecloser (hdlopenfile hfile, hdlfilenum fnum) {
242
243 if (fnum != 0) {
244
245 if (hfile == nil) /*file wasn't already open*/
246 closefile (fnum);
247
248 else /*need to restor file position*/
249 filesetposition (fnum, (**hfile).fpos);
250 }
251 } /*filecloser*/
252
253
254 boolean fiffindinfile (const tyfilespec *fs, bigstring pattern, long *index) {
255
256 /*
257 search for the indicated pattern in the file. return the index that the
258 match was found at, -1 if not found.
259
260 returns false if there was an error.
261
262 2/2/93 dmb: fixed off-by-one error; last character in string wasn't checked.
263
264 2.1b6 dmb: fixed infinite looping when partial matches were found
265 */
266
267 hdlfilenum fnum = 0;
268 short lenpattern;
269 Handle hbuffer = nil;
270 long ctbytes;
271 long fpos = 0;
272 long oldctbytes;
273 boolean flreturned = false;
274 hdlopenfile hfile = nil;
275
276 *index = -1; /*indicate an error*/
277
278 lenpattern = stringlength (pattern);
279
280 if (lenpattern == 0) { /*no error, but it wasn't found*/
281
282 flreturned = true;
283
284 goto exit;
285 }
286
287 alllower (pattern); /*search is unicase*/
288
289 if (!fileopener (fs, &hfile, &fnum))
290 goto exit;
291
292 if (!largefilebuffer (&hbuffer)) /*couldn't allocate minimum buffer*/
293 goto exit;
294
295 if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
296 goto exit;
297
298 if (ctbytes == 0) { /*it's an empty file*/
299
300 flreturned = true;
301
302 goto exit;
303 }
304
305 oldctbytes = ctbytes;
306
307 while (true) {
308
309 register char *pbuffer = *hbuffer;
310 register char *pbufferend = pbuffer + ctbytes;
311 register char chfirst = pattern [1];
312
313 //lockhandle (hbuffer);
314
315 lowercasehandle (hbuffer); /*search is unicase*/
316
317 while (pbuffer < pbufferend) {
318
319 if (*pbuffer++ == chfirst) { /*matched first character*/
320
321 register short ixpattern;
322 register char *p = pbuffer;
323
324 for (ixpattern = 2; ixpattern <= lenpattern; ixpattern++) {
325
326 if (p >= pbufferend) { /*ran out of chars in the buffer*/
327
328 --ixpattern; /*make it the number of chars already matched*/
329
330 backupfilepos (fnum, (long) ixpattern);
331
332 fpos -= ixpattern;
333
334 goto reloadbuffer;
335 }
336
337 if (*p++ != pattern [ixpattern])
338 goto fastloop;
339
340 } /*for*/
341
342 *index = fpos + (pbuffer - *hbuffer - 1);
343
344 flreturned = true;
345
346 goto exit;
347 } /*first character matched*/
348
349 fastloop:
350 ;
351 } /*for*/
352
353 reloadbuffer:
354
355 //unlockhandle (hbuffer);
356
357 if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
358 goto exit;
359
360 if (ctbytes < lenpattern) { /*not enough chars to look at*/
361
362 flreturned = false;
363
364 goto exit;
365 }
366
367 fpos += oldctbytes; /*for computing returned value*/
368
369 oldctbytes = ctbytes;
370 } /*while*/
371
372 exit:
373
374 disposehandle (hbuffer);
375
376 filecloser (hfile, fnum);
377
378 return (flreturned);
379 } /*fiffindinfile*/
380
381
382 boolean fifcomparefiles (const tyfilespec *fs1, const tyfilespec *fs2) {
383
384 /*
385 compare the two files byte-by-byte and return true if they are exactly
386 equal. only compares the data forks of the files.
387 */
388
389 hdlfilenum fnum1 = 0, fnum2 = 0;
390 Handle hbuffer1 = nil, hbuffer2 = nil;
391 long ctbytes1, ctbytes2;
392 boolean flreturned = false;
393 hdlopenfile hfile1, hfile2;
394
395 if (!fileopener (fs1, &hfile1, &fnum1))
396 goto exit;
397
398 if (!fileopener (fs2, &hfile2, &fnum2))
399 goto exit;
400
401 if (!newclearhandle ((long) filebuffersize, &hbuffer1))
402 goto exit;
403
404 if (!newclearhandle ((long) filebuffersize, &hbuffer2))
405 goto exit;
406
407 while (true) {
408
409 register long ix;
410 register char *p1, *p2;
411
412 if (!loadbufferfromfile (fnum1, hbuffer1, &ctbytes1))
413 goto exit;
414
415 if (!loadbufferfromfile (fnum2, hbuffer2, &ctbytes2))
416 goto exit;
417
418 if (ctbytes1 == 0) { /**no more chars to look at*/
419
420 flreturned = ctbytes2 == 0; /*true if it's also empty*/
421
422 goto exit;
423 }
424
425 if (ctbytes1 != ctbytes2) {
426
427 flreturned = false;
428
429 goto exit;
430 }
431
432 //lockhandle (hbuffer1);
433
434 p1 = *hbuffer1; /*copy into register*/
435
436 //lockhandle (hbuffer2);
437
438 p2 = *hbuffer2; /*copy into register*/
439
440 for (ix = 0; ix < ctbytes1; ix++) {
441
442 if (*p1++ != *p2++) {
443
444 flreturned = false;
445
446 goto exit;
447 }
448 } /*for*/
449
450 //unlockhandle (hbuffer1);
451
452 //unlockhandle (hbuffer2);
453 } /*while*/
454
455 exit:
456
457 disposehandle (hbuffer1);
458
459 disposehandle (hbuffer2);
460
461 filecloser (hfile1, fnum1);
462
463 filecloser (hfile2, fnum2);
464
465 return (flreturned);
466 } /*fifcomparefiles*/
467
468
469 boolean fifcharcounter (const tyfilespec *fs, char chlookfor, long *count) {
470
471 /*
472 searches the indicated file for the character. count returns with the number
473 of matches. set chlookfor to (char) 13 to get the number of carriage returns
474 or number of lines in the file.
475 */
476
477 register long ctmatches = 0;
478 hdlfilenum fnum = 0;
479 Handle hbuffer = nil;
480 long ctbytes;
481 boolean flreturned = false;
482 hdlopenfile hfile = nil;
483
484 if (!fileopener (fs, &hfile, &fnum))
485 goto exit;
486
487 if (!largefilebuffer (&hbuffer)) /*couldn't allocate minimum buffer*/
488 goto exit;
489
490 if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
491 goto exit;
492
493 if (ctbytes == 0) { /*it's an empty file*/
494
495 flreturned = true;
496
497 goto exit;
498 }
499
500 while (true) {
501
502 register long ct = ctbytes;
503 register long ix;
504 register char *pbuffer;
505 register char ch = chlookfor;
506
507 //lockhandle (hbuffer);
508
509 pbuffer = *hbuffer; /*copy into register*/
510
511 for (ix = 0; ix < ct; ix++) {
512
513 if (*pbuffer++ == ch)
514 ctmatches++;
515 } /*for*/
516
517 //unlockhandle (hbuffer);
518
519 if (!loadbufferfromfile (fnum, hbuffer, &ctbytes))
520 goto exit;
521
522 if (ctbytes == 0) { /*no more chars to look at*/
523
524 flreturned = true;
525
526 goto exit;
527 }
528 } /*while*/
529
530 exit:
531
532 *count = ctmatches;
533
534 disposehandle (hbuffer);
535
536 filecloser (hfile, fnum);
537
538 return (flreturned);
539 } /*fifcharcounter*/
540
541
542 boolean fifclosefile (const tyfilespec *fs) {
543
544 /*
545 close the file indicated by fs. deallocate the record and buffer. close
546 it if it wasn't open when openfile was called.
547 */
548
549 hdlopenfile hfile, hprev;
550 register hdlopenfile hf;
551
552 if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
553
554 fifopenfileerror (fs);
555
556 return (false);
557 }
558
559 hf = hfile; /*copy into register*/
560
561 closefile ((**hf).fnum);
562
563 if (hprev == nil)
564 hfirstfile = (**hf).nextfile;
565 else
566 (**hprev).nextfile = (**hf).nextfile;
567
568 disposehandle ((**hf).hbuffer);
569
570 disposehandle ((Handle) hf);
571
572 return (true);
573 } /*fifclosefile*/
574
575
576 boolean fifcloseallfiles (long refcon) {
577
578 register hdlopenfile x = hfirstfile;
579 register hdlopenfile hnext;
580 tyfilespec fs;
581
582 while (x != nil) {
583
584 hnext = (**x).nextfile;
585
586 if ((**x).refcon == refcon) {
587
588 fs = (**x).fs;
589
590 fifclosefile (&fs);
591 }
592
593 x = hnext;
594 } /*while*/
595
596 return (true);
597 } /*fifcloseallfiles*/
598
599
600 boolean fifopenfile (const tyfilespec *fs, long refcon) {
601
602 /*
603 open the indicated file, allocating a record and linking it into the list.
604 allocate a buffer. return true if the file could be opened.
605
606 10/31/91 dmb: check for eof when file is first opened
607 */
608
609 hdlfilenum fnum;
610 hdlopenfile hfile = nil;
611 hdlopenfile hprev;
612 register hdlopenfile hf;
613 Handle hbuffer;
614 long eof;
615
616 if (findopenfile (fs, &hfile, &hprev)) /*file was already opened by us*/
617 fifclosefile (fs);
618
619 if (!fileopener (fs, &hfile, &fnum))
620 return (false);
621
622 if (!newclearhandle (sizeof (tyopenfile), (Handle *) &hfile))
623 goto error;
624
625 if (!newclearhandle ((long) filebuffersize, &hbuffer))
626 goto error;
627
628 hf = hfile; /*copy into register*/
629
630 if (!filegeteof (fnum, &eof))
631 goto error;
632
633 (**hf).ctbytesleft = eof;
634
635 (**hf).fnum = fnum;
636
637 (**hf).fs = *fs;
638
639 (**hf).nextfile = hfirstfile; /*insert at the head of the file list*/
640
641 hfirstfile = hf;
642
643 (**hf).hbuffer = hbuffer;
644
645 (**hf).ixbuffer = filebuffersize; /*force file read on first getline/char*/
646
647 (**hf).ctbufferbytes = filebuffersize; //do getposition will work
648
649 (**hf).refcon = refcon;
650
651 return (true);
652
653 error:
654
655 disposehandle ((**hfile).hbuffer);
656
657 disposehandle ((Handle) hfile);
658
659 return (false);
660 } /*fifopenfile*/
661
662
663 boolean fifendoffile (const tyfilespec *fs) {
664
665 /*
666 return true if there's no more info in the file to be read.
667 */
668
669 hdlopenfile h1, h2;
670
671 if (!findopenfile (fs, &h1, &h2))
672 return (true);
673
674 return ((**h1).ctbytesleft <= 0);
675 } /*fifendoffile*/
676
677
678 static boolean fifread (const tyfilespec *fs, byte eolmarker, long ctmax, Handle *hdata) {
679
680 /*
681 read a chunk of data from the indicated file to a maximum of ctmax bytes.
682
683 if eolmarker is non-zero, stop when a matching character is encountered.
684
685 5.0.2b3 dmb: ignore actual value of eolmarker; it's either chnul or not. If not,
686 look for any kind of line ending.
687
688 5.1.4 dmb: flstriplf handling gets smart about buffer boundaries.
689 */
690
691 register Handle *x = hdata;
692 hdlopenfile hfile, hprev;
693 register hdlopenfile hf;
694 register long ctread = ctmax;
695 byte ch;
696 boolean flstriplf = false;
697
698 *x = nil;
699
700 if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
701
702 fifopenfileerror (fs);
703
704 return (false);
705 }
706
707 hf = hfile; /*copy into register*/
708
709 while (true) {
710
711 register long ixbuffer = (**hf).ixbuffer;
712 register long ixend = (**hf).ctbufferbytes;
713
714 if (ixbuffer >= ixend) { /*ran out of chars in buffer*/
715
716 if (!fileloadbuffer (hf)) {
717
718 disposehandle (*x);
719
720 *x = nil;
721
722 return (false);
723 }
724
725 ixbuffer = (**hf).ixbuffer;
726
727 ixend = (**hf).ctbufferbytes;
728 }
729
730 /*
731 first, see if first character is linefeed following previous cr
732 */
733
734 /*
735 first, extract what we want out of current buffer
736 */
737
738 ctread -= ixend - ixbuffer; /*start by planning to read entire buffer*/
739
740 if (ctread < 0) /*too many bytes; bring ixend in to match*/
741 ixend += ctread;
742
743 if (eolmarker != chnul) { /*see if eol is within range we're about to read*/
744
745 register long ix;
746 register byte *buf = (byte *) *(**hf).hbuffer;
747
748 for (ix = ixbuffer; ix < ixend; ++ix) {
749
750 ch = buf [ix];
751
752 if (ch == chreturn || ch == chlinefeed) { /*found it*/
753
754 if (ch == chreturn)
755 flstriplf = true;
756
757 ixend = ix; /*shorten range*/
758
759 ctread = 0; /*don't read no mo'*/
760
761 break;
762 }
763 }
764 }
765
766 bundle { /*move the data*/
767
768 register Handle buf = (**hf).hbuffer;
769 register long ct = ixend - ixbuffer;
770
771 if (*x == nil) { /*first time thru loop*/
772
773 long ix = ixbuffer;
774
775 if (!loadfromhandletohandle (buf, &ix, ct, false, x))
776 return (false);
777 }
778 else {
779
780 long ctbytes = gethandlesize (*x);
781
782 if (!sethandlesize (*x, ctbytes + ct)) {
783
784 disposehandle (*x);
785
786 *x = nil;
787
788 return (false);
789 }
790
791 moveleft (*buf + ixbuffer, **x + ctbytes, ct);
792 }
793
794 (**hf).ctbytesleft -= ct;
795 }
796
797 (**hf).ixbuffer = ixend; /*where we left off*/
798
799 if (ctread <= 0) { /*we're done!*/
800
801 if (eolmarker != chnul) { /*make sure we skip past the marker*/
802
803 ++(**hf).ixbuffer;
804
805 --(**hf).ctbytesleft;
806
807 if (flstriplf) { // strip next character if it's a linefeed
808
809 if (((**hf).ixbuffer < (**hf).ctbufferbytes) || fileloadbuffer (hf)) { // more chars
810
811 if ((*(**hf).hbuffer) [(**hf).ixbuffer] == chlinefeed) {
812
813 ++(**hf).ixbuffer;
814
815 --(**hf).ctbytesleft;
816 }
817 }
818 }
819 }
820
821 return (true);
822 }
823
824 /*
825 buffer is now depleted; try to move on to next
826 */
827
828 if ((**hf).ctbytesleft <= 0) /*we've emptied last buffer*/
829 return (true);
830 } /*while*/
831 } /*fifread*/
832
833
834
835 boolean fifreadline (const tyfilespec *fs, Handle *linestring) {
836
837 /*
838 read a line of text from the indicated file.
839 */
840
841 return (fifread (fs, chreturn, longinfinity, linestring));
842 } /*fifreadline*/
843
844
845 boolean fifreadhandle (const tyfilespec *fs, long ctbytes, Handle *x) {
846
847 /*
848 read a chunk of data from the indicated file.
849 */
850
851 return (fifread (fs, chnul, ctbytes, x));
852 } /*fifreadhandle*/
853
854
855 boolean fifwritehandle (const tyfilespec *fs, Handle x) {
856
857 /*
858 write some data at the end of the indicated file. it may be slow, but it's
859 very easy to use! then again it might not be slow.
860 */
861
862 boolean fl;
863 hdlopenfile hfile;
864 hdlfilenum fnum;
865 long ctbytes = gethandlesize (x);
866 long eofPos;
867
868 if (ctbytes == 0) /*nothing to write*/
869 return (true);
870
871 if (!fileopener (fs, &hfile, &fnum))
872 return (false);
873
874 filegeteof (fnum, &eofPos);
875
876 filesetposition (fnum, eofPos); /*position at the end of the file*/
877
878 fl = filewrite (fnum, ctbytes, *x); /*this call does not move memory*/
879
880 filecloser (hfile, fnum);
881
882 return (fl);
883 } /*fifwritehandle*/
884
885
886 boolean fifwriteline (const tyfilespec *fs, Handle linestring) {
887
888 /*
889 write a line at the end of the indicated file.
890 */
891
892 #ifdef WIN95VERSION
893 byte bseol [] = "\002\r\n";
894 #endif
895 #ifdef MACVERSION
896 byte bseol [] = "\001\r";
897 #endif
898
899 if (!pushtexthandle (bseol, linestring))
900 return (false);
901
902 return (fifwritehandle (fs, linestring));
903 } /*fifwriteline*/
904
905
906 boolean fifsetposition (const tyfilespec *fs, long pos) {
907
908 /*
909 5.0.1 dmb: new function. don't bother optimizing case where we're
910 repositioning withing the current buffer. In most cases, we'll be
911 called once, before any read operations.
912 */
913
914 hdlopenfile hfile, hprev;
915 register hdlopenfile hf;
916 long eof;
917
918 if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
919
920 fifopenfileerror (fs);
921
922 return (false);
923 }
924
925 hf = hfile; /*copy into register*/
926
927 if (!filesetposition ((**hf).fnum, pos))
928 return (false);
929
930 if (filegeteof ((**hf).fnum, &eof))
931 (**hf).ctbytesleft = eof - pos;
932
933 (**hf).ixbuffer = filebuffersize; /*force file read on first getline/char*/
934
935 (**hf).ctbufferbytes = filebuffersize; //so getposition will work
936
937 return (true);
938 } /*fifsetposition*/
939
940
941 boolean fifgetposition (const tyfilespec *fs, long *pos) {
942
943 /*
944 5.0.1 dmb: new function
945
946 5.1.5 dmb: account for unread buffer bytes
947 */
948
949 hdlopenfile hfile, hprev;
950 register hdlopenfile hf;
951
952 if (!findopenfile (fs, &hfile, &hprev)) { /*file isn't open*/
953
954 fifopenfileerror (fs);
955
956 return (false);
957 }
958
959 hf = hfile; /*copy into register*/
960
961 if (!filegetposition ((**hf).fnum, pos)) // next read will go from current file pos
962 return (false);
963
964 *pos -= (**hf).ctbufferbytes - (**hf).ixbuffer; // virtual pos is within already-read buffer
965
966 return (true);
967 } /*fifgetposition*/
968
969
970 boolean fifsetendoffile (const tyfilespec *fs, long eof) {
971
972 /*
973 set the eof for the file, opening & closing it if necessary
974
975 5.0.1 dmb: reset ctbytesleft after changing the eof
976
977 5.0.2 dmb: pin fpos after changing eof
978
979 2003-05-26 AR: only update ctbytesleft and fpos if hfile is not nil.
980 It can be nil if the file was not already open.
981 */
982
983 boolean fl;
984 hdlopenfile hfile;
985 hdlfilenum fnum;
986
987 if (!fileopener (fs, &hfile, &fnum))
988 return (false);
989
990 fl = fileseteof (fnum, eof);
991
992 if (fl && hfile != nil) {
993
994 (**hfile).ctbytesleft = max (0, eof - (**hfile).fpos);
995
996 (**hfile).fpos = min ((**hfile).fpos, eof);
997 }
998
999 filecloser (hfile, fnum);
1000
1001 return (fl);
1002 } /*fifseteof*/
1003
1004
1005 boolean fifgetendoffile (const tyfilespec *fs, long *eof) {
1006
1007 /*
1008 set the eof for the file, opening & closing it if necessary
1009
1010 5.0.1 dmb: reset ctbytesleft after changing the eof
1011 */
1012
1013 boolean fl;
1014 hdlopenfile hfile;
1015 hdlfilenum fnum;
1016
1017 if (!fileopener (fs, &hfile, &fnum))
1018 return (false);
1019
1020 fl = filegeteof (fnum, eof);
1021
1022 filecloser (hfile, fnum);
1023
1024 return (fl);
1025 } /*fifseteof*/
1026
1027
1028
1029
1030
1031
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.