1 /* @source ajfile *************************************************************
2 **
3 ** AJAX file routines
4 **
5 ** @author Copyright (C) 1999 Peter Rice
6 ** @version $Revision: 1.208 $
7 ** @modified May 14 Jon Ison Added ajFileExtnTrim & ajFileDirExtnTrim
8 ** @modified $Date: 2013/01/31 13:25:12 $ by $Author: rice $
9 ** @@
10 **
11 ** This library is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU Lesser General Public
13 ** License as published by the Free Software Foundation; either
14 ** version 2.1 of the License, or (at your option) any later version.
15 **
16 ** This library is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ** Lesser General Public License for more details.
20 **
21 ** You should have received a copy of the GNU Lesser General Public
22 ** License along with this library; if not, write to the Free Software
23 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 ** MA  02110-1301,  USA.
25 **
26 ******************************************************************************/
27 
28 /* ========================================================================= */
29 /* ============================= include files ============================= */
30 /* ========================================================================= */
31 
32 
33 #include "ajlib.h"
34 
35 #include "ajfile.h"
36 #include "ajsys.h"
37 #include "ajreg.h"
38 #include "ajnam.h"
39 #include "ajhttp.h"
40 #include "ajutil.h"
41 #include "ajmath.h"
42 #include "ajarr.h"
43 #include "ajfileio.h"
44 
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 #include <string.h>
48 #include <errno.h>
49 #include <time.h>
50 #include <limits.h>
51 /*#include <fcntl.h>*/
52 
53 
54 #ifndef WIN32
55 #include <dirent.h>
56 #else /* WIN32 */
57 #include "win32.h"
58 #include "dirent_w32.h"
59 #include <direct.h>
60 #endif /* !WIN32 */
61 
62 
63 #ifndef WIN32
64 #include <sys/wait.h>
65 #endif /* !WIN32 */
66 
67 
68 #ifndef WIN32
69 #include <unistd.h>
70 #endif /* !WIN32 */
71 
72 
73 
74 
75 
76 /* ========================================================================= */
77 /* =============================== constants =============================== */
78 /* ========================================================================= */
79 
80 #ifdef WIN32
81 #define PATH_MAX _MAX_PATH
82 #define getcwd _getcwd
83 #define fileno _fileno
84 #endif /* WIN32 */
85 
86 #define FILERECURSLV 20
87 
88 #ifdef __CYGWIN__
89 #define fopen(a,b) ajSysFuncFopen(a,b)
90 #endif /* __CYGWIN__ */
91 
92 
93 
94 
95 /* ========================================================================= */
96 /* =========================== global variables ============================ */
97 /* ========================================================================= */
98 
99 
100 
101 
102 /* ========================================================================= */
103 /* ============================= private data ============================== */
104 /* ========================================================================= */
105 
106 
107 
108 
109 /* ========================================================================= */
110 /* =========================== private constants =========================== */
111 /* ========================================================================= */
112 
113 
114 
115 
116 /* ========================================================================= */
117 /* =========================== private variables =========================== */
118 /* ========================================================================= */
119 
120 static ajuint fileBuffSize   = 2049;
121 static AjBool fileUsedStdin  = AJFALSE;
122 static AjBool fileUsedStdout = AJFALSE;
123 static AjBool fileUsedStderr = AJFALSE;
124 
125 static ajint fileHandle   = 0;
126 static ajint fileOpenCnt  = 0;
127 static ajint fileOpenMax  = 0;
128 static ajint fileCloseCnt = 0;
129 static ajint fileOpenTot  = 0;
130 
131 static AjPStr fileNameFix      = NULL;
132 static AjPStr fileNameStrTmp   = NULL;
133 static AjPStr fileNameTmp      = NULL;
134 static AjPStr fileDirfixTmp    = NULL;
135 static AjPStr fileCwd          = NULL;
136 static AjPStr fileTmpStr       = NULL;
137 static AjPStr fileTempFilename = NULL;
138 static AjPStr fileDirectory    = NULL;
139 
140 static AjPRegexp fileUserExp     = NULL;
141 static AjPRegexp fileWildExp     = NULL;
142 static AjPRegexp fileEntryExp    = NULL;
143 static AjPRegexp fileFileExp     = NULL;
144 static AjPRegexp fileRestExp     = NULL;
145 static AjPRegexp fileDirExp      = NULL;
146 static AjPRegexp fileFilenameExp = NULL;
147 
148 
149 
150 
151 /* ========================================================================= */
152 /* =========================== private functions =========================== */
153 /* ========================================================================= */
154 
155 static void   fileBuffLineDel(AjPFilebuff thys);
156 static AjBool fileBuffLineNext(AjPFilebuff thys);
157 static void   fileClose(AjPFile thys);
158 static void   fileListRecurs(const AjPStr file, AjPList list, ajint *recurs);
159 static DIR*   fileOpenDir(AjPStr *dir);
160 static void   filebuffFreeClear(AjPFilebuff buff);
161 static void   filePrintname(const AjPStr name, AjPStr* Pprintname);
162 
163 
164 
165 
166 /* ========================================================================= */
167 /* ======================= All functions by section ======================== */
168 /* ========================================================================= */
169 
170 
171 
172 
173 /* @filesection ajfile ********************************************************
174 **
175 ** @nam1rule aj Function belongs to the AJAX library.
176 **
177 ******************************************************************************/
178 
179 
180 
181 
182 /* @datasection [AjPDir] Directory ********************************************
183 **
184 ** Function is for manipulating directories and returns or takes at least one
185 ** AjPDir argument.
186 **
187 ** @nam2rule Dir
188 **
189 ******************************************************************************/
190 
191 
192 
193 
194 /* @section Directory constructors ********************************************
195 **
196 ** All constructors return a directory object by pointer.
197 ** It is the responsibility of the user to first destroy any previous
198 ** directory pointer. The target pointer
199 ** does not need to be initialised to NULL, but it is good programming practice
200 ** to do so anyway.
201 **
202 ** To replace or reuse an existing file, see instead
203 ** the file assignments and file modifiers functions.
204 **
205 ** The range of constructors is provided to allow flexibility in how
206 ** applications can open files to read various kinds of data.
207 **
208 ** @nam3rule New Constructor
209 ** @nam4rule Path Input file directory path
210 ** @suffix Pre Filename prefix(es) specified
211 ** @suffix Ext Filename extension(s) specified
212 **
213 ** @argrule Path path [const AjPStr] Path (full or relative) to directory
214 ** @argrule Pre prefix [const AjPStr] List of prefix wildcards for filename
215 **                                    prefixes to be used
216 ** @argrule Ext ext [const AjPStr] List of prefix wildcards for filename
217 **                                    extensions to be used
218 **
219 ** @valrule * [AjPDir] Directory object
220 **
221 ** @fcategory new
222 **
223 ** @fdata [AjPDir]
224 **
225 ******************************************************************************/
226 
227 
228 
229 
230 /* @func ajDirNewPath *********************************************************
231 **
232 ** Creates a new directory object.
233 **
234 ** @param [r] path [const AjPStr] Directory name
235 ** @return [AjPDir] New directory object.
236 **
237 ** @release 6.0.0
238 ** @@
239 ******************************************************************************/
240 
ajDirNewPath(const AjPStr path)241 AjPDir ajDirNewPath(const AjPStr path)
242 {
243     AjPDir thys;
244 
245     AJNEW0(thys);
246     ajStrAssignS(&thys->Name, path);
247     filePrintname(thys->Name, &thys->Printname);
248     thys->Prefix = NULL;
249     thys->Extension = NULL;
250 
251     return thys;
252 }
253 
254 
255 
256 
257 /* @func ajDirNewPathExt ******************************************************
258 **
259 ** Creates a new directory object.
260 **
261 ** @param [r] path [const AjPStr] Directory name
262 ** @param [r] ext [const AjPStr] File extension
263 ** @return [AjPDir] New directory object.
264 **
265 ** @release 6.0.0
266 ** @@
267 ******************************************************************************/
268 
ajDirNewPathExt(const AjPStr path,const AjPStr ext)269 AjPDir ajDirNewPathExt(const AjPStr path, const AjPStr ext)
270 {
271     AjPDir thys;
272 
273     AJNEW0(thys);
274     ajStrAssignS(&thys->Name, path);
275     filePrintname(thys->Name, &thys->Printname);
276 
277     if (ajStrMatchC(ext, " "))
278         ajStrAssignC(&thys->Extension, "");
279     else if (ajStrGetLen(ext))
280         ajStrAssignS(&thys->Extension, ext);
281 
282     return thys;
283 }
284 
285 
286 
287 
288 /* @func ajDirNewPathPreExt ***************************************************
289 **
290 ** Creates a new directory object.
291 **
292 ** @param [r] path [const AjPStr] Directory name
293 ** @param [r] prefix [const AjPStr] Filename prefix
294 ** @param [r] ext [const AjPStr] Filename extension
295 ** @return [AjPDir] New directory object.
296 **
297 ** @release 6.0.0
298 ** @@
299 ******************************************************************************/
300 
ajDirNewPathPreExt(const AjPStr path,const AjPStr prefix,const AjPStr ext)301 AjPDir ajDirNewPathPreExt(const AjPStr path,
302                           const AjPStr prefix, const AjPStr ext)
303 {
304     AjPDir thys;
305 
306     AJNEW0(thys);
307     ajStrAssignS(&thys->Name, path);
308     filePrintname(thys->Name, &thys->Printname);
309 
310     if (ajStrMatchC(prefix, " "))
311         ajStrAssignC(&thys->Prefix, "");
312     else if (ajStrGetLen(prefix))
313         ajStrAssignS(&thys->Prefix, prefix);
314 
315     if (ajStrMatchC(ext, " "))
316         ajStrAssignC(&thys->Extension, "");
317     else if (ajStrGetLen(ext))
318         ajStrAssignS(&thys->Extension, ext);
319 
320     return thys;
321 }
322 
323 
324 
325 
326 /* @section Directory destructors *********************************************
327 **
328 ** Destruction is achieved by deleting the object.
329 **
330 ** @nam3rule Del Destructor
331 **
332 ** @argrule Del Pdir [AjPDir*] Directory to be deleted
333 **
334 ** @valrule * [void]
335 **
336 ** @fcategory delete
337 **
338 ** @fdata [AjPDir]
339 **
340 ******************************************************************************/
341 
342 
343 
344 
345 /* @func ajDirDel *************************************************************
346 **
347 ** Close and free a directory object.
348 **
349 ** @param [d] Pdir [AjPDir*] Directory object.
350 ** @return [void]
351 **
352 ** @release 2.9.0
353 ** @@
354 ******************************************************************************/
355 
ajDirDel(AjPDir * Pdir)356 void ajDirDel(AjPDir* Pdir)
357 {
358     AjPDir thys;
359 
360     thys = *Pdir;
361 
362     if(!thys)
363         return;
364 
365     ajStrDel(&thys->Name);
366     ajStrDel(&thys->Printname);
367     ajStrDel(&thys->Prefix);
368     ajStrDel(&thys->Extension);
369     AJFREE(*Pdir);
370 
371     return;
372 }
373 
374 
375 
376 
377 /* @section Directory element retrieval ***************************************
378 **
379 ** Returns attributes of a directory
380 **
381 ** @nam3rule Get Return attribute value
382 ** @nam4rule Ext Return file extension
383 ** @nam4rule Prefix Return filename prefix
384 ** @nam4rule Path Return directory path
385 ** @nam4rule Printpath Return directory printable path
386 **
387 ** @argrule Get thys [const AjPDir] Directory
388 **
389 ** @valrule * [const AjPStr] String value
390 **
391 ** @fcategory use
392 **
393 ** @fdata [AjPDir]
394 **
395 ******************************************************************************/
396 
397 
398 
399 
400 /* @func ajDirGetExt **********************************************************
401 **
402 ** Returns the extension(s) of a directory object
403 **
404 ** @param [r] thys [const AjPDir] Directory object.
405 ** @return [const AjPStr] Directory name
406 **
407 ** @release 6.0.0
408 ** @@
409 ******************************************************************************/
410 
ajDirGetExt(const AjPDir thys)411 const AjPStr ajDirGetExt(const AjPDir thys)
412 {
413     if (!thys)
414         return NULL;
415 
416     return thys->Extension;
417 }
418 
419 
420 
421 
422 /* @func ajDirGetPath *********************************************************
423 **
424 ** Returns the full path of a directory object
425 **
426 ** @param [r] thys [const AjPDir] Directory object.
427 ** @return [const AjPStr] Directory name
428 **
429 ** @release 6.0.0
430 ** @@
431 ******************************************************************************/
432 
ajDirGetPath(const AjPDir thys)433 const AjPStr ajDirGetPath(const AjPDir thys)
434 {
435     if (!thys)
436         return NULL;
437 
438     return thys->Name;
439 }
440 
441 
442 
443 
444 /* @func ajDirGetPrefix *******************************************************
445 **
446 ** Returns the filename prefix(es) of a directory object
447 **
448 ** @param [r] thys [const AjPDir] Directory object.
449 ** @return [const AjPStr] Directory name
450 **
451 ** @release 6.0.0
452 ** @@
453 ******************************************************************************/
454 
ajDirGetPrefix(const AjPDir thys)455 const AjPStr ajDirGetPrefix(const AjPDir thys)
456 {
457     if (!thys)
458         return NULL;
459     return thys->Prefix;
460 }
461 
462 
463 
464 
465 /* @func ajDirGetPrintpath ****************************************************
466 **
467 ** Returns the full printable path of a directory object
468 **
469 ** @param [r] thys [const AjPDir] Directory object.
470 ** @return [const AjPStr] Directory printable name
471 **
472 ** @release 6.4.0
473 ** @@
474 ******************************************************************************/
475 
ajDirGetPrintpath(const AjPDir thys)476 const AjPStr ajDirGetPrintpath(const AjPDir thys)
477 {
478     if (!thys)
479         return NULL;
480 
481     return thys->Printname;
482 }
483 
484 
485 
486 
487 /* @datasection [AjPDirout] Output directory **********************************
488 **
489 ** Function is for manipulating output directories and returns or
490 ** takes at least one AjPDirout argument.
491 **
492 ** @nam2rule Dirout
493 **
494 ******************************************************************************/
495 
496 
497 
498 
499 /* @section Output directory constructors *************************************
500 **
501 ** All constructors return a directory object by pointer.
502 ** It is the responsibility of the user to first destroy any previous
503 ** directory pointer. The target pointer
504 ** does not need to be initialised to NULL, but it is good programming practice
505 ** to do so anyway.
506 **
507 ** To replace or reuse an existing file, see instead
508 ** the {File Assignments} and {File Modifiers} functions.
509 **
510 ** The range of constructors is provided to allow flexibility in how
511 ** applications can open files to read various kinds of data.
512 **
513 ** @nam3rule New Constructor
514 ** @nam4rule Path Output file directory path
515 ** @suffix Pre Filename prefix(es) specified
516 ** @suffix Ext Filename extension(s) specified
517 **
518 ** @argrule Path path [const AjPStr] Path (full or relative) to directory
519 ** @argrule Pre prefix [const AjPStr] List of prefix wildcards for filename
520 **                                    prefixes to be used
521 ** @argrule Ext ext [const AjPStr] List of prefix wildcards for filename
522 **                                    extensions to be used
523 **
524 ** @valrule * [AjPDirout] Output directory object
525 **
526 ** @fcategory new
527 **
528 ** @fdata [AjPDirout]
529 **
530 ******************************************************************************/
531 
532 
533 
534 
535 /* @func ajDiroutNewPath ******************************************************
536 **
537 ** Creates a new directory output object.
538 **
539 ** @param [r] path [const AjPStr] Directory name
540 ** @return [AjPDirout] New directory object.
541 **
542 ** @release 6.0.0
543 ** @@
544 ******************************************************************************/
545 
ajDiroutNewPath(const AjPStr path)546 AjPDirout ajDiroutNewPath(const AjPStr path)
547 {
548     AjPDirout thys;
549 
550     AJNEW0(thys);
551     ajStrAssignS(&thys->Name, path);
552     filePrintname(thys->Name, &thys->Printname);
553     thys->Extension = NULL;
554 
555     return thys;
556 }
557 
558 
559 
560 
561 /* @func ajDiroutNewPathExt ***************************************************
562 **
563 ** Creates a new directory output object.
564 **
565 ** @param [r] path [const AjPStr] Directory name
566 ** @param [r] ext [const AjPStr] File extension
567 ** @return [AjPDirout] New directory object.
568 **
569 ** @release 6.0.0
570 ** @@
571 ******************************************************************************/
572 
ajDiroutNewPathExt(const AjPStr path,const AjPStr ext)573 AjPDirout ajDiroutNewPathExt(const AjPStr path, const AjPStr ext)
574 {
575     AjPDirout thys;
576 
577     AJNEW0(thys);
578     ajStrAssignS(&thys->Name, path);
579     filePrintname(thys->Name, &thys->Printname);
580 
581     if (ajStrGetLen(ext))
582         ajStrAssignS(&thys->Extension, ext);
583 
584     return thys;
585 }
586 
587 
588 
589 
590 /* @section Output directory destructors **************************************
591 **
592 ** Destruction is achieved by deleting the object.
593 **
594 ** @nam3rule Del Destructor
595 **
596 ** @argrule Del Pdir [AjPDirout*] Directory to be deleted
597 **
598 ** @valrule * [void]
599 **
600 ** @fcategory delete
601 **
602 ** @fdata [AjPDirout]
603 **
604 ******************************************************************************/
605 
606 
607 
608 
609 /* @func ajDiroutDel **********************************************************
610 **
611 ** Close and free a directory object.
612 **
613 ** @param [d] Pdir [AjPDirout*] Directory object.
614 ** @return [void]
615 **
616 ** @release 2.9.0
617 ** @@
618 ******************************************************************************/
619 
ajDiroutDel(AjPDirout * Pdir)620 void ajDiroutDel(AjPDirout* Pdir)
621 {
622     AjPDirout thys;
623 
624     thys = *Pdir;
625 
626     if(!thys)
627         return;
628 
629     ajStrDel(&thys->Name);
630     ajStrDel(&thys->Printname);
631     ajStrDel(&thys->Extension);
632     AJFREE(*Pdir);
633 
634     return;
635 }
636 
637 
638 
639 
640 /* @section Output directory element retrieval ********************************
641 **
642 ** Returns attributes of a directory
643 **
644 ** @nam3rule Get Return attribute value
645 ** @nam4rule Ext Return file extension
646 ** @nam4rule Path Return directory path
647 ** @nam4rule Printpath Return directory printable path
648 **
649 ** @argrule Get thys [const AjPDirout] Directory
650 **
651 ** @valrule * [const AjPStr] String value
652 **
653 ** @fdata [AjPDirout]
654 ** @fcategory use
655 **
656 ******************************************************************************/
657 
658 
659 
660 
661 /* @func ajDiroutGetExt *******************************************************
662 **
663 ** Returns the extension of an output directory object
664 **
665 ** @param [r] thys [const AjPDirout] Directory object.
666 ** @return [const AjPStr] Directory name
667 **
668 ** @release 6.0.0
669 ** @@
670 ******************************************************************************/
671 
ajDiroutGetExt(const AjPDirout thys)672 const AjPStr ajDiroutGetExt(const AjPDirout thys)
673 {
674     if (!thys)
675         return NULL;
676 
677     return thys->Extension;
678 }
679 
680 
681 
682 
683 /* @func ajDiroutGetPath ******************************************************
684 **
685 ** Returns the name of an output directory object
686 **
687 ** @param [r] thys [const AjPDirout] Directory object.
688 ** @return [const AjPStr] Directory name
689 **
690 ** @release 6.0.0
691 ** @@
692 ******************************************************************************/
693 
ajDiroutGetPath(const AjPDirout thys)694 const AjPStr ajDiroutGetPath(const AjPDirout thys)
695 {
696     if (!thys)
697         return NULL;
698 
699     return thys->Name;
700 }
701 
702 
703 
704 
705 /* @func ajDiroutGetPrintpath *************************************************
706 **
707 ** Returns the printable name of an output directory object
708 **
709 ** @param [r] thys [const AjPDirout] Directory object.
710 ** @return [const AjPStr] Directory printable name
711 **
712 ** @release 6.4.0
713 ** @@
714 ******************************************************************************/
715 
ajDiroutGetPrintpath(const AjPDirout thys)716 const AjPStr ajDiroutGetPrintpath(const AjPDirout thys)
717 {
718     if (!thys)
719         return NULL;
720 
721     return thys->Printname;
722 }
723 
724 
725 
726 
727 /* @section Output directory element tests ************************************
728 **
729 ** Modifies attributes of a directory
730 **
731 ** @nam3rule Created tests whether directory is newly created
732 ** @nam3rule Exists  tests whether directory exists already
733 **
734 ** @argrule * thys [AjPDirout] Directory
735 **
736 ** @valrule * [AjBool] True on success
737 **
738 ** @fcategory use
739 **
740 ** @fdata [AjPDirout]
741 **
742 ******************************************************************************/
743 
744 
745 
746 
747 /* @func ajDiroutCreated ******************************************************
748 **
749 ** Tests if an output directory was created when it did not already exist
750 **
751 ** @param [u] thys [AjPDirout] Directory name
752 ** @return [AjBool] True if a newly cteated directory
753 **
754 ** @release 6.5.0
755 ** @@
756 ******************************************************************************/
757 
ajDiroutCreated(AjPDirout thys)758 AjBool ajDiroutCreated(AjPDirout thys)
759 {
760     if(!thys)
761         return ajFalse;
762 
763     return thys->Created;
764 }
765 
766 
767 
768 
769 /* @func ajDiroutExists *******************************************************
770 **
771 ** Tests a directory output object is for an existing directory
772 **
773 ** @param [u] thys [AjPDirout] Directory name
774 ** @return [AjBool] True on success.
775 **
776 ** @release 6.1.0
777 ** @@
778 ******************************************************************************/
779 
ajDiroutExists(AjPDirout thys)780 AjBool ajDiroutExists(AjPDirout thys)
781 {
782 #ifdef WIN32
783     if(ajStrMatchC(thys->Name, "."))
784     {
785         ajStrAssignC(&thys->Name, "");
786         ajStrAssignC(&thys->Printname, "");
787         return ajTrue;
788     }
789 #endif /* WIN32 */
790 
791     if(ajStrGetCharLast(thys->Name) != SLASH_CHAR)
792     {
793         ajStrAppendC(&thys->Name, SLASH_STRING);
794         filePrintname(thys->Name, &thys->Printname);
795     }
796 
797     if(!ajFilenameExistsDir(thys->Name))
798         return ajFalse;
799 
800     return ajTrue;
801 }
802 
803 
804 
805 
806 /* @section Output directory element modifiers ********************************
807 **
808 ** Modifies attributes of a directory
809 **
810 ** @nam3rule Open Open the directory, creating if needed
811 **
812 ** @argrule * thys [AjPDirout] Directory
813 **
814 ** @valrule * [AjBool] True on success
815 **
816 ** @fcategory modify
817 **
818 ** @fdata [AjPDirout]
819 **
820 ******************************************************************************/
821 
822 
823 
824 
825 /* @func ajDiroutOpen *********************************************************
826 **
827 ** Opens a directory output object, creating it if it does not already exist
828 **
829 ** @param [u] thys [AjPDirout] Directory name
830 ** @return [AjBool] True on success.
831 **
832 ** @release 6.1.0
833 ** @@
834 ******************************************************************************/
835 
ajDiroutOpen(AjPDirout thys)836 AjBool ajDiroutOpen(AjPDirout thys)
837 {
838 #ifdef WIN32
839     if(ajStrMatchC(thys->Name, "."))
840     {
841         ajStrAssignC(&thys->Name, "");
842         ajStrAssignC(&thys->Printname, "");
843         return ajTrue;
844     }
845 #endif /* WIN32 */
846 
847     if(ajStrGetCharLast(thys->Name) != SLASH_CHAR)
848     {
849         ajStrAppendC(&thys->Name, SLASH_STRING);
850         filePrintname(thys->Name, &thys->Printname);
851     }
852 
853     if(!ajFilenameExists(thys->Name))
854     {
855         ajSysCommandMakedirS(thys->Name);
856         thys->Created = ajTrue;
857     }
858 
859     if(!ajFilenameExistsDir(thys->Name))
860         return ajFalse;
861 
862     return ajTrue;
863 }
864 
865 
866 
867 
868 /* @datasection [AjPFile] File object *****************************************
869 **
870 ** Function is for manipulating buffered files and returns or takes at least
871 ** one AjSFileBuff argument.
872 **
873 ** Function is for manipulating file and file-related objects and usually
874 ** processes an AjSOutfile, AjSDir, AjSFileBuff, AjSFileBuffList or AjSFile
875 ** object.
876 **
877 ** @nam2rule File
878 ******************************************************************************/
879 
880 
881 
882 
883 /* @section File constructors *************************************************
884 **
885 ** All constructors return a new open file by pointer. It is the responsibility
886 ** of the user to first destroy any previous file pointer. The target pointer
887 ** does not need to be initialised to NULL, but it is good programming practice
888 ** to do so anyway.
889 **
890 ** The range of constructors is provided to allow flexibility in how
891 ** applications can open files to read and write various kinds of data.
892 **
893 ** @nam3rule New Constructor
894 ** @nam4rule From Create from an already open file
895 ** @nam4rule In Input file
896 ** @nam4rule Listin List of one or more input files
897 ** @nam4rule Out Output file created or rewritten
898 ** @nam4rule Outappend Output file appended to existing content
899 ** @nam5rule Block File opened for block read with internal system functions
900 ** @nam5rule FromCfile C FILE* structure used to create file object
901 ** @nam5rule Pipe Read from piped output of command
902 ** @nam5rule ListinList List of files specified
903 ** @nam5rule InPath Input directory path specified
904 ** @nam5rule OutPath Output directory path specified
905 ** @nam5rule Dir Input directory specified
906 ** @nam6rule ListinNameDir Input directory specified
907 ** @nam6rule OutNameDir Output directory specified
908 **
909 ** @suffix Name Existing filename specified
910 ** @suffix C Filename as C character string
911 ** @suffix S Filename as string
912 ** @suffix Pre Filename prefix(es) specified
913 ** @suffix Ext Filename extension(s) specified
914 ** @suffix Dir Input directory specified
915 ** @suffix Path Input directory path specified
916 ** @suffix Wild Wildcard filename
917 ** @suffix Exclude Filename exclusion wildcard(s)
918 **
919 **
920 **
921 ** @argrule C name [const char*] Filename
922 ** @argrule S name [const AjPStr] Filename
923 **
924 ** @argrule Block blocksize [ajuint] Block size for buffered system reads
925 ** @argrule Cfile file [FILE*] C file pointer
926 ** @argrule Pipe command [const AjPStr] Commandline
927 ** @argrule ListinList list [AjPList] List of filenames as strings
928 ** @argrule ListinNameDir dir [const AjPDir] Input directory
929 ** @argrule ListinDir dir [const AjPDir] Input directory
930 ** @argrule InNameDir dir [const AjPDir] Input directory
931 ** @argrule OutNameDir dir [const AjPDirout] Output directory
932 ** @argrule Path path [const AjPStr] Input directory path
933 ** @argrule OutPath path [const AjPStr] Output directory path
934 ** @argrule Pre prefix [const AjPStr] List of prefix wildcards for filename
935 **                                    prefixes to be used
936 ** @argrule Wild wildname [const AjPStr] Wildcard filename
937 ** @argrule Exclude exclude [const AjPStr] Filename exclusion wildcard(s)
938 ** @argrule Ext ext [const AjPStr] List of wildcards for filename
939 **                                    extensions to be used
940 **
941 ** @valrule * [AjPFile] New file object
942 ** @fcategory new
943 **
944 ** @fdata [AjPFile]
945 **
946 ******************************************************************************/
947 
948 
949 
950 
951 /* @func ajFileNewFromCfile ***************************************************
952 **
953 ** Creates a new file object from an open C file.
954 **
955 ** The file is for input, output, or append - depending on how the C FILE
956 ** pointer was opened.
957 **
958 ** @param [u] file [FILE*] C file.
959 ** @return [AjPFile] New file object.
960 **
961 ** @release 6.0.0
962 ** @@
963 ******************************************************************************/
964 
ajFileNewFromCfile(FILE * file)965 AjPFile ajFileNewFromCfile(FILE* file)
966 {
967     AjPFile thys;
968 
969     if(!file)
970         ajFatal("Trying to create an AJAX file from a bad C RTL FILE*");
971 
972     AJNEW0(thys);
973     thys->fp     = file;
974     thys->Handle = ++fileHandle;
975 
976     if(file == stdout)
977         thys->Name = ajStrNewC("stdout");
978     else if(file == stderr)
979         thys->Name = ajStrNewC("stderr");
980     else if(file == stdin)
981         thys->Name = ajStrNewC("stdin");
982     else
983         thys->Name = ajStrNew();
984 
985     ajStrAssignS(&thys->Printname, thys->Name);
986 
987     thys->End    = ajFalse;
988 
989     fileOpenCnt++;
990     fileOpenTot++;
991 
992     if(fileOpenCnt > fileOpenMax)
993         fileOpenMax = fileOpenCnt;
994 
995     if(file == stdin)
996         fileUsedStdin = ajTrue;
997     else if(file == stdout)
998         fileUsedStdout = ajTrue;
999     else if(file == stderr)
1000         fileUsedStderr = ajTrue;
1001 
1002     ajDebug("Created file from C FILE %p\n", file);
1003 
1004     return thys;
1005 }
1006 
1007 
1008 
1009 
1010 /* @funcstatic fileNew ********************************************************
1011 **
1012 ** Creates a new file object.
1013 **
1014 ** @return [AjPFile] New file object.
1015 **
1016 ** @release 6.0.0
1017 ** @@
1018 ******************************************************************************/
1019 
fileNew(void)1020 static AjPFile fileNew(void)
1021 {
1022     AjPFile thys;
1023 
1024     AJNEW0(thys);
1025     thys->fp = NULL;
1026     thys->Handle = 0;
1027     thys->Name = ajStrNew();
1028     thys->Printname = ajStrNew();
1029     thys->Buff = ajStrNewRes(fileBuffSize);
1030     thys->Buffsize = fileBuffSize;
1031     thys->List = NULL;
1032     thys->End = ajFalse;
1033 
1034     fileOpenCnt++;
1035     fileOpenTot++;
1036 
1037     if(fileOpenCnt > fileOpenMax)
1038         fileOpenMax = fileOpenCnt;
1039 
1040     return thys;
1041 }
1042 
1043 
1044 
1045 
1046 /* @func ajFileNewInBlockS ****************************************************
1047 **
1048 ** Creates a new file object to read a named file using blocked fread calls.
1049 **
1050 ** If the filename ends with a pipe character then a pipe is opened
1051 ** using ajFileNewInPipe.
1052 **
1053 ** @param [r] name [const AjPStr] File name.
1054 ** @param [r] blocksize [ajuint] Block size
1055 ** @return [AjPFile] New file object.
1056 **
1057 ** @release 6.0.0
1058 ** @@
1059 ******************************************************************************/
1060 
ajFileNewInBlockS(const AjPStr name,ajuint blocksize)1061 AjPFile ajFileNewInBlockS(const AjPStr name, ajuint blocksize)
1062 {
1063     AjPFile ret;
1064     ret = ajFileNewInNameS(name);
1065     ret->Blocksize = blocksize;
1066 
1067     if(blocksize)
1068     {
1069         ret->Workbuffer = ajCharNewRes(blocksize);
1070         /*setvbuf(ret->fp, ret->Workbuffer, _IOFBF, blocksize);*/
1071         ret->Readblock = ajCharNewRes(blocksize+1);
1072         ret->Blockpos = 0;
1073         ret->Blocklen = 0;
1074         ret->Blocksize = blocksize;
1075     }
1076 
1077     ajDebug("ajFileNewInBlock '%S' blocksize:%u\n", name, blocksize);
1078 
1079     return ret;
1080 }
1081 
1082 
1083 
1084 
1085 /* @func ajFileNewInNameC *****************************************************
1086 **
1087 ** Creates a new file object to read a named file.
1088 **
1089 ** If the filename begins with a pipe character then a pipe is opened
1090 ** using ajFileNewInPipe.
1091 **
1092 ** @param [r] name [const char*] File name.
1093 ** @return [AjPFile] New file object.
1094 **
1095 ** @release 6.2.0
1096 ** @@
1097 ******************************************************************************/
1098 
ajFileNewInNameC(const char * name)1099 AjPFile ajFileNewInNameC(const char *name)
1100 {
1101     ajStrAssignC(&fileNameStrTmp, name);
1102 
1103     return ajFileNewInNameS(fileNameStrTmp);
1104 }
1105 
1106 
1107 
1108 
1109 /* @func ajFileNewInNameS *****************************************************
1110 **
1111 ** Creates a new file object to read a named file.
1112 **
1113 ** If the filename ends with a pipe character then a pipe is opened
1114 ** using ajFileNewInPipe.
1115 **
1116 ** @param [r] name [const AjPStr] File name.
1117 ** @return [AjPFile] New file object.
1118 **
1119 ** @release 6.0.0
1120 ** @@
1121 ******************************************************************************/
1122 
ajFileNewInNameS(const AjPStr name)1123 AjPFile ajFileNewInNameS(const AjPStr name)
1124 {
1125     AjPFile thys          = NULL;
1126     AjPStr userstr = NULL;
1127     AjPStr reststr = NULL;
1128 
1129     AjPStr dirname        = NULL;
1130     AjPStr wildname       = NULL;
1131     AjPFile ptr;
1132 
1133     char *hdir = NULL;
1134 
1135     ajDebug("ajFileNewInNameS '%S'\n", name);
1136 
1137     if(ajStrMatchC(name, "stdin"))
1138     {
1139         thys = ajFileNewFromCfile(stdin);
1140         ajStrAssignC(&thys->Name, "stdin");
1141         ajStrAssignS(&thys->Printname, thys->Name);
1142         return thys;
1143     }
1144 
1145     ajStrAssignS(&fileNameTmp, name);
1146 
1147     if(ajStrGetCharLast(name) == '|')   /* pipe character at end */
1148         return ajFileNewInPipe(name);
1149 
1150     if(ajStrGetCharFirst(fileNameTmp) == '~')
1151     {
1152         ajDebug("starts with '~'\n");
1153 
1154         if(!fileUserExp)
1155             fileUserExp = ajRegCompC("^~([^/\\\\]*)");
1156 
1157         ajRegExec(fileUserExp, fileNameTmp);
1158         ajRegSubI(fileUserExp, 1, &userstr);
1159         ajRegPost(fileUserExp, &reststr);
1160         ajDebug("  user: '%S' rest: '%S'\n", userstr, reststr);
1161 
1162         if(ajStrGetLen(userstr))
1163         {
1164             /* username specified */
1165             hdir = ajSysGetHomedirFromName(ajStrGetPtr(userstr));
1166 
1167             if(!hdir)
1168             {
1169                 ajStrDel(&userstr);
1170                 ajStrDelStatic(&fileNameTmp);
1171                 ajStrDel(&reststr);
1172 
1173                 return NULL;
1174             }
1175 
1176             ajFmtPrintS(&fileNameTmp, "%s%S", hdir, reststr);
1177             AJFREE(hdir);
1178 
1179             ajDebug("use getpwnam: '%S'\n", fileNameTmp);
1180         }
1181         else
1182         {
1183             /* just ~/ */
1184             hdir = ajSysGetHomedir();
1185 
1186             if(hdir)
1187             {
1188                 ajFmtPrintS(&fileNameTmp, "%s%S", hdir, reststr);
1189                 AJFREE(hdir);
1190             }
1191             else
1192                 ajFmtPrintS(&fileNameTmp,"%S",reststr);
1193 
1194             ajDebug("use HOME: '%S'\n", fileNameTmp);
1195         }
1196     }
1197 
1198     ajStrDel(&userstr);
1199     ajStrDel(&reststr);
1200 
1201     if(!fileWildExp)
1202         fileWildExp = ajRegCompC("(.*/)?([^/]*[*?][^/]*)$");
1203 
1204     if(ajRegExec(fileWildExp, fileNameTmp))
1205     {
1206         /* wildcard file names */
1207         ajRegSubI(fileWildExp, 1, &dirname);
1208         ajRegSubI(fileWildExp, 2, &wildname);
1209         ajDebug("wild dir '%S' files '%S'\n", dirname, wildname);
1210         ptr = ajFileNewListinPathWild(dirname, wildname);
1211         ajStrDelStatic(&fileNameTmp);
1212         ajStrDel(&dirname);
1213         ajStrDel(&wildname);
1214 
1215         return ptr;
1216     }
1217 
1218 
1219 
1220     AJNEW0(thys);
1221     ajStrAssignS(&thys->Name, fileNameTmp);
1222     ajStrDelStatic(&fileNameTmp);
1223 
1224     ajNamResolve(&thys->Name);
1225 
1226 #ifdef WIN32
1227     if(ajStrMatchC(thys->Name, "/dev/null"))
1228         thys->fp = fopen("NUL", "rb");
1229     else
1230 #endif /* WIN32 */
1231         thys->fp = fopen(ajStrGetPtr(thys->Name), "rb");
1232 
1233     if(!thys->fp)
1234     {
1235         ajStrDel(&thys->Name);
1236         AJFREE(thys);
1237         /*    thys->Handle = 0;*/
1238         return NULL;
1239     }
1240 
1241     filePrintname(thys->Name, &thys->Printname);
1242 
1243     thys->Handle = ++fileHandle;
1244     thys->List = NULL;
1245     thys->End = ajFalse;
1246 
1247     fileOpenCnt++;
1248     fileOpenTot++;
1249     if(fileOpenCnt > fileOpenMax)
1250         fileOpenMax = fileOpenCnt;
1251 
1252     return thys;
1253 }
1254 
1255 
1256 
1257 
1258 /* @func ajFileNewInNamePathC *************************************************
1259 **
1260 ** Opens directory "dir".
1261 ** Looks for file "file"
1262 **
1263 ** @param [r] name [const char*] Filename.
1264 ** @param [r] path [const AjPStr] Directory
1265 ** @return [AjPFile] New file object.
1266 **
1267 ** @release 6.0.0
1268 ** @@
1269 ******************************************************************************/
1270 
ajFileNewInNamePathC(const char * name,const AjPStr path)1271 AjPFile ajFileNewInNamePathC(const char* name, const AjPStr path)
1272 {
1273     ajStrAssignC(&fileNameStrTmp, name);
1274 
1275     return ajFileNewInNamePathS(fileNameStrTmp, path);
1276 }
1277 
1278 
1279 
1280 
1281 /* @func ajFileNewInNamePathS *************************************************
1282 **
1283 ** Opens directory "dir".
1284 ** Looks for file "file"
1285 **
1286 ** @param [r] name [const AjPStr] Filename.
1287 ** @param [r] path [const AjPStr] Directory
1288 ** @return [AjPFile] New file object.
1289 **
1290 ** @release 6.0.0
1291 ** @@
1292 ******************************************************************************/
1293 
ajFileNewInNamePathS(const AjPStr name,const AjPStr path)1294 AjPFile ajFileNewInNamePathS(const AjPStr name, const AjPStr path)
1295 {
1296     if(ajStrGetLen(path))
1297         ajStrAssignS(&fileNameFix, path);
1298     else
1299         ajStrAssignC(&fileNameFix, CURRENT_DIR);
1300 
1301     if(ajStrGetCharLast(fileNameFix) != SLASH_CHAR)
1302         ajStrAppendC(&fileNameFix, SLASH_STRING);
1303 
1304     ajStrAppendS(&fileNameFix, name);
1305 
1306     return ajFileNewInNameS(fileNameFix);
1307 }
1308 
1309 
1310 
1311 
1312 /* @func ajFileNewInPipe ******************************************************
1313 **
1314 ** Creates a new file object to read the output from a command.
1315 **
1316 ** @param [r] command [const AjPStr] Command string.
1317 **                    The string may end with a trailing pipe character.
1318 ** @return [AjPFile] New file object.
1319 **
1320 ** @release 1.0.0
1321 ** @@
1322 ******************************************************************************/
1323 
ajFileNewInPipe(const AjPStr command)1324 AjPFile ajFileNewInPipe(const AjPStr command)
1325 {
1326     AjPFile thys = NULL;
1327 
1328     thys = ajSysCreateInpipeS(command);
1329 
1330     if(!thys)
1331         return NULL;
1332 
1333     thys->Handle = ++fileHandle;
1334 
1335     ajStrAssignS(&thys->Name, command);
1336     ajStrAssignS(&thys->Printname, thys->Name);
1337 
1338     thys->End = ajFalse;
1339 
1340     fileOpenCnt++;
1341     fileOpenTot++;
1342     if(fileOpenCnt > fileOpenMax)
1343         fileOpenMax = fileOpenCnt;
1344 
1345     return thys;
1346 }
1347 
1348 
1349 
1350 
1351 /* @func ajFileNewListinDirPre ************************************************
1352 **
1353 ** Opens directory "dir".
1354 ** Looks for file "file" with the extension (if any) specified
1355 ** for the directory
1356 **
1357 ** @param [r] dir [const AjPDir] Directory
1358 ** @param [r] prefix [const AjPStr] Wildcard Filename.
1359 ** @return [AjPFile] New file object.
1360 **
1361 ** @release 6.0.0
1362 ** @@
1363 ******************************************************************************/
1364 
ajFileNewListinDirPre(const AjPDir dir,const AjPStr prefix)1365 AjPFile ajFileNewListinDirPre(const AjPDir dir, const AjPStr prefix)
1366 {
1367     if(ajStrGetLen(dir->Name))
1368         ajStrAssignS(&fileNameFix, dir->Name);
1369     else
1370         ajStrAssignC(&fileNameFix, CURRENT_DIR);
1371 
1372     if(ajStrGetCharLast(fileNameFix) != SLASH_CHAR)
1373         ajStrAppendC(&fileNameFix, SLASH_STRING);
1374 
1375     ajStrAppendS(&fileNameFix, prefix);
1376     ajFilenameReplaceExtS(&fileNameFix, dir->Extension);
1377 
1378     return ajFileNewInNameS(fileNameFix);
1379 }
1380 
1381 
1382 
1383 
1384 /* @func ajFileNewListinList **************************************************
1385 **
1386 ** Creates a new file object with a list of input file names.
1387 **
1388 ** @param [u] list [AjPList] List of input filenames as strings.
1389 ** @return [AjPFile] New file object.
1390 **
1391 ** @release 6.0.0
1392 ** @@
1393 ******************************************************************************/
1394 
ajFileNewListinList(AjPList list)1395 AjPFile ajFileNewListinList(AjPList list)
1396 {
1397     AjPFile thys;
1398 
1399     AJNEW0(thys);
1400 
1401     thys->List = list;
1402     thys->Name = NULL;
1403     ajListstrTrace(thys->List);
1404     ajListstrPop(thys->List, &thys->Name);
1405     ajDebug("ajFileNewListinList pop '%S'\n", thys->Name);
1406     ajListstrTrace(thys->List);
1407     ajNamResolve(&thys->Name);
1408 
1409 #ifdef WIN32
1410     if(ajStrMatchC(thys->Name, "/dev/null"))
1411         thys->fp = fopen("NUL", "rb");
1412     else
1413 #endif /* WIN32 */
1414         thys->fp = fopen(ajStrGetPtr(thys->Name), "rb");
1415 
1416 
1417     if(!thys->fp)
1418     {
1419         ajDebug("ajFileNewListinList fopen failed\n");
1420         ajStrDel(&thys->Name);
1421         thys->Handle = 0;
1422         AJFREE(thys);
1423         return NULL;
1424     }
1425 
1426     filePrintname(thys->Name, &thys->Printname);
1427 
1428     thys->Handle = ++fileHandle;
1429     thys->End = ajFalse;
1430 
1431     fileOpenCnt++;
1432     fileOpenTot++;
1433 
1434     if(fileOpenCnt > fileOpenMax)
1435         fileOpenMax = fileOpenCnt;
1436 
1437     return thys;
1438 }
1439 
1440 
1441 
1442 
1443 /* @func ajFileNewListinNameDirS **********************************************
1444 **
1445 ** Opens directory "dir" and looks for file "filename".
1446 **
1447 ** @param [r] name [const AjPStr] Wildcard Filename.
1448 ** @param [r] dir [const AjPDir] Directory
1449 ** @return [AjPFile] New file object.
1450 **
1451 ** @release 6.0.0
1452 ** @@
1453 ******************************************************************************/
1454 
ajFileNewListinNameDirS(const AjPStr name,const AjPDir dir)1455 AjPFile ajFileNewListinNameDirS(const AjPStr name, const AjPDir dir)
1456 {
1457     if(ajStrGetLen(dir->Name))
1458         ajStrAssignS(&fileNameFix, dir->Name);
1459     else
1460         ajStrAssignC(&fileNameFix, CURRENT_DIR);
1461 
1462     if(ajStrGetCharLast(fileNameFix) != SLASH_CHAR)
1463         ajStrAppendC(&fileNameFix, SLASH_STRING);
1464 
1465     ajStrAppendS(&fileNameFix, name);
1466 
1467     return ajFileNewInNameS(fileNameFix);
1468 }
1469 
1470 
1471 
1472 
1473 /* @func ajFileNewListinPathWild **********************************************
1474 **
1475 ** Opens directory "dir"
1476 ** Looks for file(s) matching "file"
1477 ** Opens them as a list of files using a simple file object.
1478 **
1479 ** @param [r] path [const AjPStr] Directory
1480 ** @param [r] wildname [const AjPStr] Wildcard filename.
1481 ** @return [AjPFile] New file object.
1482 **
1483 ** @release 6.0.0
1484 ** @@
1485 ******************************************************************************/
1486 
ajFileNewListinPathWild(const AjPStr path,const AjPStr wildname)1487 AjPFile ajFileNewListinPathWild(const AjPStr path, const AjPStr wildname)
1488 {
1489     DIR* dp;
1490 #if defined(AJ_IRIXLF)
1491     struct dirent64 *de;
1492 #else /* !AJ_IRIXLF */
1493     struct dirent* de;
1494 #endif /* AJ_IRIXLF */
1495     ajint dirsize;
1496     AjPList list = NULL;
1497     AjPStr name  = NULL;
1498 #ifdef _POSIX_C_SOURCE
1499     char buf[sizeof(struct dirent)+MAXNAMLEN];
1500 #endif /* _POSIX_C_SOURCE */
1501 
1502     if(ajStrGetLen(path))
1503         ajStrAssignS(&fileDirfixTmp, path);
1504     else
1505         ajStrAssignC(&fileDirfixTmp, CURRENT_DIR);
1506 
1507     if(ajStrGetCharLast(fileDirfixTmp) != SLASH_CHAR)
1508         ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
1509 
1510     dp = fileOpenDir(&fileDirfixTmp);
1511 
1512     if(!dp)
1513         return NULL;
1514 
1515     dirsize = 0;
1516     list = ajListstrNew();
1517 
1518     while(
1519 #if defined(AJ_IRIXLF)
1520 #ifdef _POSIX_C_SOURCE
1521         !readdir64_r(dp,(struct dirent64 *)buf,&de)
1522 #else /* !_POSIX_C_SOURCE */
1523         (de=readdir64(dp))
1524 #endif /* _POSIX_C_SOURCE */
1525 #else /* !AJ_IRIXLF */
1526 #ifdef _POSIX_C_SOURCE
1527         !readdir_r(dp,(struct dirent *)buf,&de)
1528 #else /* _POSIX_C_SOURCE */
1529         (de=readdir(dp))
1530 #endif /* _POSIX_C_SOURCE */
1531 #endif /* AJ_IRIXLF */
1532           )
1533     {
1534 #ifdef _POSIX_C_SOURCE
1535         if(!de)
1536             break;
1537 #endif /* _POSIX_C_SOURCE */
1538         /* skip deleted files with inode zero */
1539 #ifndef __CYGWIN__
1540         if(!de->d_ino)
1541             continue;
1542 #endif /* !__CYGWIN__ */
1543 
1544         if(ajCharMatchC(de->d_name, "."))
1545             continue;
1546 
1547         if(ajCharMatchC(de->d_name, ".."))
1548             continue;
1549 
1550         if(!ajCharMatchWildS(de->d_name, wildname))
1551             continue;
1552 
1553         dirsize++;
1554         ajDebug("accept '%s'\n", de->d_name);
1555         name = NULL;
1556         ajFmtPrintS(&name, "%S%s", fileDirfixTmp, de->d_name);
1557         ajListstrPushAppend(list, name);
1558     }
1559 
1560     closedir(dp);
1561     ajDebug("%d files for '%S' '%S'\n", dirsize, path, wildname);
1562 
1563     return ajFileNewListinList(list);
1564 }
1565 
1566 
1567 
1568 
1569 /* @func ajFileNewListinPathWildExclude ***************************************
1570 **
1571 ** Opens directory "dir".
1572 ** Looks for file(s) matching "file".
1573 ** Skip files matching excluded files wildcard.
1574 ** Opens them as a list of files using a simple file object.
1575 **
1576 ** @param [r] path [const AjPStr] Directory path
1577 ** @param [r] wildname [const AjPStr] Wildcard filename.
1578 ** @param [r] exclude [const AjPStr] Wildcard excluded filename.
1579 ** @return [AjPFile] New file object.
1580 **
1581 ** @release 6.0.0
1582 ** @@
1583 ******************************************************************************/
1584 
ajFileNewListinPathWildExclude(const AjPStr path,const AjPStr wildname,const AjPStr exclude)1585 AjPFile ajFileNewListinPathWildExclude(const AjPStr path,
1586                                        const AjPStr wildname,
1587                                        const AjPStr exclude)
1588 {
1589     DIR* dp;
1590 #if defined(AJ_IRIXLF)
1591     struct dirent64 *de;
1592 #else /* !AJ_IRIXLF */
1593     struct dirent* de;
1594 #endif /* AJ_IRIXLF */
1595     ajint dirsize;
1596     AjPList list = NULL;
1597     AjPStr name  = NULL;
1598 #ifdef _POSIX_C_SOURCE
1599     char buf[sizeof(struct dirent)+MAXNAMLEN];
1600 #endif /* _POSIX_C_SOURCE */
1601     ajDebug("ajFileNewListinPathWildExclude "
1602             "path '%S' wildname '%S' exclude '%S\n",
1603             path, wildname, exclude);
1604 
1605     if(ajStrGetLen(path))
1606         ajStrAssignS(&fileDirfixTmp, path);
1607     else
1608         ajStrAssignC(&fileDirfixTmp, CURRENT_DIR);
1609 
1610     if(ajStrGetCharLast(fileDirfixTmp) != SLASH_CHAR)
1611         ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
1612 
1613     dp = fileOpenDir(&fileDirfixTmp);
1614     if(!dp)
1615         return NULL;
1616 
1617     dirsize = 0;
1618     list = ajListstrNew();
1619 
1620     while(
1621 #if defined(AJ_IRIXLF)
1622 #ifdef _POSIX_C_SOURCE
1623         !readdir64_r(dp,(struct dirent64 *)buf,&de)
1624 #else /* !_POSIX_C_SOURCE */
1625         (de=readdir64(dp))
1626 #endif /* _POSIX_C_SOURCE */
1627 #else /* !AJ_IRIXLF */
1628 #ifdef _POSIX_C_SOURCE
1629         !readdir_r(dp,(struct dirent *)buf,&de)
1630 #else /* !_POSIX_C_SOURCE */
1631         (de=readdir(dp))
1632 #endif /* _POSIX_C_SOURCE */
1633 #endif /* AJ_IRIXLF */
1634           )
1635     {
1636 #ifdef _POSIX_C_SOURCE
1637         if(!de)
1638             break;
1639 #endif /* _POSIX_C_SOURCE */
1640         /* skip deleted files with inode zero */
1641 #ifndef __CYGWIN__
1642         if(!de->d_ino)
1643             continue;
1644 #endif /* !__CYGWIN__ */
1645 
1646         if(ajCharMatchC(de->d_name, "."))
1647             continue;
1648 
1649         if(ajCharMatchC(de->d_name, ".."))
1650             continue;
1651 
1652         ajStrAssignC(&fileNameTmp, de->d_name);
1653 
1654         if(!ajFilenameTestExclude(fileNameTmp, exclude, wildname))
1655             continue;
1656 
1657         dirsize++;
1658         ajDebug("accept '%s'\n", de->d_name);
1659         name = NULL;
1660         ajFmtPrintS(&name, "%S%s", fileDirfixTmp, de->d_name);
1661         ajListstrPushAppend(list, name);
1662     }
1663 
1664     closedir(dp);
1665     ajDebug("%d files for '%S' '%S'\n", dirsize, path, wildname);
1666 
1667     return ajFileNewListinList(list);
1668 }
1669 
1670 
1671 
1672 
1673 /* @func ajFileNewOutNameC ****************************************************
1674 **
1675 ** Creates a new output file object with a specified name.
1676 **
1677 ** 'stdout' and 'stderr' are special names for standard output and
1678 ** standard error respectively.
1679 **
1680 ** @param [r] name [const char*] File name.
1681 ** @return [AjPFile] New file object.
1682 **
1683 ** @release 6.0.0
1684 ** @@
1685 ******************************************************************************/
1686 
ajFileNewOutNameC(const char * name)1687 AjPFile ajFileNewOutNameC(const char* name)
1688 {
1689     ajStrAssignC(&fileNameStrTmp, name);
1690 
1691     return ajFileNewOutNameS(fileNameStrTmp);
1692 }
1693 
1694 
1695 
1696 
1697 /* @func ajFileNewOutNameS ****************************************************
1698 **
1699 ** Creates a new output file object with a specified name.
1700 **
1701 ** 'stdout' and 'stderr' are special names for standard output and
1702 ** standard error respectively.
1703 **
1704 ** @param [r] name [const AjPStr] File name.
1705 ** @return [AjPFile] New file object.
1706 **
1707 ** @release 6.0.0
1708 ** @@
1709 ******************************************************************************/
1710 
ajFileNewOutNameS(const AjPStr name)1711 AjPFile ajFileNewOutNameS(const AjPStr name)
1712 {
1713     AjPFile thys;
1714 
1715     if(ajStrMatchC(name, "stdout"))
1716     {
1717         thys = ajFileNewFromCfile(stdout);
1718         ajStrAssignC(&thys->Name, "stdout");
1719         ajStrAssignS(&thys->Printname, thys->Name);
1720         return thys;
1721     }
1722 
1723     if(ajStrMatchC(name, "stderr"))
1724     {
1725         thys = ajFileNewFromCfile(stderr);
1726         ajStrAssignC(&thys->Name, "stderr");
1727         ajStrAssignS(&thys->Printname, thys->Name);
1728         return thys;
1729     }
1730 
1731     AJNEW0(thys);
1732 
1733 #ifdef WIN32
1734     if(ajStrMatchC(name, "/dev/null"))
1735         thys->fp = fopen(ajStrGetPtr(name), "wb");
1736     else
1737 #endif /* WIN32 */
1738         thys->fp = fopen(ajStrGetPtr(name), "wb");
1739 
1740     if(!thys->fp)
1741     {
1742         ajWarn("Failed to open output file '%S' error:%d '%s'",
1743                name, errno, strerror(errno));
1744         thys->Handle = 0;
1745         return NULL;
1746     }
1747 
1748     thys->Handle = ++fileHandle;
1749     ajStrAssignS(&thys->Name, name);
1750     filePrintname(thys->Name, &thys->Printname);
1751     thys->End = ajFalse;
1752 
1753     fileOpenCnt++;
1754     fileOpenTot++;
1755 
1756     if(fileOpenCnt > fileOpenMax)
1757         fileOpenMax = fileOpenCnt;
1758 
1759     thys->App = ajFalse;
1760 
1761     return thys;
1762 }
1763 
1764 
1765 
1766 
1767 /* @func ajFileNewOutNameDirS *************************************************
1768 **
1769 ** Creates a new output file object with a specified directory and name.
1770 ** Uses the default extension (if any) specified for the directory.
1771 **
1772 ** 'stdout' and 'stderr' are special names for standard output and
1773 ** standard error respectively.
1774 **
1775 ** If the filename already has a directory specified,
1776 ** the "dir" argument is ignored.
1777 **
1778 ** @param [r] name [const AjPStr] File name.
1779 ** @param [rN] dir [const AjPDirout] Directory
1780 **                                  (optional, can be empty or NULL).
1781 ** @return [AjPFile] New file object.
1782 **
1783 ** @release 6.0.0
1784 ** @@
1785 ******************************************************************************/
1786 
ajFileNewOutNameDirS(const AjPStr name,const AjPDirout dir)1787 AjPFile ajFileNewOutNameDirS(const AjPStr name, const AjPDirout dir)
1788 {
1789     AjPFile thys;
1790 
1791     ajDebug("ajFileNewOutNameDirS('%S' '%S')\n", dir->Name, name);
1792 
1793     AJNEW0(thys);
1794 
1795     if(!dir)
1796     {
1797 #ifdef WIN32
1798         if(ajStrMatchC(name, "/dev/null"))
1799             thys->fp = fopen("NUL", "wb");
1800         else
1801 #endif /* WIN32 */
1802             thys->fp = fopen(ajStrGetPtr(name), "wb");
1803         ajDebug("ajFileNewOutNameDirS open name '%S'\n", name);
1804     }
1805     else
1806     {
1807         if(ajFilenameHasPath(name))
1808             ajStrAssignS(&fileDirfixTmp, name);
1809         else
1810         {
1811             ajStrAssignS(&fileDirfixTmp, dir->Name);
1812 
1813             if(ajStrGetCharLast(dir->Name) != SLASH_CHAR)
1814                 ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
1815 
1816             ajStrAppendS(&fileDirfixTmp, name);
1817         }
1818 
1819         ajFilenameSetExtS(&fileDirfixTmp, dir->Extension);
1820 
1821         thys->fp = fopen(ajStrGetPtr(fileDirfixTmp), "wb");
1822         ajDebug("ajFileNewOutNameDirS open dirfix '%S'\n", fileDirfixTmp);
1823     }
1824 
1825     if(!thys->fp)
1826     {
1827         ajWarn("Failed to open output file '%S' in directory '%S' "
1828                "error:%d '%s'",
1829                name, dir, errno, strerror(errno));
1830         thys->Handle = 0;
1831         return NULL;
1832     }
1833 
1834     thys->Handle = ++fileHandle;
1835     ajStrAssignS(&thys->Name, name);
1836     filePrintname(thys->Name, &thys->Printname);
1837     thys->End = ajFalse;
1838 
1839     fileOpenCnt++;
1840     fileOpenTot++;
1841 
1842     if(fileOpenCnt > fileOpenMax)
1843         fileOpenMax = fileOpenCnt;
1844 
1845     return thys;
1846 }
1847 
1848 
1849 
1850 
1851 /* @func ajFileNewOutNamePathS ************************************************
1852 **
1853 ** Creates a new output file object with a specified directory and name.
1854 **
1855 ** 'stdout' and 'stderr' are special names for standard output and
1856 ** standard error respectively.
1857 **
1858 ** If the filename already has a directory specified,
1859 ** the "dir" argument is ignored.
1860 **
1861 ** @param [r] name [const AjPStr] File name.
1862 ** @param [rN] path [const AjPStr] Directory (optional, can be empty or NULL).
1863 ** @return [AjPFile] New file object.
1864 **
1865 ** @release 6.0.0
1866 ** @@
1867 ******************************************************************************/
1868 
ajFileNewOutNamePathS(const AjPStr name,const AjPStr path)1869 AjPFile ajFileNewOutNamePathS(const AjPStr name, const AjPStr path)
1870 {
1871     AjPFile thys;
1872 
1873     ajDebug("ajFileNewOutNamePathS('%S' '%S')\n", path, name);
1874 
1875     if(ajStrMatchC(name, "stdout"))
1876         return ajFileNewFromCfile(stdout);
1877 
1878     if(ajStrMatchC(name, "stderr"))
1879         return ajFileNewFromCfile(stderr);
1880 
1881     AJNEW0(thys);
1882 
1883     if(!ajStrGetLen(path))
1884     {
1885 #ifdef WIN32
1886         if(ajStrMatchC(name, "/dev/null"))
1887             thys->fp = fopen("NUL", "wb");
1888         else
1889 #endif /* WIN32 */
1890             thys->fp = fopen(ajStrGetPtr(name), "wb");
1891         ajDebug("ajFileNewOutNamePathS open name '%S'\n", name);
1892     }
1893     else
1894     {
1895         if(ajFilenameHasPath(name))
1896             ajStrAssignS(&fileDirfixTmp, name);
1897         else
1898         {
1899             ajStrAssignS(&fileDirfixTmp, path);
1900 
1901             if(ajStrGetCharLast(path) != SLASH_CHAR)
1902                 ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
1903 
1904             ajStrAppendS(&fileDirfixTmp, name);
1905         }
1906 
1907         thys->fp = fopen(ajStrGetPtr(fileDirfixTmp), "wb");
1908         ajDebug("ajFileNewOutNamePathS open dirfix '%S'\n", fileDirfixTmp);
1909     }
1910 
1911     if(!thys->fp)
1912     {
1913         ajWarn("Failed to open output file '%S' in directory '%S' "
1914                "error:%d '%s'",
1915                name, path, errno, strerror(errno));
1916         thys->Handle = 0;
1917         return NULL;
1918     }
1919 
1920     thys->Handle = ++fileHandle;
1921     ajStrAssignS(&thys->Name, name);
1922     filePrintname(thys->Name, &thys->Printname);
1923     thys->End = ajFalse;
1924 
1925     fileOpenCnt++;
1926     fileOpenTot++;
1927 
1928     if(fileOpenCnt > fileOpenMax)
1929         fileOpenMax = fileOpenCnt;
1930 
1931     return thys;
1932 }
1933 
1934 
1935 
1936 
1937 /* @func ajFileNewOutappendNameS **********************************************
1938 **
1939 ** Creates an output file object with a specified name.
1940 ** The file is opened for append so it either appends to an existing file
1941 ** or opens a new one.
1942 **
1943 ** @param [r] name [const AjPStr] File name.
1944 ** @return [AjPFile] New file object.
1945 **
1946 ** @release 6.0.0
1947 ** @@
1948 ******************************************************************************/
1949 
ajFileNewOutappendNameS(const AjPStr name)1950 AjPFile ajFileNewOutappendNameS(const AjPStr name)
1951 {
1952     AjPFile thys;
1953 
1954     AJNEW0(thys);
1955 
1956 #ifdef WIN32
1957     if(ajStrMatchC(name, "/dev/null"))
1958         thys->fp = fopen("NUL", "ab");
1959     else
1960 #endif /* WIN32 */
1961         thys->fp = fopen(ajStrGetPtr(name), "ab");
1962 
1963     if(!thys->fp)
1964     {
1965         thys->Handle = 0;
1966         return NULL;
1967     }
1968 
1969     thys->Handle = ++fileHandle;
1970     ajStrAssignS(&thys->Name, name);
1971     filePrintname(thys->Name, &thys->Printname);
1972     thys->End = ajFalse;
1973 
1974     fileOpenCnt++;
1975     fileOpenTot++;
1976 
1977     if(fileOpenCnt > fileOpenMax)
1978         fileOpenMax = fileOpenCnt;
1979 
1980     thys->App = ajTrue;
1981 
1982     return thys;
1983 }
1984 
1985 
1986 
1987 
1988 /* @section File destructors **************************************************
1989 **
1990 ** Destruction is achieved by closing the file.
1991 **
1992 ** Unlike ANSI C, there are tests to ensure a file is not closed twice.
1993 **
1994 ** @nam3rule Close Close file and destroy object
1995 **
1996 ** @argrule Close Pfile [AjPFile*] File to be closed and deleted
1997 **
1998 ** @valrule Close [void]
1999 **
2000 ** @fcategory delete
2001 **
2002 ** @fdata [AjPFile]
2003 **
2004 ******************************************************************************/
2005 
2006 
2007 
2008 
2009 /* @func ajFileClose **********************************************************
2010 **
2011 ** Close and free a file object.
2012 **
2013 ** @param [d] Pfile [AjPFile*] File.
2014 ** @return [void]
2015 **
2016 ** @release 1.0.0
2017 ** @@
2018 ******************************************************************************/
2019 
ajFileClose(AjPFile * Pfile)2020 void ajFileClose(AjPFile* Pfile)
2021 {
2022     AjPFile thys;
2023 
2024     thys = Pfile ? *Pfile : 0;
2025 
2026     if(!Pfile)
2027         return;
2028 
2029     if(!*Pfile)
2030         return;
2031 
2032     fileClose(thys);
2033     AJFREE(*Pfile);
2034 
2035     return;
2036 }
2037 
2038 
2039 
2040 
2041 /* @funcstatic fileClose ******************************************************
2042 **
2043 ** Closes a file object. Used as part of the public destructor and
2044 ** other public functions.
2045 **
2046 ** @param [w] thys [AjPFile] File.
2047 ** @return [void]
2048 **
2049 ** @release 1.0.0
2050 ** @@
2051 ******************************************************************************/
2052 
fileClose(AjPFile thys)2053 static void fileClose(AjPFile thys)
2054 {
2055     int sleepcount = 0;
2056     int status = 0;
2057     int maxsleep = 60;
2058 #ifndef WIN32
2059     pid_t retval;
2060 #endif /* !WIN32 */
2061 
2062     if(!thys)
2063         return;
2064 
2065 #ifndef WIN32
2066 
2067     /*
2068     ** Only wait for the PID to close if we have read everything.
2069     ** Otherwise ... we will wait for ever as it will not
2070     ** go away until its output is read or closed
2071     */
2072 
2073     if (thys->Pid && thys->End)
2074     {
2075         while((retval=waitpid(thys->Pid,&status,WNOHANG))!= thys->Pid)
2076         {
2077             if(sleepcount > maxsleep)
2078                 break;
2079 
2080             sleepcount++;
2081             sleep(1);
2082 
2083             /*ajDebug("fileClose waitpid returns %d status %d\n",
2084               retval, status);*/
2085 
2086             if(retval == -1)
2087                 if(errno != EINTR)
2088                     break;
2089 
2090             status = 0;
2091         }
2092     }
2093 #else /* WIN32 */
2094     if(thys->Process && thys->End)
2095     {
2096         WaitForSingleObject(thys->Process,INFINITE);
2097         CloseHandle(thys->Process);
2098         CloseHandle(thys->Thread);
2099     }
2100 
2101 #endif /* !WIN32 */
2102 
2103     if(thys->Handle)
2104     {
2105         if(thys->fp)
2106         {
2107             if(thys->fp == stdout)
2108                 fileUsedStdout = ajFalse;
2109             else if(thys->fp == stderr)
2110                 fileUsedStderr = ajFalse;
2111             else if(thys->fp == stdin)
2112                 fileUsedStdin = ajFalse;
2113             else
2114             {
2115                 if(fclose(thys->fp))
2116                     ajFatal("File close problem in fileClose error:%d '%s'",
2117                             errno, strerror(errno));
2118             }
2119         }
2120 
2121         thys->Handle = 0;
2122 
2123         fileCloseCnt++;
2124         fileOpenCnt--;
2125     }
2126     else
2127         ajDebug("file already closed\n");
2128 
2129     ajStrDel(&thys->Name);
2130     ajStrDel(&thys->Printname);
2131     ajStrDel(&thys->Buff);
2132     ajListstrFreeData(&thys->List);
2133     AJFREE(thys->Workbuffer);
2134     AJFREE(thys->Readblock);
2135 
2136     return;
2137 }
2138 
2139 
2140 
2141 
2142 /* @section File reopen *******************************************************
2143 **
2144 ** These functions close a file and open a new file with the same file object
2145 **
2146 ** @nam3rule Reopen Reopen an existing input file object
2147 ** @nam4rule Name Reopen using a new filename
2148 ** @nam4rule Next Reopen using the next filename in the input file list
2149 **
2150 ** @argrule Reopen file [AjPFile] File object
2151 ** @argrule Name name [const AjPStr] Filename to open
2152 **
2153 ** @valrule * [AjBool] True on success
2154 **
2155 ** @fcategory modify
2156 **
2157 ** @fdata [AjPFile]
2158 **
2159 ******************************************************************************/
2160 
2161 
2162 
2163 
2164 /* @func ajFileReopenName *****************************************************
2165 **
2166 ** Reopens an input file with a new name
2167 **
2168 ** @param [u] file [AjPFile] Input file.
2169 ** @param [r] name [const AjPStr] name of file.
2170 ** @return [AjBool] True on success
2171 **
2172 ** @release 6.0.0
2173 ** @@
2174 ******************************************************************************/
2175 
ajFileReopenName(AjPFile file,const AjPStr name)2176 AjBool ajFileReopenName(AjPFile file, const AjPStr name)
2177 {
2178     ajStrAssignS(&file->Name, name);
2179     filePrintname(file->Name, &file->Printname);
2180 
2181     if(!freopen(MAJSTRGETPTR(file->Name), "rb", file->fp))
2182         return ajFalse;
2183 
2184     return ajTrue;
2185 }
2186 
2187 
2188 
2189 
2190 /* @func ajFileReopenNext *****************************************************
2191 **
2192 ** Given a file object that includes a list of input files, closes the
2193 ** current input file and opens the next one.
2194 **
2195 ** @param [u] file [AjPFile] File object.
2196 ** @return [AjBool] ajTrue on success.
2197 **
2198 ** @release 6.0.0
2199 ** @@
2200 ******************************************************************************/
2201 
ajFileReopenNext(AjPFile file)2202 AjBool ajFileReopenNext(AjPFile file)
2203 {
2204     static AjPStr name = NULL;
2205 
2206     if(!file->List)
2207     {
2208         ajDebug("ajFileReopenNext for non-list file %F\n", file);
2209         return ajFalse;
2210     }
2211 
2212     ajDebug("ajFileReopenNext for non-list file %F name '%S'\n",
2213             file, file->Name);
2214 
2215     /*ajListTrace(file->List);*/
2216     if(!ajListPop(file->List, (void*) &name))
2217     {
2218         /* end of list */
2219         ajDebug("ajFileReopenNext failed - list completed\n");
2220 
2221         return ajFalse;
2222     }
2223 
2224     ajDebug("ajFileReopenNext filename '%S'\n", name);
2225 
2226     if(!ajFileReopenName(file, name))
2227     {
2228         /* popped from the list */
2229         ajStrDel(&name);
2230 
2231         return ajFalse;
2232     }
2233 
2234     /* popped from the list */
2235     ajStrDel(&name);
2236     file->End = ajFalse;
2237 
2238     ajDebug("ajFileNext success\n");
2239 
2240     return ajTrue;
2241 }
2242 
2243 
2244 
2245 
2246 /* @section File modifiers ****************************************************
2247 **
2248 ** Modifying file object attributes, reset file position.
2249 **
2250 ** @nam3rule Fix Reset all file attribute that may have been changed
2251 **                 by non-AJAX calls
2252 ** @nam3rule Reset Reset a file attribute that may have been changed
2253 **                 by non-AJAX calls
2254 ** @nam3rule Seek Call system file seek function
2255 ** @nam3rule Set Set a file attribute
2256 ** @nam4rule ResetEof Reset the end of file value using the system
2257 **                    'feof' function
2258 ** @nam4rule ResetPos Reset the file position using the system
2259 **                    'ftell' function
2260 ** @nam4rule SetEof Set the end of file value for a file that has been read
2261 **                  without going past the last record.
2262 ** @nam4rule SetUnbuffer Set file unbuffered
2263 **
2264 ** @argrule * file [AjPFile] File object
2265 ** @argrule Seek offset [ajlong] File offset to pass to system seek call
2266 ** @argrule Seek wherefrom [ajint] File wherefrom value to pass to
2267 **                                 system seek call
2268 **
2269 ** @valrule Seek [ajint] Return value from seek
2270 ** @valrule SetUnbuffer [void]
2271 ** @valrule Fix [AjBool] End of file reached
2272 ** @valrule Eof [AjBool] End of file reached
2273 ** @valrule Pos [ajlong] File position from ftell
2274 **
2275 ** @fcategory modify
2276 **
2277 ** @fdata [AjPFile]
2278 **
2279 ******************************************************************************/
2280 
2281 
2282 
2283 
2284 /* @func ajFileFix ************************************************************
2285 **
2286 ** Resets internal file attribute after non-AJAX operations.
2287 **
2288 ** @param [u] file [AjPFile] File.
2289 ** @return [AjBool] True if end of file is reached
2290 **
2291 ** @release 6.0.0
2292 ** @@
2293 ******************************************************************************/
2294 
ajFileFix(AjPFile file)2295 AjBool ajFileFix(AjPFile file)
2296 {
2297     ajFileResetPos(file);
2298 
2299     return ajFileResetEof(file);
2300 }
2301 
2302 
2303 
2304 
2305 /* @func ajFileResetEof *******************************************************
2306 **
2307 ** Resets the end of file attribute after non-AJAX operations.
2308 **
2309 ** @param [u] file [AjPFile] File.
2310 ** @return [AjBool] True if end of file is set
2311 **
2312 ** @release 6.0.0
2313 ** @@
2314 ******************************************************************************/
2315 
ajFileResetEof(AjPFile file)2316 AjBool ajFileResetEof(AjPFile file)
2317 {
2318     if(feof(file->fp))
2319         file->End = ajTrue;
2320     else
2321         file->End = ajFalse;
2322 
2323     return file->End;
2324 }
2325 
2326 
2327 
2328 
2329 /* @func ajFileResetPos *******************************************************
2330 **
2331 ** Resets and returns the current position in an open file.
2332 **
2333 ** @param [u] file [AjPFile] File.
2334 ** @return [ajlong] Result of 'ftell'
2335 **
2336 ** @release 6.0.0
2337 ** @@
2338 ******************************************************************************/
2339 
ajFileResetPos(AjPFile file)2340 ajlong ajFileResetPos(AjPFile file)
2341 {
2342     if(!file->fp)
2343         return 0;
2344 
2345     file->Filepos = ftell(file->fp);
2346 
2347     return file->Filepos;
2348 }
2349 
2350 
2351 
2352 
2353 /* @func ajFileSeek ***********************************************************
2354 **
2355 ** Sets the current position in an open file.
2356 **
2357 ** Resets the end-of-file flag End for cases where end-of-file was
2358 ** reached and then we seek back somewhere in the file.
2359 **
2360 ** @param [u] file [AjPFile] File.
2361 ** @param [r] offset [ajlong] Offset
2362 ** @param [r] wherefrom [ajint] Start of offset, as defined for 'fseek'.
2363 ** @return [ajint] Result of 'fseek'
2364 **
2365 ** @release 1.0.0
2366 ** @@
2367 ******************************************************************************/
2368 
ajFileSeek(AjPFile file,ajlong offset,ajint wherefrom)2369 ajint ajFileSeek(AjPFile file, ajlong offset, ajint wherefrom)
2370 {
2371     ajint ret;
2372 
2373     clearerr(file->fp);
2374     ret = fseek(file->fp, offset, wherefrom);
2375 
2376     if(feof(file->fp))
2377     {
2378         file->End = ajTrue;
2379         ajDebug("EOF ajFileSeek file %F\n", file);
2380     }
2381     else
2382         file->End = ajFalse;
2383 
2384     return ret;
2385 }
2386 
2387 
2388 
2389 
2390 /* @func ajFileSetEof *********************************************************
2391 **
2392 ** Ensures a binary file has reached the end of file and sets the
2393 ** end of file attribute
2394 **
2395 ** @param [u] file [AjPFile] File.
2396 ** @return [AjBool] True if end of file was already
2397 **
2398 ** @release 6.5.0
2399 ** @@
2400 ******************************************************************************/
2401 
ajFileSetEof(AjPFile file)2402 AjBool ajFileSetEof(AjPFile file)
2403 {
2404     AjBool ret = file->End;
2405     char c;
2406 
2407     fseek(file->fp, 0, SEEK_END);
2408     fread(&c, 1, 1, file->fp);
2409 
2410     if(feof(file->fp))
2411         file->End = ajTrue;
2412     else
2413         file->End = ajFalse;
2414 
2415     return ret;
2416 }
2417 
2418 
2419 
2420 
2421 /* @func ajFileSetUnbuffer ****************************************************
2422 **
2423 ** Turns off system buffering of an output file, for example to allow
2424 ** debug output to appear even in the event of a program abort.
2425 **
2426 ** @param [u] file [AjPFile] File object.
2427 ** @return [void]
2428 **
2429 ** @release 6.0.0
2430 ** @@
2431 ******************************************************************************/
2432 
ajFileSetUnbuffer(AjPFile file)2433 void ajFileSetUnbuffer(AjPFile file)
2434 {
2435     setbuf(file->fp, NULL);
2436 
2437     return;
2438 }
2439 
2440 
2441 
2442 
2443 /* @section File casts ********************************************************
2444 **
2445 ** Returns attributes of a file object
2446 **
2447 ** @nam3rule Get Return attribute of a file object
2448 ** @nam4rule GetFileptr Return C file pointer
2449 ** @nam4rule GetName Return filename
2450 ** @nam4rule GetPrintname Return printable filename
2451 ** @nam3rule Is Return true if attribute is set
2452 ** @nam4rule IsAppend Test file is open for appending output
2453 ** @nam4rule IsEof Test end of file has been reached
2454 ** @nam4rule IsFile Test file is a regular file, not a pipe or terminal
2455 ** @nam4rule IsStderr Test file is writing to standard error
2456 ** @nam4rule IsStdin test file is reading from standard input
2457 ** @nam4rule IsStdout test file is writing to standard output
2458 **
2459 ** @suffix C Return a C character string
2460 ** @suffix S return a string object
2461 **
2462 ** @argrule * file [const AjPFile] File object
2463 **
2464 ** @valrule C [const char*] C character string
2465 ** @valrule S [const AjPStr] String object
2466 ** @valrule Is [AjBool] True on success
2467 ** @valrule GetFileptr [FILE*] C file pointer
2468 **
2469 ** @fdata [AjPFile]
2470 ** @fcategory cast
2471 **
2472 ******************************************************************************/
2473 
2474 
2475 
2476 
2477 /* @func ajFileGetFileptr *****************************************************
2478 **
2479 ** Returns the C file pointer for an open file.
2480 **
2481 ** Warning: Using the C file pointer will make internals of the file
2482 ** object invalid. The file position can be reset with ajFileResetPos.
2483 **
2484 ** @param [r] file [const AjPFile] File.
2485 ** @return [FILE*] C file pointer for the file.
2486 **
2487 ** @release 6.0.0
2488 ** @@
2489 ******************************************************************************/
2490 
ajFileGetFileptr(const AjPFile file)2491 FILE* ajFileGetFileptr(const AjPFile file)
2492 {
2493     if(!file)
2494         return NULL;
2495 
2496     return file->fp;
2497 }
2498 
2499 
2500 
2501 
2502 /* @func ajFileGetNameC *******************************************************
2503 **
2504 ** Returns the file name for a file object. The filename returned is a pointer
2505 ** to the real string internally, so the user must take care not to change
2506 ** it and cannot trust the value if the file object is deleted.
2507 **
2508 ** @param [r] file [const AjPFile] File.
2509 ** @return [const char*] Filename as a C character string.
2510 **
2511 ** @release 6.0.0
2512 ** @@
2513 ******************************************************************************/
2514 
ajFileGetNameC(const AjPFile file)2515 const char* ajFileGetNameC(const AjPFile file)
2516 {
2517     if(!file)
2518         return "";
2519 
2520     return ajStrGetPtr(file->Name);
2521 }
2522 
2523 
2524 
2525 
2526 /* @func ajFileGetNameS *******************************************************
2527 **
2528 ** Returns the file name for a file object. The filename returned is a pointer
2529 ** to the real string internally, so the user must take care not to change
2530 ** it and cannot trust the value if the file object is deleted.
2531 **
2532 ** @param [r] file [const AjPFile] File.
2533 ** @return [const AjPStr] Filename as a C character string.
2534 **
2535 ** @release 6.0.0
2536 ** @@
2537 ******************************************************************************/
2538 
ajFileGetNameS(const AjPFile file)2539 const AjPStr ajFileGetNameS(const AjPFile file)
2540 {
2541     if(!file)
2542         return NULL;
2543 
2544     return file->Name;
2545 }
2546 
2547 
2548 
2549 
2550 /* @func ajFileGetPrintnameC **************************************************
2551 **
2552 ** Returns the file name for a file object. The filename returned is a pointer
2553 ** to the real string internally, so the user must take care not to change
2554 ** it and cannot trust the value if the file object is deleted.
2555 **
2556 ** @param [r] file [const AjPFile] File.
2557 ** @return [const char*] Printable filename as a C character string.
2558 **
2559 ** @release 6.4.0
2560 ** @@
2561 ******************************************************************************/
2562 
ajFileGetPrintnameC(const AjPFile file)2563 const char* ajFileGetPrintnameC(const AjPFile file)
2564 {
2565     if(!file)
2566         return "";
2567 
2568     return ajStrGetPtr(file->Printname);
2569 }
2570 
2571 
2572 
2573 
2574 /* @func ajFileGetPrintnameS **************************************************
2575 **
2576 ** Returns the file name for a file object. The filename returned is a pointer
2577 ** to the real string internally, so the user must take care not to change
2578 ** it and cannot trust the value if the file object is deleted.
2579 **
2580 ** @param [r] file [const AjPFile] File.
2581 ** @return [const AjPStr] Printable filename as a C character string.
2582 **
2583 ** @release 6.4.0
2584 ** @@
2585 ******************************************************************************/
2586 
ajFileGetPrintnameS(const AjPFile file)2587 const AjPStr ajFileGetPrintnameS(const AjPFile file)
2588 {
2589     if(!file)
2590         return NULL;
2591 
2592     return file->Printname;
2593 }
2594 
2595 
2596 
2597 
2598 /* @func ajFileIsAppend *******************************************************
2599 **
2600 ** Returns the App element for a file object. The App element is True if the
2601 ** file was opened for appending to, False otherwise.
2602 **
2603 ** @param [r] file [const AjPFile] File.
2604 ** @return [AjBool] App element, True if if file was opened for appending to,
2605 ** False otherwise.
2606 **
2607 ** @release 6.0.0
2608 ** @@
2609 ******************************************************************************/
2610 
ajFileIsAppend(const AjPFile file)2611 AjBool ajFileIsAppend(const AjPFile file)
2612 {
2613     if(!file)
2614         return ajFalse;
2615 
2616     return file->App;
2617 }
2618 
2619 
2620 
2621 
2622 /* @func ajFileIsEof **********************************************************
2623 **
2624 ** Tests whether we have reached end of file already
2625 **
2626 ** @param [r] file [const AjPFile] File
2627 ** @return [AjBool] ajTrue if we already set end-of-file
2628 **
2629 ** @release 6.0.0
2630 ** @@
2631 ******************************************************************************/
2632 
ajFileIsEof(const AjPFile file)2633 AjBool ajFileIsEof(const AjPFile file)
2634 {
2635     if(!file)
2636         return ajTrue;
2637 
2638     return file->End;
2639 }
2640 
2641 
2642 
2643 
2644 /* @func ajFileIsFile *********************************************************
2645 **
2646 ** Tests whether a file object is really a regular file.
2647 **
2648 ** Used to test for character devices, for example standard input from
2649 ** a terminal.
2650 **
2651 ** @param [r] file [const AjPFile] File object.
2652 ** @return [AjBool] ajTrue if the file matches stderr.
2653 **
2654 ** @release 6.3.0
2655 ** @@
2656 ******************************************************************************/
2657 
ajFileIsFile(const AjPFile file)2658 AjBool ajFileIsFile(const AjPFile file)
2659 {
2660 #if defined(AJ_IRIXLF)
2661     struct stat64 buf;
2662 #else /* !AJ_IRIXLF */
2663     struct stat buf;
2664 #endif /* AJ_IRIXLF */
2665 
2666     if(
2667 #if defined(AJ_IRIXLF)
2668         !fstat64(fileno(file->fp), &buf)
2669 #else /* !AJ_IRIXLF */
2670         !fstat(fileno(file->fp), &buf)
2671 #endif /* AJ_IRIXLF */
2672        )
2673         if((ajuint)buf.st_mode & AJ_FILE_R)
2674             return ajTrue;
2675 
2676     return ajFalse;
2677 }
2678 
2679 
2680 
2681 
2682 /* @func ajFileIsStderr *******************************************************
2683 **
2684 ** Tests whether a file object is really stderr.
2685 **
2686 ** @param [r] file [const AjPFile] File object.
2687 ** @return [AjBool] ajTrue if the file matches stderr.
2688 **
2689 ** @release 6.0.0
2690 ** @@
2691 ******************************************************************************/
2692 
ajFileIsStderr(const AjPFile file)2693 AjBool ajFileIsStderr(const AjPFile file)
2694 {
2695     if(!file)
2696         return ajFalse;
2697 
2698     if(file->fp == stderr)
2699         return ajTrue;
2700 
2701     return ajFalse;
2702 }
2703 
2704 
2705 
2706 
2707 /* @func ajFileIsStdin ********************************************************
2708 **
2709 ** Tests whether a file object is really stdin.
2710 **
2711 ** @param [r] file [const AjPFile] File object.
2712 ** @return [AjBool] ajTrue if the file matches stdin.
2713 **
2714 ** @release 6.0.0
2715 ** @@
2716 ******************************************************************************/
2717 
ajFileIsStdin(const AjPFile file)2718 AjBool ajFileIsStdin(const AjPFile file)
2719 {
2720     if(!file)
2721         return ajFalse;
2722 
2723     if(file->fp == stdin)
2724         return ajTrue;
2725 
2726     return ajFalse;
2727 }
2728 
2729 
2730 
2731 
2732 /* @func ajFileIsStdout *******************************************************
2733 **
2734 ** Tests whether a file object is really stdout.
2735 **
2736 ** @param [r] file [const AjPFile] File object.
2737 ** @return [AjBool] ajTrue if the file matches stdout.
2738 **
2739 ** @release 6.0.0
2740 ** @@
2741 ******************************************************************************/
2742 
ajFileIsStdout(const AjPFile file)2743 AjBool ajFileIsStdout(const AjPFile file)
2744 {
2745     if(!file)
2746         return ajFalse;
2747 
2748     if(file->fp == stdout)
2749         return ajTrue;
2750 
2751     return ajFalse;
2752 }
2753 
2754 
2755 
2756 
2757 
2758 /* @section File debug ********************************************************
2759 **
2760 ** report file object contents for debugging
2761 **
2762 **
2763 ** @nam3rule Trace    Print report to debug file (if any)
2764 **
2765 ** @argrule * file [const AjPFile]
2766 **
2767 ** @valrule * [void]
2768 **
2769 ** @fcategory misc
2770 ** @fdata [AjPFile]
2771 **
2772 ******************************************************************************/
2773 
2774 
2775 
2776 
2777 /* @func ajFileTrace **********************************************************
2778 **
2779 ** Writes debug messages to trace the contents of a file object.
2780 **
2781 ** @param [r] file [const AjPFile] File.
2782 ** @return [void]
2783 **
2784 ** @release 1.0.0
2785 ** @@
2786 ******************************************************************************/
2787 
ajFileTrace(const AjPFile file)2788 void ajFileTrace(const AjPFile file)
2789 {
2790     ajulong i;
2791     ajulong j;
2792     AjIList iter;
2793 
2794     ajDebug("File: '%S'\n", file->Name);
2795     ajDebug("Print: '%S'\n", file->Printname);
2796     ajDebug("  Handle:   %d\n", file->Handle);
2797     ajDebug("  End:      %B\n", file->End);
2798     ajDebug("  Append:   %B\n", file->App);
2799     ajDebug("  Filepos:  %ld\n", file->Filepos);
2800 #ifndef WIN32
2801     ajDebug("  PID:      %d\n", file->Pid);
2802 #endif /* !WIN32 */
2803     ajDebug("  feof:     %d\n", feof(file->fp));
2804     ajDebug("  ftell:    %ld\n", ftell(file->fp));
2805     i =  ajListGetLength(file->List);
2806     ajDebug("  List:     %Lu\n", i);
2807 
2808     if(i)
2809     {
2810         j = 0;
2811         iter = ajListIterNewread(file->List);
2812 
2813         while (!ajListIterDone(iter))
2814             ajDebug("    %3Ld: '%S'\n", ++j, ajListstrIterGet(iter));
2815     }
2816 
2817     return;
2818 }
2819 
2820 
2821 
2822 
2823 /* @section File exit *********************************************************
2824 **
2825 ** Cleanup memory on program exit
2826 **
2827 ** @fnote     general exit functions, no arguments
2828 **
2829 ** @nam3rule Exit Cleanup and report on exit
2830 **
2831 ** @valrule * [void]
2832 **
2833 ** @fcategory misc
2834 **
2835 ** @fdata [AjPFile]
2836 **
2837 ******************************************************************************/
2838 
2839 
2840 
2841 
2842 /* @func ajFileExit ***********************************************************
2843 **
2844 ** Prints a summary of file usage with debug calls
2845 **
2846 ** @return [void]
2847 **
2848 ** @release 1.0.0
2849 ** @@
2850 ******************************************************************************/
2851 
ajFileExit(void)2852 void ajFileExit(void)
2853 {
2854     ajDebug("File usage : %d opened, %d closed, %d max, %d total\n",
2855             fileOpenCnt, fileCloseCnt, fileOpenMax, fileOpenTot);
2856 
2857     ajStrDel(&fileNameFix);
2858     ajStrDel(&fileNameTmp);
2859     ajStrDel(&fileNameStrTmp);
2860     ajStrDel(&fileDirfixTmp);
2861     ajStrDel(&fileCwd);
2862     ajStrDel(&fileTmpStr);
2863     ajStrDel(&fileTempFilename);
2864     ajStrDel(&fileDirectory);
2865 
2866     ajRegFree(&fileUserExp);
2867     ajRegFree(&fileWildExp);
2868     ajRegFree(&fileEntryExp);
2869     ajRegFree(&fileFileExp);
2870     ajRegFree(&fileRestExp);
2871     ajRegFree(&fileDirExp);
2872     ajRegFree(&fileFilenameExp);
2873 
2874     return;
2875 }
2876 
2877 
2878 
2879 
2880 /* @datasection [AjPFilebuff] Buffered file object ****************************
2881 **
2882 ** Function is for manipulating buffered files and returns or takes at least
2883 ** one AjSFileBuff argument.
2884 **
2885 ** @nam2rule Filebuff
2886 **
2887 ******************************************************************************/
2888 
2889 
2890 
2891 
2892 /* @section Buffered file constructors ****************************************
2893 **
2894 ** All constructors return a new open file by pointer. It is the responsibility
2895 ** of the user to first destroy any previous file pointer. The target pointer
2896 ** does not need to be initialised to NULL, but it is good programming practice
2897 ** to do so anyway.
2898 **
2899 ** To replace or reuse an existing file, see instead
2900 ** the {File Assignments} and {File Modifiers} functions.
2901 **
2902 ** The range of constructors is provided to allow flexibility in how
2903 ** applications can open files to read various kinds of data.
2904 **
2905 ** @nam3rule New Constructor
2906 ** @nam4rule From Create from an already open file
2907 ** @nam4rule Nofile Create without an input file for use as a text buffer
2908 ** @nam5rule FromFile AjPfile object used to create buffered file object
2909 ** @nam5rule FromCfile C FILE* structure used to create buffered file object
2910 ** @nam4rule Line Create buffer with line of text
2911 ** @nam4rule Listin List of one or more input files
2912 ** @nam5rule ListinList List of files specified
2913 **
2914 ** @suffix Name Existing filename specified
2915 ** @suffix C Filename as C character string
2916 ** @suffix S Filename as string
2917 ** @suffix Path Input directory path specified
2918 ** @suffix Wild Wildcard filename
2919 ** @suffix Exclude Filename exclusion wildcard(s)
2920 **
2921 ** @argrule Cfile file [FILE*] C file pointer
2922 ** @argrule ListinList list [AjPList] List of filenames as strings
2923 ** @argrule C name [const char*] Filename
2924 ** @argrule S name [const AjPStr] Filename
2925 ** @argrule Line line [const AjPStr] First line of new buffer
2926 ** @argrule FromFile file [AjPFile] Input file object
2927 ** @argrule Path path [const AjPStr] Input directory path
2928 ** @argrule Wild wildname [const AjPStr] Wildcard filename
2929 ** @argrule Exclude exclude [const AjPStr] Filename exclusion wildcard(s)
2930 **
2931 ** @valrule * [AjPFilebuff] New buffered file object
2932 **
2933 ** @fcategory new
2934 **
2935 ** @fdata [AjPFilebuff]
2936 **
2937 ******************************************************************************/
2938 
2939 
2940 
2941 
2942 /* @func ajFilebuffNewFromCfile ***********************************************
2943 **
2944 ** Creates a new buffered input file from an already open C file.
2945 **
2946 ** @param [u] file [FILE*] Open C file.
2947 ** @return [AjPFilebuff] New buffered file object.
2948 **
2949 ** @release 6.0.0
2950 ** @@
2951 ******************************************************************************/
2952 
ajFilebuffNewFromCfile(FILE * file)2953 AjPFilebuff ajFilebuffNewFromCfile(FILE* file)
2954 {
2955     AjPFile tmpcfile;
2956 
2957     tmpcfile = ajFileNewFromCfile(file);
2958 
2959     if(!tmpcfile)
2960         return NULL;
2961 
2962     return ajFilebuffNewFromFile(tmpcfile);
2963 }
2964 
2965 
2966 
2967 
2968 /* @func ajFilebuffNewFromFile ************************************************
2969 **
2970 ** Creates a new buffered input file object from an open file.
2971 **
2972 ** @param [u] file [AjPFile] File object to be buffered.
2973 ** @return [AjPFilebuff] New buffered file object.
2974 **
2975 ** @release 6.0.0
2976 ** @@
2977 ******************************************************************************/
2978 
ajFilebuffNewFromFile(AjPFile file)2979 AjPFilebuff ajFilebuffNewFromFile(AjPFile file)
2980 {
2981     AjPFilebuff thys;
2982 
2983     if(!file)
2984         return NULL;
2985 
2986     AJNEW0(thys);
2987     thys->File = file;
2988 
2989     thys->Last = thys->Curr = thys->Prev = thys->Lines =  NULL;
2990     thys->Freelines = thys->Freelast = NULL;
2991     thys->Pos = thys->Size = 0;
2992 
2993     return thys;
2994 }
2995 
2996 
2997 
2998 
2999 /* @func ajFilebuffNewLine ****************************************************
3000 **
3001 ** Creates a new buffered input file object with no file but with
3002 ** one line of buffered data provided.
3003 **
3004 ** @param [r] line [const AjPStr] One line of buffered data.
3005 ** @return [AjPFilebuff] New buffered file object.
3006 **
3007 ** @release 6.0.0
3008 ** @@
3009 ******************************************************************************/
3010 
ajFilebuffNewLine(const AjPStr line)3011 AjPFilebuff ajFilebuffNewLine(const AjPStr line)
3012 {
3013     AjPFilebuff thys;
3014     AjPFile file;
3015 
3016     file = fileNew();
3017     file->End = ajTrue;
3018     ajDebug("EOF ajFilebuffNewLine file <none>\n");
3019 
3020     thys = ajFilebuffNewFromFile(file);
3021 
3022     thys->Lines = AJNEW0(thys->Last);
3023     ajStrAssignS(&thys->Last->Line,line);
3024 
3025     thys->Curr = thys->Lines;
3026     thys->Pos  = 0;
3027     thys->Size = 1;
3028 
3029     return thys;
3030 }
3031 
3032 
3033 
3034 
3035 /* @func ajFilebuffNewListinList **********************************************
3036 **
3037 ** Creates a new buffered file object from a list of filenames.
3038 **
3039 ** @param [u] list [AjPList] List of filenames as strings.
3040 ** @return [AjPFilebuff] New buffered file object.
3041 **
3042 ** @release 6.0.0
3043 ** @@
3044 ******************************************************************************/
3045 
ajFilebuffNewListinList(AjPList list)3046 AjPFilebuff ajFilebuffNewListinList(AjPList list)
3047 {
3048     AjPFile file;
3049 
3050     file = ajFileNewListinList(list);
3051 
3052     if(!file)
3053         return NULL;
3054 
3055     return ajFilebuffNewFromFile(file);
3056 }
3057 
3058 
3059 
3060 
3061 /* @func ajFilebuffNewNameS ***************************************************
3062 **
3063 ** Creates a new buffered input file object with an opened named file.
3064 **
3065 ** @param [r] name [const AjPStr] File name.
3066 ** @return [AjPFilebuff] New buffered file object.
3067 **
3068 ** @release 6.0.0
3069 ** @@
3070 ******************************************************************************/
3071 
ajFilebuffNewNameS(const AjPStr name)3072 AjPFilebuff ajFilebuffNewNameS(const AjPStr name)
3073 {
3074     AjPFile file;
3075 
3076     file = ajFileNewInNameS(name);
3077 
3078     return ajFilebuffNewFromFile(file);
3079 }
3080 
3081 
3082 
3083 
3084 /* @func ajFilebuffNewNamePathC ***********************************************
3085 **
3086 ** Opens directory "dir", finds and opens file "name"
3087 **
3088 ** @param [r] name [const char*] Filename.
3089 ** @param [r] path [const AjPStr] Directory. If empty uses current directory.
3090 ** @return [AjPFilebuff] New buffered file object.
3091 **
3092 ** @release 6.0.0
3093 ** @@
3094 ******************************************************************************/
3095 
ajFilebuffNewNamePathC(const char * name,const AjPStr path)3096 AjPFilebuff ajFilebuffNewNamePathC(const char* name, const AjPStr path)
3097 {
3098     if(ajStrGetLen(path))
3099         ajStrAssignS(&fileNameFix, path);
3100     else
3101         ajStrAssignC(&fileNameFix, CURRENT_DIR);
3102 
3103     if(ajStrGetCharLast(fileNameFix) != SLASH_CHAR)
3104         ajStrAppendC(&fileNameFix, SLASH_STRING);
3105 
3106     ajStrAppendC(&fileNameFix, name);
3107 
3108     return ajFilebuffNewNameS(fileNameFix);
3109 }
3110 
3111 
3112 
3113 
3114 /* @func ajFilebuffNewNamePathS ***********************************************
3115 **
3116 ** Opens directory "dir", finds and opens file "name"
3117 **
3118 ** @param [r] name [const AjPStr] Filename.
3119 ** @param [r] path [const AjPStr] Directory. If empty uses current directory.
3120 ** @return [AjPFilebuff] New buffered file object.
3121 **
3122 ** @release 6.0.0
3123 ** @@
3124 ******************************************************************************/
3125 
ajFilebuffNewNamePathS(const AjPStr name,const AjPStr path)3126 AjPFilebuff ajFilebuffNewNamePathS(const AjPStr name, const AjPStr path)
3127 {
3128     if(ajStrGetLen(path))
3129         ajStrAssignS(&fileNameFix, path);
3130     else
3131         ajStrAssignC(&fileNameFix, CURRENT_DIR);
3132 
3133     if(ajStrGetCharLast(fileNameFix) != SLASH_CHAR)
3134         ajStrAppendC(&fileNameFix, SLASH_STRING);
3135 
3136     ajStrAppendS(&fileNameFix, name);
3137 
3138     return ajFilebuffNewNameS(fileNameFix);
3139 }
3140 
3141 
3142 
3143 
3144 /* @func ajFilebuffNewNofile **************************************************
3145 **
3146 ** Creates a new buffered input file object with an undefined file
3147 ** to be used as a text buffer.
3148 **
3149 ** @return [AjPFilebuff] New buffered file object.
3150 **
3151 ** @release 6.0.0
3152 ** @@
3153 ******************************************************************************/
3154 
ajFilebuffNewNofile(void)3155 AjPFilebuff ajFilebuffNewNofile(void)
3156 {
3157     AjPFile file;
3158 
3159     file = fileNew();           /* dummy file */
3160 
3161     return ajFilebuffNewFromFile(file);
3162 }
3163 
3164 
3165 
3166 
3167 /* @func ajFilebuffNewPathWild ************************************************
3168 **
3169 ** Opens directory "dir"
3170 ** Looks for file(s) matching "file"
3171 ** Opens them as a list of files using a buffered file object.
3172 **
3173 ** @param [r] path [const AjPStr] Directory
3174 ** @param [r] wildname [const AjPStr] Wildcard filename.
3175 ** @return [AjPFilebuff] New buffered file object.
3176 **
3177 ** @release 6.0.0
3178 ** @@
3179 ******************************************************************************/
3180 
ajFilebuffNewPathWild(const AjPStr path,const AjPStr wildname)3181 AjPFilebuff ajFilebuffNewPathWild(const AjPStr path,
3182                                   const AjPStr wildname)
3183 {
3184     DIR* dp;
3185 #if defined(AJ_IRIXLF)
3186     struct dirent64 *de;
3187 #else /* !AJ_IRIXLF */
3188     struct dirent* de;
3189 #endif /* AJ_IRIXLF */
3190     ajint dirsize;
3191     AjPList list = NULL;
3192     AjPStr name  = NULL;
3193 #ifdef _POSIX_C_SOURCE
3194     char buf[sizeof(struct dirent)+MAXNAMLEN];
3195 #endif /* _POSIX_C_SOURCE */
3196 
3197     if(ajStrGetLen(path))
3198         ajStrAssignS(&fileDirfixTmp, path);
3199     else
3200         ajStrAssignC(&fileDirfixTmp, CURRENT_DIR);
3201 
3202     if(ajStrGetCharLast(fileDirfixTmp) != SLASH_CHAR)
3203         ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
3204 
3205     dp = fileOpenDir(&fileDirfixTmp);
3206 
3207     if(!dp)
3208         return NULL;
3209 
3210     dirsize = 0;
3211     list = ajListstrNew();
3212 
3213     while(
3214 #if defined(AJ_IRIXLF)
3215 #ifdef _POSIX_C_SOURCE
3216         !readdir64_r(dp,(struct dirent64 *)buf,&de)
3217 #else /* !_POSIX_C_SOURCE */
3218         (de=readdir64(dp))
3219 #endif /* _POSIX_C_SOURCE */
3220 #else /* !AJ_IRIXLF */
3221 #ifdef _POSIX_C_SOURCE
3222         !readdir_r(dp,(struct dirent *)buf,&de)
3223 #else /* !_POSIX_C_SOURCE */
3224         (de=readdir(dp))
3225 #endif /* _POSIX_C_SOURCE */
3226 #endif /* AJ_IRIXLF */
3227           )
3228     {
3229 #ifdef _POSIX_C_SOURCE
3230         if(!de)
3231             break;
3232 #endif /* _POSIX_C_SOURCE */
3233         /* skip deleted files with inode zero */
3234 #ifndef __CYGWIN__
3235         if(!de->d_ino)
3236             continue;
3237 #endif /* !__CYGWIN__ */
3238         if(ajCharMatchC(de->d_name, "."))
3239             continue;
3240 
3241         if(ajCharMatchC(de->d_name, ".."))
3242             continue;
3243 
3244         if(!ajCharMatchWildS(de->d_name, wildname))
3245             continue;
3246 
3247         dirsize++;
3248         ajDebug("accept '%s'\n", de->d_name);
3249         name = NULL;
3250         ajFmtPrintS(&name, "%S%s", fileDirfixTmp, de->d_name);
3251         ajListstrPushAppend(list, name);
3252     }
3253 
3254     closedir(dp);
3255     ajDebug("%d files for '%S' '%S'\n", dirsize, path, wildname);
3256 
3257     return ajFilebuffNewListinList(list);
3258 }
3259 
3260 
3261 
3262 
3263 /* @func ajFilebuffNewPathWildExclude *****************************************
3264 **
3265 ** Opens directory "dir"
3266 ** Looks for file(s) matching "file"
3267 ** Skip files matching excluded files wildcard
3268 ** Opens them as a list of files using a buffered file object.
3269 **
3270 ** @param [r] path [const AjPStr] Directory
3271 ** @param [r] wildname [const AjPStr] Wildcard filename.
3272 ** @param [r] exclude [const AjPStr] Wildcard excluded filename.
3273 ** @return [AjPFilebuff] New buffered file object.
3274 **
3275 ** @release 6.0.0
3276 ** @@
3277 ******************************************************************************/
3278 
ajFilebuffNewPathWildExclude(const AjPStr path,const AjPStr wildname,const AjPStr exclude)3279 AjPFilebuff ajFilebuffNewPathWildExclude(const AjPStr path,
3280                                          const AjPStr wildname,
3281                                          const AjPStr exclude)
3282 {
3283     DIR* dp;
3284 #if defined(AJ_IRIXLF)
3285     struct dirent64 *de;
3286 #else /* !AJ_IRIXLF */
3287     struct dirent* de;
3288 #endif /* AJ_IRIXLF */
3289     ajint dirsize;
3290     AjPList list = NULL;
3291     AjPStr name  = NULL;
3292 #ifdef _POSIX_C_SOURCE
3293     char buf[sizeof(struct dirent)+MAXNAMLEN];
3294 #endif /* _POSIX_C_SOURCE */
3295 
3296     ajDebug("ajFilebuffNewPathWildExclude "
3297             "path '%S' wildname '%S' exclude '%S\n",
3298             path, wildname, exclude);
3299 
3300     if(ajStrGetLen(path))
3301         ajStrAssignS(&fileDirfixTmp, path);
3302     else
3303         ajStrAssignC(&fileDirfixTmp, CURRENT_DIR);
3304 
3305     if(ajStrGetCharLast(fileDirfixTmp) != SLASH_CHAR)
3306         ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
3307 
3308     dp = fileOpenDir(&fileDirfixTmp);
3309 
3310     if(!dp)
3311         return NULL;
3312 
3313     dirsize = 0;
3314     list = ajListstrNew();
3315 
3316     while(
3317 #if defined(AJ_IRIXLF)
3318 #ifdef _POSIX_C_SOURCE
3319         !readdir64_r(dp,(struct dirent64 *)buf,&de)
3320 #else /* !_POSIX_C_SOURCE */
3321         (de=readdir64(dp))
3322 #endif /* _POSIX_C_SOURCE */
3323 #else /* !AJ_IRIXLF */
3324 #ifdef _POSIX_C_SOURCE
3325         !readdir_r(dp,(struct dirent *)buf,&de)
3326 #else /* !_POSIX_C_SOURCE */
3327         (de=readdir(dp))
3328 #endif /* _POSIX_C_SOURCE */
3329 #endif /* AJ_IRIXLF */
3330           )
3331     {
3332 #ifdef _POSIX_C_SOURCE
3333         if(!de)
3334             break;
3335 #endif /* _POSIX_C_SOURCE */
3336         /* skip deleted files with inode zero */
3337 #ifndef __CYGWIN__
3338         if(!de->d_ino)
3339             continue;
3340 #endif /* !__CYGWIN__ */
3341         if(ajCharMatchC(de->d_name, "."))
3342             continue;
3343 
3344         if(ajCharMatchC(de->d_name, ".."))
3345             continue;
3346 
3347         ajStrAssignC(&fileNameTmp, de->d_name);
3348         ajDebug("testing '%s'\n", de->d_name);
3349 
3350         if(!ajFilenameTestExclude(fileNameTmp, exclude, wildname))
3351             continue;
3352 
3353         dirsize++;
3354         ajDebug("accept '%s'\n", de->d_name);
3355         name = NULL;
3356         ajFmtPrintS(&name, "%S%s", fileDirfixTmp, de->d_name);
3357         ajListstrPushAppend(list, name);
3358     }
3359 
3360     closedir(dp);
3361     ajDebug("%d files for '%S' '%S'\n", dirsize, path, wildname);
3362     ajStrDelStatic(&fileNameTmp);
3363 
3364     return ajFilebuffNewListinList(list);
3365 }
3366 
3367 
3368 
3369 
3370 /* @funcstatic fileOpenDir ****************************************************
3371 **
3372 ** Runs 'opendir' on the specified directory. If the directory name
3373 ** has no trailing slash (on Unix) then one is added. This is why the
3374 ** directory name must be writable.
3375 **
3376 ** @param [u] dir [AjPStr*] Directory name.
3377 ** @return [DIR*] result of the opendir call.
3378 **
3379 ** @release 1.0.0
3380 ** @@
3381 ******************************************************************************/
3382 
fileOpenDir(AjPStr * dir)3383 static DIR* fileOpenDir(AjPStr* dir)
3384 {
3385     AjBool moved = ajFalse;
3386     AjPStr cwdpath = NULL;
3387     AjPStr userstr = NULL;
3388     AjPStr reststr = NULL;
3389     char *hdir = NULL;
3390 
3391     if(ajStrGetCharLast(*dir) != SLASH_CHAR)
3392         ajStrAppendC(dir, SLASH_STRING);
3393 
3394     /*  going up */
3395     while(ajStrPrefixC(*dir, UP_DIR))
3396     {
3397         if(!moved)
3398             cwdpath = ajStrNewS(ajFileValueCwd());
3399 
3400         moved = ajTrue;
3401         ajDirnameUp(&cwdpath);
3402         ajStrKeepRange(dir, 3, -1);
3403         ajDebug("Going up '%S' '%S'\n", *dir, fileCwd);
3404     }
3405 
3406     if(moved)
3407         ajStrInsertS(dir, 0, cwdpath);
3408 
3409     if(moved)
3410         ajStrDel(&cwdpath);
3411 
3412     ajStrAssignS(&fileNameTmp, *dir);
3413     if(ajStrGetCharFirst(fileNameTmp) == '~')
3414     {
3415         ajDebug("starts with '~'\n");
3416 
3417         if(!fileUserExp)
3418             fileUserExp = ajRegCompC("^~([^/\\\\]*)");
3419 
3420         ajRegExec(fileUserExp, fileNameTmp);
3421         ajRegSubI(fileUserExp, 1, &userstr);
3422         ajRegPost(fileUserExp, &reststr);
3423         ajDebug("  user: '%S' rest: '%S'\n", userstr, reststr);
3424 
3425         if(ajStrGetLen(userstr))
3426         {
3427             /* username specified */
3428             hdir = ajSysGetHomedirFromName(ajStrGetPtr(userstr));
3429 
3430             if(!hdir)
3431             {
3432                 ajStrDel(&userstr);
3433                 ajStrDelStatic(&fileNameTmp);
3434                 ajStrDel(&reststr);
3435 
3436                 return NULL;
3437             }
3438 
3439             ajFmtPrintS(&fileNameTmp, "%s%S", hdir, reststr);
3440             AJFREE(hdir);
3441 
3442             ajDebug("use getpwnam: '%S'\n", fileNameTmp);
3443         }
3444         else
3445         {
3446             /* just ~/ */
3447             hdir = ajSysGetHomedir();
3448 
3449             if(hdir)
3450             {
3451                 ajFmtPrintS(&fileNameTmp, "%s%S", hdir, reststr);
3452                 AJFREE(hdir);
3453             }
3454             else
3455                 ajFmtPrintS(&fileNameTmp,"%S",reststr);
3456 
3457             ajDebug("use HOME: '%S'\n", fileNameTmp);
3458         }
3459         ajStrAssignS(dir, fileNameTmp);
3460     }
3461 
3462     ajStrDel(&userstr);
3463     ajStrDel(&reststr);
3464 
3465     ajDebug("fileOpenDir opened '%S'\n", *dir);
3466 
3467     return opendir(ajStrGetPtr(*dir));
3468 }
3469 
3470 
3471 
3472 
3473 /* @section Buffered file destructors *****************************************
3474 **
3475 ** Destruction is achieved by closing the file.
3476 **
3477 ** Unlike ANSI C, there are tests to ensure a file is not closed twice.
3478 **
3479 ** @nam3rule Del Destructor
3480 **
3481 ** @argrule Del Pbuff [AjPFilebuff*] Buffered file to be deleted
3482 **
3483 ** @valrule * [void]
3484 **
3485 ** @fcategory delete
3486 **
3487 ** @fdata [AjPFilebuff]
3488 **
3489 ******************************************************************************/
3490 
3491 
3492 
3493 
3494 /* @func ajFilebuffDel ********************************************************
3495 **
3496 ** Destructor for a buffered file object.
3497 **
3498 ** @param [d] Pbuff [AjPFilebuff*] Buffered file object.
3499 ** @return [void]
3500 **
3501 ** @release 6.0.0
3502 ** @@
3503 ******************************************************************************/
3504 
ajFilebuffDel(AjPFilebuff * Pbuff)3505 void ajFilebuffDel(AjPFilebuff* Pbuff)
3506 {
3507     AjPFilebuff thys;
3508 
3509     if(!Pbuff)
3510         return;
3511 
3512     thys = *Pbuff;
3513 
3514     if(!thys)
3515         return;
3516 
3517     if(thys->File)
3518         ajDebug("ajFilebuffDel '%F' fp: %p size:%u\n",
3519                 thys->File, thys->File->fp, thys->Size);
3520 
3521     ajFilebuffClear(thys, -1);
3522     filebuffFreeClear(thys);
3523     ajFileClose(&thys->File);
3524     AJFREE(*Pbuff);
3525 
3526     return;
3527 }
3528 
3529 
3530 
3531 
3532 /* @section Buffered file reopen **********************************************
3533 **
3534 ** These functions close a file and open a new file with the same file object
3535 **
3536 ** @nam3rule Reopen Reopen an existing buffered file object
3537 ** @nam4rule File Reopen using a new file object
3538 **
3539 ** @argrule Reopen Pbuff [AjPFilebuff*] Buffered file object
3540 ** @argrule Reopen file [AjPFile] File object
3541 **
3542 ** @valrule * [AjBool] True on success
3543 **
3544 ** @fcategory modify
3545 **
3546 ** @fdata [AjPFilebuff]
3547 **
3548 ******************************************************************************/
3549 
3550 
3551 
3552 
3553 /* @func ajFilebuffReopenFile *************************************************
3554 **
3555 ** Sets buffered input file to use a new open file.
3556 **
3557 ** The AjPFile pointer is a clone, so we should simply overwrite
3558 ** whatever was there before, but we do need to clear the previous buffer
3559 ** contents.
3560 **
3561 ** @param [w] Pbuff [AjPFilebuff*] Buffered file object.
3562 ** @param [u] file [AjPFile] File object to be buffered.
3563 ** @return [AjBool] ajTrue on success
3564 **
3565 ** @release 6.0.0
3566 ** @@
3567 ******************************************************************************/
3568 
ajFilebuffReopenFile(AjPFilebuff * Pbuff,AjPFile file)3569 AjBool ajFilebuffReopenFile(AjPFilebuff* Pbuff, AjPFile file)
3570 {
3571     AjPFilebuff thys;
3572 
3573     if(!file)
3574     {
3575         ajFatal("used ajFilebuffReopenFile with deleted file buffer");
3576         ajFilebuffDel(Pbuff);
3577         return ajFalse;
3578     }
3579 
3580     if(!*Pbuff)
3581     {
3582         *Pbuff = ajFilebuffNewFromFile(file);
3583         thys = *Pbuff;
3584         return ajTrue;
3585     }
3586 
3587     thys = *Pbuff;
3588 
3589     ajFilebuffClear(thys, -1);
3590 
3591     thys->File = file;
3592 
3593     return ajTrue;
3594 }
3595 
3596 
3597 
3598 
3599 /* @section Buffered file modifiers *******************************************
3600 **
3601 ** These functions use the attributes of a buffered file object and
3602 ** update them.
3603 **
3604 ** @nam3rule Clear Removes processed lines from the buffer
3605 ** @nam3rule Fix Resets the pointer and current record of a file buffer
3606 **           after buffer contents have been edited
3607 ** @nam3rule Reset Reset buffered file attributes and contents.
3608 ** @nam3rule Set Set file attribute
3609 ** @nam4rule Pos Reset file pointer to start of buffer
3610 ** @nam5rule Buffered Set file unbuffered
3611 ** @nam4rule Buffered Set file buffered
3612 ** @nam4rule Unbuffered Set file unbuffered
3613 **
3614 ** @suffix Store Reset test store buffer
3615 **
3616 ** @argrule * buff [AjPFilebuff] Buffered input file object
3617 ** @argrule C line [const char*] Line of text
3618 ** @argrule S line [const AjPStr] Line of text
3619 ** @argrule Clear lines [ajint] Number of lines to retain
3620 **                              (-1 to clear whole buffer)
3621 ** @argrule ClearStore lastline [const AjPStr] Last line of input
3622 ** @argrule Store dostore [AjBool] If true, use the text store buffer
3623 ** @argrule Store Pstore [AjPStr*] Original text store buffer
3624 **
3625 ** @valrule * [void]
3626 ** @valrule *Set [AjBool] Previous buffer setting
3627 **
3628 ** @fcategory modify
3629 **
3630 ** @fdata [AjPFilebuff]
3631 **
3632 ******************************************************************************/
3633 
3634 
3635 
3636 
3637 /* @func ajFilebuffClear ******************************************************
3638 **
3639 ** Deletes processed lines from a file buffer. The buffer has a record
3640 ** (Pos) of the next unprocessed line in the buffer.
3641 **
3642 ** Unbuffered files need special handling. The buffer can be turned off
3643 ** while it still contains data. If so, we have to carefully run it down.
3644 ** If this runs it to zero, we may want to save the last line read.
3645 **
3646 ** @param [u] buff [AjPFilebuff] File buffer
3647 ** @param [r] lines [ajint] Number of lines to retain. -1 deletes everything.
3648 ** @return [void]
3649 **
3650 ** @release 6.0.0
3651 ** @@
3652 ******************************************************************************/
3653 
ajFilebuffClear(AjPFilebuff buff,ajint lines)3654 void ajFilebuffClear(AjPFilebuff buff, ajint lines)
3655 {
3656     ajint i = 0;
3657     AjPFilebufflist list;
3658     AjPFilebufflist next;
3659     ajint first;
3660     ajint ifree = 0;
3661 
3662     ajDebug("ajFilebuffClear (%d) Nobuff: %B size: %u\n",
3663             lines, buff->Nobuff, buff->Size);
3664     /*FilebuffTraceFull(buff, buff->Size, 100);*/
3665 
3666     if(!buff)
3667         return;
3668 
3669     if(!buff->File)
3670         return;
3671 
3672     if(lines < 0)
3673         first = buff->Size;
3674     else
3675         first = buff->Pos - lines;
3676 
3677     if(first < 0)
3678         first = 0;
3679 
3680     /* nobuff, and all read */
3681     if(buff->Nobuff && buff->Pos == buff->Size)
3682         /* delete any old saved line */
3683         first = buff->Pos;
3684 
3685     list = buff->Lines;
3686     for(i=0; i < first; i++)
3687     {
3688         /* we save one line at a time */
3689         next = list->Next;
3690         /* so keep a note of the next one for later */
3691         /*ajDebug("Try to reuse %x size: %d use: %d\n",
3692           list->Line, ajStrGetRes(list->Line), ajStrGetUse(list->Line));*/
3693 
3694         if(buff->Nobuff)
3695         {
3696             ajStrDel(&list->Line);
3697             AJFREE(list);            /* deleted, kill the list item */
3698         }
3699         else
3700         {
3701             if(ajStrDelStatic(&list->Line))
3702             {
3703                 /* move free line to the end */
3704 
3705                 /*ajDebug("can save to free list %x %d bytes\n",
3706                   list->Line, ajStrGetRes(list->Line));*/
3707 
3708                 ifree++;
3709                 /* just save the one line */
3710                 list->Next = NULL;
3711 
3712                 if(!buff->Freelines)
3713                 {
3714                     /* start a new free list */
3715                     buff->Freelines = list;
3716                     buff->Freelast = list;
3717                     /*ajDebug("start  list Free %x Freelast %x \n",
3718                       buff->Freelines, buff->Freelast);*/
3719                 }
3720                 else
3721                 {
3722                     /* append to free list */
3723                     buff->Freelast->Next = list;
3724                     buff->Freelast = buff->Freelast->Next;
3725                     /*ajDebug("append list Free %x Freelast %x \n",
3726                       buff->Freelines, buff->Freelast);*/
3727                 }
3728             }
3729             else
3730             {
3731                 ajDebug("ajStrDelReuse was false\n");
3732             }
3733         }
3734         list = next;
3735     }
3736 
3737     buff->Pos   = 0;
3738     buff->Size -= i;
3739 
3740 /*
3741 //    if(!buff->Size)
3742 //    {
3743 //      ajDebug("size 0: Lines: %x Curr: %x  Prev: %x Last: %x Free: "
3744 //                "%x Freelast: %x\n",
3745 //              buff->Lines, buff->Curr, buff->Prev, buff->Last,
3746 //              buff->Freelines, buff->Freelast);
3747 //    }
3748 */
3749 
3750     buff->Lines = buff->Curr = list;
3751 
3752 /*
3753 //    ajDebug("ajFilebuffClear '%F' (%d lines)\n"
3754 //           "     %b size: %d pos: %d removed %d lines add to free: %d\n",
3755 //           buff->File, lines, buff->Nobuff, buff->Size, buff->Pos, i, ifree);
3756 */
3757 
3758     /* ajFilebuffTrace(buff);*/
3759 
3760     if(buff->Nobuff && !buff->Size && lines == 1)
3761     {
3762         /* unbuffered - can only save last line */
3763         if(buff->Lines)
3764             ajFatal("Buffer error clearing unbuffered file "
3765                     "in ajFilebuffClear\n");
3766 
3767         buff->Lines = AJNEW0(buff->Last);
3768 
3769         ajStrAssignS(&buff->Last->Line, buff->File->Buff);
3770         buff->Curr = buff->Last;
3771         buff->Curr->Fpos = buff->Fpos;
3772         buff->Last->Next = NULL;
3773         buff->Pos = 0;
3774         buff->Size = 1;
3775     }
3776 
3777     return;
3778 }
3779 
3780 
3781 
3782 
3783 /* @func ajFilebuffClearStore *************************************************
3784 **
3785 ** Deletes processed lines from a file buffer. The buffer has a record
3786 ** (Pos) of the next unprocessed line in the buffer.
3787 **
3788 ** Unbuffered files need special handling. The buffer can be turned off
3789 ** while it still contains data. If so, we have to carefully run it down.
3790 ** If this runs it to zero, we may want to save the last line read.
3791 **
3792 ** @param [u] buff [AjPFilebuff] File buffer
3793 ** @param [r] lines [ajint] Number of lines to retain. -1 deletes everything.
3794 ** @param [r] lastline [const AjPStr] Last line of input.
3795 **                            Used to count characters to be saved
3796 ** @param [r] dostore [AjBool] append if true
3797 ** @param [w] Pstore [AjPStr*] Caller's record of the processed lines
3798 ** @return [void]
3799 **
3800 ** @release 6.0.0
3801 ** @@
3802 ******************************************************************************/
3803 
ajFilebuffClearStore(AjPFilebuff buff,ajint lines,const AjPStr lastline,AjBool dostore,AjPStr * Pstore)3804 void ajFilebuffClearStore(AjPFilebuff buff, ajint lines, const AjPStr lastline,
3805                           AjBool dostore, AjPStr *Pstore)
3806 {
3807     ajFilebuffClear(buff, lines);
3808 
3809     if(dostore && ajStrGetLen(lastline))
3810         ajStrCutEnd(Pstore, ajStrGetLen(lastline));
3811 
3812     return;
3813 }
3814 
3815 
3816 
3817 
3818 /* @func ajFilebuffFix ********************************************************
3819 **
3820 ** Resets the pointer and current record of a file buffer so the next
3821 ** read starts at the first buffered line. Fixes buffer size after the
3822 ** buffer has been edited.
3823 **
3824 ** @param [u] buff [AjPFilebuff] File buffer
3825 ** @return [void]
3826 **
3827 ** @release 6.0.0
3828 ** @@
3829 ******************************************************************************/
3830 
ajFilebuffFix(AjPFilebuff buff)3831 void ajFilebuffFix(AjPFilebuff buff)
3832 {
3833     AjPFilebufflist list;
3834     ajint i = 1;
3835 
3836     ajFilebuffReset(buff);
3837     buff->Pos  = 0;
3838     buff->Curr = buff->Lines;
3839 
3840     list = buff->Lines;
3841 
3842     if(!list)
3843     {
3844         buff->Size = 0;
3845         return;
3846     }
3847 
3848     while(list->Next)
3849     {
3850         i++;
3851         list = list->Next;
3852     }
3853 
3854     if(i != buff->Size)
3855         ajDebug("ajFilebuffFix size was %d now %d\n", buff->Size, i);
3856 
3857     buff->Size=i;
3858     return;
3859 }
3860 
3861 
3862 
3863 
3864 /* @func ajFilebuffReset ******************************************************
3865 **
3866 ** Resets the pointer and current record of a file buffer so the next read
3867 ** starts at the first buffered line.
3868 **
3869 ** @param [u] buff [AjPFilebuff] File buffer
3870 ** @return [void]
3871 **
3872 ** @release 6.0.0
3873 ** @@
3874 ******************************************************************************/
3875 
ajFilebuffReset(AjPFilebuff buff)3876 void ajFilebuffReset(AjPFilebuff buff)
3877 {
3878     ajDebug("ajFilebuffReset '%F' size: %u\n", buff->File, buff->Size);
3879     buff->Pos  = 0;
3880     buff->Curr = buff->Lines;
3881     buff->Prev = NULL;
3882 
3883     return;
3884 }
3885 
3886 
3887 
3888 
3889 /* @func ajFilebuffResetPos ***************************************************
3890 **
3891 ** Resets the pointer and current record of a file buffer so the next read
3892 ** starts at the first buffered line.
3893 **
3894 ** Also resets the file position to the last known read, to undo the
3895 ** damage done by (for example) ajseqabi functions.
3896 **
3897 ** @param [u] buff [AjPFilebuff] File buffer
3898 ** @return [void]
3899 **
3900 ** @release 6.0.0
3901 ** @@
3902 ******************************************************************************/
3903 
ajFilebuffResetPos(AjPFilebuff buff)3904 void ajFilebuffResetPos(AjPFilebuff buff)
3905 {
3906     ajDebug("ajFilebuffResetPos   End: %B  Fpos: %ld ftell: %ld\n",
3907             buff->File->End, buff->Fpos, ftell(buff->File->fp));
3908     /*ajFilebuffTraceFull(buff, 10, 10);*/
3909 
3910     buff->Pos  = 0;
3911     buff->Curr = buff->Lines;
3912 
3913     if(!buff->File->End && (buff->File->fp != stdin))
3914         ajFileSeek(buff->File, buff->File->Filepos, SEEK_SET);
3915 
3916     buff->File->Filepos = buff->Fpos;
3917 
3918     /*ajFilebuffTraceFull(buff,10,10);*/
3919 
3920     return;
3921 }
3922 
3923 
3924 
3925 
3926 /* @func ajFilebuffResetStore *************************************************
3927 **
3928 ** Resets the pointer and current record of a file buffer so the next read
3929 ** starts at the first buffered line.
3930 **
3931 ** @param [u] buff [AjPFilebuff] File buffer
3932 ** @param [r] dostore [AjBool] True if text is stored
3933 ** @param [w] Pstore [AjPStr*] Stored string cleared if store is true
3934 ** @return [void]
3935 **
3936 ** @release 6.0.0
3937 ** @@
3938 ******************************************************************************/
3939 
ajFilebuffResetStore(AjPFilebuff buff,AjBool dostore,AjPStr * Pstore)3940 void ajFilebuffResetStore(AjPFilebuff buff, AjBool dostore, AjPStr *Pstore)
3941 {
3942     ajFilebuffReset(buff);
3943 
3944     if(dostore)
3945         ajStrAssignClear(Pstore);
3946 
3947     return;
3948 }
3949 
3950 
3951 
3952 
3953 /* @funcstatic filebuffFreeClear **********************************************
3954 **
3955 ** Deletes freed lines from a file buffer. The free list is used to avoid
3956 ** reallocating space for new records and must be deleted as part of
3957 ** the destructor.
3958 **
3959 ** @param [u] buff [AjPFilebuff] File buffer
3960 ** @return [void]
3961 **
3962 ** @release 6.0.0
3963 ** @@
3964 ******************************************************************************/
3965 
filebuffFreeClear(AjPFilebuff buff)3966 static void filebuffFreeClear(AjPFilebuff buff)
3967 {
3968     AjPFilebufflist list;
3969 
3970     if(!buff)
3971         return;
3972 
3973     /*ajDebug("filebuffFreeClear %x\n", buff->Freelines);*/
3974 
3975     while(buff->Freelines)
3976     {
3977         list = buff->Freelines;
3978         buff->Freelines = buff->Freelines->Next;
3979         ajStrDel(&list->Line);
3980         AJFREE(list);
3981     }
3982 
3983     return;
3984 }
3985 
3986 
3987 
3988 
3989 /* @func ajFilebuffSetBuffered ************************************************
3990 **
3991 ** Sets file to be buffered. If it already has buffered data, we have to
3992 ** first run down the buffer.
3993 **
3994 ** @param [u] buff [AjPFilebuff] Buffered file object.
3995 ** @return [AjBool] ajTrue if the file was unbuffered before
3996 **
3997 ** @release 6.0.0
3998 ** @@
3999 ******************************************************************************/
4000 
ajFilebuffSetBuffered(AjPFilebuff buff)4001 AjBool ajFilebuffSetBuffered(AjPFilebuff buff)
4002 {
4003     AjBool ret;
4004 
4005     if(!buff)
4006         return ajFalse;
4007 
4008     ret = buff->Nobuff;
4009     ajDebug("ajFilebuffSetBuffered %F buffsize: %d\n",
4010             buff->File, buff->Size);
4011     buff->Nobuff = ajFalse;
4012 
4013     return ret;
4014 }
4015 
4016 
4017 
4018 
4019 /* @func ajFilebuffSetUnbuffered **********************************************
4020 **
4021 ** Sets file to be unbuffered. If it already has buffered data, we have to
4022 ** first run down the buffer.
4023 **
4024 ** @param [u] buff [AjPFilebuff] Buffered file object.
4025 ** @return [AjBool] ajTrue if the file was unbuffered before
4026 **
4027 ** @release 6.0.0
4028 ** @@
4029 ******************************************************************************/
4030 
ajFilebuffSetUnbuffered(AjPFilebuff buff)4031 AjBool ajFilebuffSetUnbuffered(AjPFilebuff buff)
4032 {
4033     AjBool ret;
4034 
4035     if(!buff)
4036         return ajFalse;
4037 
4038     ret = buff->Nobuff;
4039     ajDebug("ajFilebuffSetUnbuffered '%F' fsize: %d\n", buff->File, buff->Size);
4040     buff->Nobuff = ajTrue;
4041 
4042     return ret;
4043 }
4044 
4045 
4046 
4047 
4048 /* @section Buffered file content modifiers ***********************************
4049 **
4050 ** These functions use the buffer contents of a buffered file object
4051 ** and update them.
4052 **
4053 ** @nam3rule Html Modify HTML tags in the buffer
4054 ** @nam4rule HtmlPre Reduce to a pre-formatted section if found in HTML
4055 ** @nam4rule HtmlNoheader Remove HTML header in the buffer
4056 ** @nam4rule HtmlStrip Remove all HTML tags in the buffer
4057 ** @nam3rule Load Add text to the buffer
4058 ** @nam4rule LoadAll Read all file lines into buffer
4059 ** @nam4rule Readurl Replace buffer with results from a URL
4060 **
4061 ** @suffix C Character string text
4062 ** @suffix S String object text
4063 **
4064 ** @argrule * buff [AjPFilebuff] Buffered file object
4065 ** @argrule C line [const char*] Line of text
4066 ** @argrule S line [const AjPStr] Line of text
4067 ** @argrule Readurl url [const AjPStr] URL to be read
4068 **
4069 ** @valrule * [void]
4070 ** @valrule *Noheader [ajuint] HTTP error code
4071 ** @valrule *HtmlPre [AjBool] True if changed
4072 ** @valrule *Readurl [AjBool] True on success
4073 **
4074 ** @fcategory modify
4075 **
4076 ** @fdata [AjPFilebuff]
4077 **
4078 ******************************************************************************/
4079 
4080 
4081 
4082 
4083 /* @func ajFilebuffHtmlNoheader ***********************************************
4084 **
4085 ** Processes data in the file buffer, removing HTML titles and
4086 ** decoding possible chunked input
4087 **
4088 ** @param [u] buff [AjPFilebuff] Buffered file with data loaded
4089 **                                     in the buffer.
4090 ** @return [ajuint] HTTP error code
4091 **
4092 ** @release 6.2.0
4093 ** @@
4094 ******************************************************************************/
4095 
ajFilebuffHtmlNoheader(AjPFilebuff buff)4096 ajuint ajFilebuffHtmlNoheader(AjPFilebuff buff)
4097 {
4098     AjPRegexp httpexp  = NULL;
4099     AjPRegexp nullexp  = NULL;
4100     AjPRegexp chunkexp = NULL;
4101     AjPRegexp hexexp   = NULL;
4102     AjPRegexp redirexp = NULL;
4103 
4104     AjBool doChunk = ajFalse;
4105     ajint ichunk;
4106     ajint chunkSize;
4107     ajint iline;
4108     AjPStr saveLine = NULL;
4109     AjPStr hexstr   = NULL;
4110     AjPStr codestr = NULL;
4111     AjPStr newurl = NULL;
4112     ajuint httpcode = 0;
4113 
4114     AjBool isheader = ajFalse;
4115 
4116     /* first take out the HTTP header (HTTP 1.0 onwards) */
4117     if(!buff || !buff->Size)
4118         return 0;
4119 
4120     httpexp  = ajRegCompC("^HTTP/\\S+\\s+(\\d+)");
4121     nullexp  = ajRegCompC("^\r?\n?$");
4122 
4123     /*ajFilebuffTraceTitle(buff, "Before ajFilebuffHtmlNoheader");*/
4124 
4125 
4126     ajDebug("ajFilebuffHtmlNoheader: First line [%d] '%S' \n",
4127             ajStrGetUse(buff->Curr->Line), buff->Curr->Line);
4128 
4129     if(ajRegExec(httpexp, buff->Curr->Line))
4130     {
4131         isheader = ajTrue;
4132         ajRegSubI(httpexp, 1, &codestr);
4133         ajStrToUint(codestr, &httpcode);
4134         ajStrDel(&codestr);
4135         fileBuffLineDel(buff);
4136     }
4137 
4138     if(isheader)
4139     {
4140         /*
4141          * ajHttpRedirect() function should be called
4142          * before calling this function to follow redirections
4143          * rather than using http redirection support here
4144          */
4145         if(httpcode >= 301 && httpcode <= 302)
4146         {
4147             redirexp = ajRegCompC("^Location: (\\S+)");
4148 
4149             while(buff->Pos < buff->Size &&
4150                   !ajRegExec(nullexp, buff->Curr->Line))
4151             {
4152                 /* to empty line */
4153                 if(ajRegExec(redirexp, buff->Curr->Line))
4154                 {
4155                     ajRegSubI(redirexp, 1, &newurl);
4156 
4157                     ajRegFree(&httpexp);
4158                     ajRegFree(&nullexp);
4159                     ajRegFree(&redirexp);
4160 
4161                     ajFilebuffClear(buff, -1);
4162                     ajFileClose(&buff->File);
4163 
4164                     ajFilebuffLoadReadurl(buff, newurl);
4165 
4166                     ajStrDel(&newurl);
4167 
4168                     return ajFilebuffHtmlNoheader(buff);
4169                 }
4170 
4171                 fileBuffLineDel(buff);
4172             }
4173 
4174             /* blank line after header */
4175             fileBuffLineDel(buff);
4176             ajRegFree(&redirexp);
4177         }
4178         else
4179         {
4180 /* HTTP  header processing */
4181             if(httpcode >= 300)
4182             {
4183                 ajWarn("HTTP code %u", httpcode);
4184                 ajRegFree(&httpexp);
4185                 ajRegFree(&nullexp);
4186                 return httpcode;
4187             }
4188 
4189             chunkexp = ajRegCompC("^Transfer-Encoding: +chunked");
4190             while(buff->Pos < buff->Size &&
4191                   !ajRegExec(nullexp, buff->Curr->Line))
4192             {
4193                 if(ajRegExec(chunkexp, buff->Curr->Line))
4194                 {
4195                     ajDebug("Chunk encoding: %S", buff->Curr->Line);
4196                     /* chunked - see later */
4197                     doChunk = ajTrue;
4198                 }
4199 
4200                 fileBuffLineDel(buff);
4201             }
4202 
4203             /* blank line after header */
4204             fileBuffLineDel(buff);
4205             ajRegFree(&chunkexp);
4206         }
4207     }
4208 
4209     if(doChunk)
4210     {
4211         /*ajFilebuffTraceFull(buff, 999999, 0);*/
4212 
4213         hexexp   = ajRegCompC("^([0-9a-fA-F]+) *\r?\n?$");
4214         if(!ajRegExec(hexexp, buff->Curr->Line))
4215         {
4216             ajFatal("Bad chunk data from HTTP, expect chunk size got '%S'",
4217                     buff->Curr->Line);
4218         }
4219 
4220         ajRegSubI(hexexp, 1, &hexstr);
4221         ajStrToHex(hexstr, &chunkSize);
4222 
4223         ajDebug("chunkSize hex:%x %d\n", chunkSize, chunkSize);
4224         fileBuffLineDel(buff);  /* chunk size */
4225 
4226         ichunk = 0;
4227         iline = 0;
4228 
4229         while(chunkSize && buff->Curr)
4230         {
4231             iline++;
4232             /* get the chunk size - zero is the end */
4233             /* process the chunk */
4234             ichunk += ajStrGetLen(buff->Curr->Line);
4235 
4236             /*ajDebug("++input line [%d] ichunk=%d:%d %d:%S",
4237               iline, ichunk, chunkSize,
4238               ajStrGetLen(buff->Curr->Line), buff->Curr->Line);*/
4239 
4240             if(ichunk >= chunkSize)     /* end of chunk */
4241             {
4242                 if(ichunk == chunkSize)
4243                 {
4244                     /* end-of-chunk at end-of-line */
4245                     fileBuffLineNext(buff);
4246                     ajStrAssignClear(&saveLine);
4247                     /*ajDebug("end-of-chunk at end-of-line: '%S'\n",
4248                       saveLine);*/
4249                 }
4250                 else
4251                 {
4252                     /* end-of-chunk in mid-line, patch up the input */
4253                     ajDebug("end-of-chunk in mid-line, %d:%d have input size:"
4254                             " %d\n",
4255                             ichunk, chunkSize,
4256                             ajStrGetLen(buff->Curr->Line));
4257                     ajStrAssignSubS(&saveLine, buff->Curr->Line, 0,
4258                                     -(ichunk-chunkSize+1));
4259                     ajStrKeepRange(&buff->Curr->Line, -(ichunk-chunkSize), -1);
4260                 }
4261 
4262                 /* skip a blank line */
4263 
4264                 if(!ajRegExec(nullexp, buff->Curr->Line))
4265                 {
4266                     ajFilebuffTraceTitle(buff, "Blank line not found");
4267                     ajFatal("Bad chunk data from HTTP, expect blank line"
4268                             " got '%S'", buff->Curr->Line);
4269                 }
4270 
4271                 fileBuffLineDel(buff);
4272 
4273                 /** read the next chunk size */
4274 
4275                 if(!ajRegExec(hexexp, buff->Curr->Line))
4276                 {
4277                     ajFilebuffTraceTitle(buff, "Chunk size not found");
4278                     ajFatal("Bad chunk data from HTTP, expect chunk size "
4279                             "got '%S'",
4280                             buff->Curr->Line);
4281                 }
4282 
4283                 ajRegSubI(hexexp, 1, &hexstr);
4284                 ajStrToHex(hexstr, &chunkSize);
4285                 ichunk = 0;
4286                 fileBuffLineDel(buff);
4287             }
4288 
4289             if(saveLine)
4290             {
4291                 if(ajStrGetLen(saveLine))
4292                 {
4293                     ichunk = ajStrGetLen(buff->Curr->Line);
4294                     ajDebug("curr-line/chunk: '%S'\n", buff->Curr->Line);
4295                     /* preserve the line split by chunk size */
4296                     ajStrInsertS(&buff->Curr->Line, 0, saveLine);
4297 
4298                     if(ichunk < chunkSize)
4299                     {
4300                         /* process the next line */
4301                         fileBuffLineNext(buff); /* after restored line */
4302                     }
4303                     else
4304                     {
4305                         /* we already have the whole chunk! */
4306                         ichunk -= ajStrGetLen(buff->Curr->Line);
4307                     }
4308                 }
4309                 else
4310                 {
4311                     /* just a chunk size, skip */
4312                     if(buff->Curr && chunkSize)
4313                     {
4314                         /*fileBuffLineDel(buff);*/
4315                     }
4316                     else if (chunkSize)/* final non-zero chunk size */
4317                     {
4318                         fileBuffLineDel(buff);
4319                     }
4320                 }
4321 
4322                 ajStrDel(&saveLine);
4323             }
4324             else
4325             {
4326                 /* next line */
4327                 fileBuffLineNext(buff);
4328             }
4329         }
4330 
4331         ajFilebuffFix(buff);
4332         /*ajFilebuffTraceFull(buff, 999999, 0);*/
4333         ajStrDel(&hexstr);
4334         /*ajFilebuffTraceTitle(buff, "Chunks resolved");*/
4335     }
4336 
4337     ajFilebuffReset(buff);
4338 
4339     ajRegFree(&httpexp);
4340     ajRegFree(&nullexp);
4341     ajRegFree(&hexexp);
4342 
4343     return 0;
4344 }
4345 
4346 
4347 
4348 
4349 /* @func ajFilebuffHtmlPre ****************************************************
4350 **
4351 ** If we only have one pre-formatted section in HTML, that is all we keep.
4352 **
4353 ** @param [u] buff [AjPFilebuff] buffer
4354 ** @return [AjBool] ajTrue=cleaned ajFalse=unchanged
4355 **
4356 ** @release 6.0.0
4357 ** @@
4358 ******************************************************************************/
4359 
ajFilebuffHtmlPre(AjPFilebuff buff)4360 AjBool ajFilebuffHtmlPre(AjPFilebuff buff)
4361 {
4362     AjPFilebufflist lptr    = NULL;
4363     AjPFilebufflist tptr    = NULL;
4364     AjPRegexp preexp = NULL;
4365     AjPRegexp endexp = NULL;
4366     ajint ifound = 0;
4367 
4368     lptr = buff->Curr;
4369 
4370     preexp = ajRegCompC("<[Pp][Rr][Ee]>");
4371 
4372     lptr=buff->Curr;
4373 
4374     ajDebug("ajFilebuffHtmlPre testing for <pre> line(s)\n");
4375 
4376     while(lptr)
4377     {
4378         if(ajRegExec(preexp, lptr->Line))
4379             ifound++;
4380 
4381         lptr = lptr->Next;
4382     }
4383 
4384     if(!ifound)
4385     {
4386         ajRegFree(&preexp);
4387 
4388         return ajFalse;
4389     }
4390 
4391     if (ifound > 1)
4392     {
4393         ajRegFree(&preexp);
4394 
4395         return ajFalse;
4396     }
4397 
4398     lptr=buff->Curr;
4399 
4400 
4401     while(lptr && !ajRegExec(preexp, lptr->Line))
4402     {
4403         tptr = lptr;
4404         lptr = lptr->Next;
4405         ajStrDel(&tptr->Line);
4406         AJFREE(tptr);
4407         buff->Size--;
4408     }
4409 
4410     buff->Lines = buff->Curr = lptr;
4411     ajRegPost(preexp, &lptr->Line);
4412     ajRegFree(&preexp);
4413 
4414     endexp = ajRegCompC("</[Pp][Rr][Ee]>");
4415 
4416     while(lptr && !ajRegExec(endexp,lptr->Line))
4417     {
4418         lptr    = lptr->Next;
4419     }
4420 
4421     ajRegPre(endexp, &lptr->Line);
4422     buff->Last = lptr;
4423     lptr = lptr->Next;
4424     ajRegFree(&endexp);
4425 
4426     while(lptr)
4427     {
4428         tptr = lptr;
4429         lptr = lptr->Next;
4430         ajStrDel(&tptr->Line);
4431         AJFREE(tptr);
4432         buff->Size--;
4433     }
4434 
4435     buff->Last->Next = NULL;
4436     ajFilebuffReset(buff);
4437     ajFilebuffTraceTitle(buff, "ajFilebuffHtmlPre completed");
4438 
4439     return ajTrue;
4440 }
4441 
4442 
4443 
4444 
4445 /* @func ajFilebuffHtmlStrip **************************************************
4446 **
4447 ** Processes data in the file buffer, removing HTML tokens between
4448 ** angle brackets, plus any TITLE. This seems to be enough to make HTML
4449 ** output readable.
4450 **
4451 ** @param [u] buff [AjPFilebuff] Buffered file with data loaded
4452 **                                     in the buffer.
4453 ** @return [void]
4454 **
4455 ** @release 6.0.0
4456 ** @@
4457 ******************************************************************************/
4458 
ajFilebuffHtmlStrip(AjPFilebuff buff)4459 void ajFilebuffHtmlStrip(AjPFilebuff buff)
4460 {
4461     AjPRegexp tagexp   = NULL;
4462     AjPRegexp fullexp  = NULL;
4463     AjPRegexp httpexp  = NULL;
4464     AjPRegexp nullexp  = NULL;
4465     AjPRegexp chunkexp = NULL;
4466     AjPRegexp hexexp   = NULL;
4467     AjPRegexp ncbiexp  = NULL;
4468     AjPRegexp ncbiexp2 = NULL;
4469     AjPRegexp srsdbexp = NULL;
4470 
4471     AjPStr s1 = NULL;
4472     AjPStr s2 = NULL;
4473     AjPStr s3 = NULL;
4474     ajint i;
4475     AjBool doChunk = ajFalse;
4476     ajint ichunk;
4477     ajint chunkSize;
4478     ajint iline;
4479     AjPStr saveLine = NULL;
4480     AjPStr hexstr   = NULL;
4481 
4482     /* first take out the HTTP header (HTTP 1.0 onwards) */
4483     if(!buff->Size)
4484         return;
4485 
4486     tagexp   = ajRegCompC("^(.*)(<[!/A-Za-z][^>]*>)(.*)$");
4487     fullexp  = ajRegCompC("^(.*)(<([A-Za-z]+)[^>]*>.*</\\3>)(.*)$");
4488     httpexp  = ajRegCompC("^HTTP/");
4489     nullexp  = ajRegCompC("^\r?\n?$");
4490     chunkexp = ajRegCompC("^Transfer-Encoding: +chunked");
4491     hexexp   = ajRegCompC("^([0-9a-fA-F]+) *\r?\n?$");
4492     ncbiexp  = ajRegCompC("^Entrez Reports\r?\n$");
4493     ncbiexp2 = ajRegCompC("^----------------\r?\n$");
4494     srsdbexp = ajRegCompC("^([A-Za-z0-9_-]+)(:)([A-Za-z0-9_-]+)");
4495 
4496 /*    ajFilebuffTraceTitle(buff, "Before ajFilebuffHtmlStrip");*/
4497 
4498     i = 0;
4499 
4500     /* ajDebug("First line [%d] '%S' \n",
4501        ajStrGetUse(buff->Curr->Line), buff->Curr->Line);*/
4502 
4503     if(ajRegExec(httpexp, buff->Curr->Line))
4504     {
4505         /* ^HTTP  header processing */
4506         while(buff->Pos < buff->Size &&
4507               !ajRegExec(nullexp, buff->Curr->Line))
4508         {
4509             /* to empty line */
4510             if(ajRegExec(chunkexp, buff->Curr->Line))
4511             {
4512                 /*ajDebug("Chunk encoding: %S", buff->Curr->Line);*/
4513                 /* chunked - see later */
4514                 doChunk = ajTrue;
4515             }
4516             fileBuffLineDel(buff);
4517         }
4518 
4519         /* blank line after header */
4520         fileBuffLineDel(buff);
4521     }
4522 
4523     if(doChunk)
4524     {
4525         /*ajFilebuffTraceFull(buff, 999999, 0);*/
4526 
4527         if(!ajRegExec(hexexp, buff->Curr->Line))
4528         {
4529             ajFatal("Bad chunk data from HTTP, expect chunk size got '%S'",
4530                     buff->Curr->Line);
4531         }
4532 
4533         ajRegSubI(hexexp, 1, &hexstr);
4534         ajStrToHex(hexstr, &chunkSize);
4535 
4536         /*ajDebug("chunkSize hex:%x %d\n", chunkSize, chunkSize);*/
4537         fileBuffLineDel(buff);  /* chunk size */
4538 
4539         ichunk = 0;
4540         iline = 0;
4541 
4542         while(chunkSize && buff->Curr)
4543         {
4544             iline++;
4545             /* get the chunk size - zero is the end */
4546             /* process the chunk */
4547             ichunk += ajStrGetLen(buff->Curr->Line);
4548 
4549             /*ajDebug("++input line [%d] ichunk=%d:%d %d:%S",
4550               iline, ichunk, chunkSize,
4551               ajStrGetLen(buff->Curr->Line), buff->Curr->Line);*/
4552 
4553             if(ichunk >= chunkSize)     /* end of chunk */
4554             {
4555                 if(ichunk == chunkSize)
4556                 {
4557                     /* end-of-chunk at end-of-line */
4558                     fileBuffLineNext(buff);
4559                     ajStrAssignClear(&saveLine);
4560                     /*ajDebug("end-of-chunk at end-of-line: '%S'\n",
4561                       saveLine); */
4562                 }
4563                 else
4564                 {
4565                     /* end-of-chunk in mid-line, patch up the input */
4566                     /*ajDebug("end-of-chunk in mid-line, %d:%d have input: "
4567                       "%d '%S'\n",
4568                       ichunk, chunkSize,
4569                       ajStrGetLen(buff->Curr->Line),
4570                       buff->Curr->Line);*/
4571                     ajStrAssignSubS(&saveLine, buff->Curr->Line, 0,
4572                                     -(ichunk-chunkSize+1));
4573                     ajStrKeepRange(&buff->Curr->Line, -(ichunk-chunkSize), -1);
4574                 }
4575 
4576                 /* skip a blank line */
4577 
4578                 if(!ajRegExec(nullexp, buff->Curr->Line))
4579                 {
4580                     ajFilebuffTraceTitle(buff, "Blank line not found");
4581                     ajFatal("Bad chunk data from HTTP, expect blank line"
4582                             " got '%S'", buff->Curr->Line);
4583                 }
4584 
4585                 fileBuffLineDel(buff);
4586 
4587                 /** read the next chunk size */
4588 
4589                 if(!ajRegExec(hexexp, buff->Curr->Line))
4590                 {
4591                     ajFilebuffTraceTitle(buff, "Chunk size not found");
4592                     ajFatal("Bad chunk data from HTTP, expect chunk size "
4593                             "got '%S'",
4594                             buff->Curr->Line);
4595                 }
4596 
4597                 ajRegSubI(hexexp, 1, &hexstr);
4598                 ajStrToHex(hexstr, &chunkSize);
4599                 ichunk = 0;
4600                 fileBuffLineDel(buff);
4601             }
4602 
4603             if(saveLine)
4604             {
4605                 if(ajStrGetLen(saveLine))
4606                 {
4607                     ichunk = ajStrGetLen(buff->Curr->Line);
4608                     /* preserve the line split by chunk size */
4609                     ajStrInsertS(&buff->Curr->Line, 0, saveLine);
4610 
4611                     if(ichunk < chunkSize)
4612                     {
4613                         /* process the next line */
4614                         fileBuffLineNext(buff); /* after restored line */
4615                     }
4616                     else
4617                     {
4618                         /* we already have the whole chunk! */
4619                         ichunk -= ajStrGetLen(buff->Curr->Line);
4620                     }
4621                 }
4622                 else
4623                 {
4624                     /* just a chunk size, skip */
4625                     if(buff->Curr && chunkSize)
4626                     {
4627                         /*fileBuffLineDel(buff);*/
4628                     }
4629                     else if (chunkSize)/* final non-zero chunk size */
4630                     {
4631                         fileBuffLineDel(buff);
4632                     }
4633                 }
4634 
4635                 ajStrDel(&saveLine);
4636             }
4637             else
4638             {
4639                 /* next line */
4640                 fileBuffLineNext(buff);
4641             }
4642         }
4643 
4644         ajFilebuffFix(buff);
4645         /*ajFilebuffTraceFull(buff, 999999, 0);*/
4646         ajStrDel(&hexstr);
4647         /*ajFilebuffTraceTitle(buff, "Chunks resolved");*/
4648     }
4649 
4650     ajFilebuffReset(buff);
4651 
4652     /*
4653     ** Now we have a clean single file to process
4654     */
4655 
4656     /*ajFilebuffTraceTitle(buff, "About to preprocess");*/
4657     ajFilebuffHtmlPre(buff);
4658 
4659     while(buff->Curr)
4660     {
4661         if(ajRegExec(ncbiexp, buff->Curr->Line))
4662             ajStrAssignC(&buff->Curr->Line, "\n");
4663 
4664         if(ajRegExec(ncbiexp2, buff->Curr->Line))
4665             ajStrAssignC(&buff->Curr->Line, "\n");
4666 
4667         while(ajRegExec(fullexp, buff->Curr->Line))
4668         {
4669             ajRegSubI(fullexp, 1, &s1);
4670             ajRegSubI(fullexp, 2, &s2);
4671             ajRegSubI(fullexp, 4, &s3);
4672             ajFmtPrintS(&buff->Curr->Line, "%S%S", s1, s3);
4673         }
4674 
4675         while(ajRegExec(tagexp, buff->Curr->Line))
4676         {
4677             ajRegSubI(tagexp, 1, &s1);
4678             ajRegSubI(tagexp, 2, &s2);
4679             ajRegSubI(tagexp, 3, &s3);
4680             ajFmtPrintS(&buff->Curr->Line, "%S%S", s1, s3);
4681         }
4682 
4683         if(ajRegExec(srsdbexp, buff->Curr->Line))
4684         {
4685             ajRegSubI(srsdbexp,1,&s1);
4686             ajRegSubI(srsdbexp,2,&s2);
4687             ajRegSubI(srsdbexp,3,&s3);
4688             fileBuffLineDel(buff);
4689             ++i;
4690             continue;
4691         }
4692 
4693         if(ajRegExec(nullexp, buff->Curr->Line))
4694         {
4695             /* allow for newline */
4696             fileBuffLineDel(buff);
4697         }
4698         else
4699             fileBuffLineNext(buff);
4700 
4701         i++;
4702     }
4703 
4704     ajFilebuffReset(buff);
4705 
4706     ajStrDel(&s1);
4707     ajStrDel(&s2);
4708     ajStrDel(&s3);
4709 
4710     /* free the regular expressions - we expect to use them once only */
4711 
4712     ajRegFree(&tagexp);
4713     ajRegFree(&fullexp);
4714     ajRegFree(&httpexp);
4715     ajRegFree(&nullexp);
4716     ajRegFree(&chunkexp);
4717     ajRegFree(&hexexp);
4718     ajRegFree(&ncbiexp);
4719     ajRegFree(&ncbiexp2);
4720     ajRegFree(&srsdbexp);
4721 
4722     /*ajFilebuffTraceTitle(buff, "After ajFilebuffHtmlStrip");*/
4723 
4724     return;
4725 }
4726 
4727 
4728 
4729 
4730 /* @func ajFilebuffLoadC ******************************************************
4731 **
4732 ** Adds a line to the buffer.
4733 **
4734 ** Intended for cases where the file data must be pre-processed before
4735 ** being seen by the sequence reading routines. The first case was
4736 ** for stripping HTML tags after reading via HTTP.
4737 **
4738 ** @param [u] buff [AjPFilebuff] Buffered file.
4739 ** @param [r] line [const char*] Line of input.
4740 ** @return [void]
4741 **
4742 ** @release 6.0.0
4743 ** @@
4744 ******************************************************************************/
4745 
ajFilebuffLoadC(AjPFilebuff buff,const char * line)4746 void ajFilebuffLoadC(AjPFilebuff buff, const char* line)
4747 {
4748     if(!buff->Lines)
4749         buff->Curr = buff->Lines = AJNEW0(buff->Last);
4750     else
4751         buff->Last = AJNEW0(buff->Last->Next);
4752 
4753     ajStrAssignC(&buff->Last->Line,line);
4754     buff->Last->Next = NULL;
4755     buff->Size++;
4756 
4757     return;
4758 }
4759 
4760 
4761 
4762 
4763 /* @func ajFilebuffLoadS ******************************************************
4764 **
4765 ** Adds a copy of a line to the buffer.
4766 **
4767 ** Intended for cases where the file data must be pre processed before
4768 ** being seen by the sequence reading routines. The first case was
4769 ** for stripping HTML tags after reading via HTTP.
4770 **
4771 ** @param [u] buff [AjPFilebuff] Buffered file.
4772 ** @param [r] line [const AjPStr] Line of input.
4773 ** @return [void]
4774 **
4775 ** @release 6.0.0
4776 ** @@
4777 ******************************************************************************/
4778 
ajFilebuffLoadS(AjPFilebuff buff,const AjPStr line)4779 void ajFilebuffLoadS(AjPFilebuff buff, const AjPStr line)
4780 {
4781     if(!buff->Lines)
4782         buff->Curr = buff->Lines = AJNEW0(buff->Last);
4783     else
4784         buff->Last = AJNEW0(buff->Last->Next);
4785 
4786     ajStrAssignS(&buff->Last->Line,line);
4787     buff->Last->Next = NULL;
4788     buff->Size++;
4789 
4790     return;
4791 }
4792 
4793 
4794 
4795 
4796 /* @func ajFilebuffLoadAll ****************************************************
4797 **
4798 ** Reads all input lines from a file into the buffer.
4799 **
4800 ** Intended for cases where the file data must be pre-processed before
4801 ** being seen by the sequence reading routines. The first case was
4802 ** for stripping HTML tags after reading via HTTP.
4803 **
4804 ** @param [u] buff [AjPFilebuff] Buffered file.
4805 ** @return [void]
4806 **
4807 ** @release 6.0.0
4808 ** @@
4809 ******************************************************************************/
4810 
ajFilebuffLoadAll(AjPFilebuff buff)4811 void ajFilebuffLoadAll(AjPFilebuff buff)
4812 {
4813     AjPStr rdline = NULL;
4814     AjBool status = ajTrue;
4815 
4816     while(status)
4817     {
4818         status = ajBuffreadLine(buff, &rdline);
4819         /*ajDebug("read: <%S>\n", rdline);*/
4820     }
4821 
4822     ajFilebuffReset(buff);
4823     ajStrDel(&rdline);
4824 
4825     /*ajFilebuffTrace(buff);*/
4826 
4827     return;
4828 }
4829 
4830 
4831 
4832 
4833 /* @func ajFilebuffLoadReadurl ************************************************
4834 **
4835 ** Reads from a URL and loads all input lines into the buffer.
4836 **
4837 ** @param [u] buff [AjPFilebuff] Buffered file.
4838 ** @param [r] url [const AjPStr] URL
4839 ** @return [AjBool] True on success
4840 **
4841 ** @release 6.4.0
4842 ** @@
4843 ******************************************************************************/
4844 
ajFilebuffLoadReadurl(AjPFilebuff buff,const AjPStr url)4845 AjBool ajFilebuffLoadReadurl(AjPFilebuff buff, const AjPStr url)
4846 {
4847     AjPStr host      = NULL;
4848     AjPStr urlget    = NULL;
4849     AjPStr get       = NULL;
4850     AjPStr proxyName = NULL;            /* host for proxy access.*/
4851     AjPStr proxyAuth = NULL;
4852     AjPStr proxyCred = NULL;
4853     AjPStr httpver   = NULL;          /* HTTP version 1.0, 1.1, ... */
4854     ajint iport = 80;
4855     ajint proxyPort;
4856     FILE *fp;
4857     AjOSysTimeout timo;
4858     AjOSysSocket sock;
4859 
4860     AjPStr dbproxy = ajStrNew();
4861 
4862     ajHttpUrlDeconstruct(url, &iport, &host, &urlget);
4863 
4864     ajHttpGetVersion(NULL, &httpver);
4865 
4866     if(ajHttpGetProxyinfo(dbproxy, &proxyPort, &proxyName,
4867                           &proxyAuth, &proxyCred))
4868         ajFmtPrintS(&get, "GET http://%S:%d%S HTTP/%S\n",
4869                     host, iport, urlget, httpver);
4870     else
4871         ajFmtPrintS(&get, "GET %S HTTP/%S\n", urlget, httpver);
4872 
4873     if(ajStrGetLen(proxyName))
4874         fp = ajHttpOpenProxy(dbproxy, proxyName, proxyPort,
4875                              proxyAuth, proxyCred,
4876                              host, iport,
4877                              get, &sock);
4878     else
4879         fp = ajHttpOpen(NULL, host, iport, get, &sock);
4880 
4881     buff->File = ajFileNewFromCfile(fp);
4882 
4883     if(!buff)
4884     {
4885         ajDebug("socket buffer attach failed\n");
4886         ajErr("socket buffer attach failed for '%S'", url);
4887 
4888         return ajFalse;
4889     }
4890 
4891     ajDebug("Ready to read errno %d msg '%s'\n",
4892             errno, ajMessGetSysmessageC());
4893 
4894     timo.seconds = 180;
4895     ajSysTimeoutSet(&timo);
4896 
4897     ajFilebuffLoadAll(buff);
4898 
4899     ajSysTimeoutUnset(&timo);
4900 
4901     return ajTrue;
4902 }
4903 
4904 
4905 
4906 
4907 /* @section Buffered file operators *******************************************
4908 **
4909 ** These functions use the contents of a file object but do not make
4910 ** any changes.
4911 **
4912 ** @nam3rule Get Return an attribute value
4913 ** @nam4rule GetFile Return the file object
4914 ** @nam4rule GetFileptr Return the C file pointer
4915 ** @nam4rule GetFirst Return the first line in the buffer
4916 ** @nam3rule Is Tests a condition
4917 ** @nam4rule IsBuffered Tests whether file input is buffered
4918 ** @nam4rule IsEmpty Tests whether buffer is exhausted for all input files
4919 ** @nam4rule IsEnded Tests whether buffer is at end of current file and empty
4920 ** @nam4rule IsEof Tests whether buffer is at end of file
4921 **
4922 ** @argrule * buff [const AjPFilebuff] Buffered file object
4923 **
4924 ** @valrule GetFileptr [FILE*] C file pointer
4925 ** @valrule GetFile [AjPFile] File object
4926 ** @valrule GetFirst [const AjPStr] First line of buffer
4927 ** @valrule IsBuffered [AjBool] True if file is buffered
4928 ** @valrule IsEmpty [AjBool] True if buffer is empty
4929 ** @valrule IsEnded [AjBool] True if buffer is ended for this file
4930 ** @valrule IsEof [AjBool] True if buffer has read to end of this file
4931 **
4932 ** @fcategory use
4933 **
4934 ** @fdata [AjPFilebuff]
4935 **
4936 ******************************************************************************/
4937 
4938 
4939 
4940 
4941 /* @func ajFilebuffGetFile ****************************************************
4942 **
4943 ** Returns the file object from a buffered file object.
4944 **
4945 ** @param [r] buff [const AjPFilebuff] Buffered file.
4946 ** @return [AjPFile] File object.
4947 **
4948 ** @release 6.0.0
4949 ** @@
4950 ******************************************************************************/
4951 
ajFilebuffGetFile(const AjPFilebuff buff)4952 AjPFile ajFilebuffGetFile(const AjPFilebuff buff)
4953 {
4954     if(!buff)
4955         return NULL;
4956 
4957     return buff->File;
4958 }
4959 
4960 
4961 
4962 
4963 /* @func ajFilebuffGetFileptr *************************************************
4964 **
4965 ** Returns the C file pointer for an open buffered file.
4966 **
4967 ** @param [r] buff [const AjPFilebuff] Buffered file.
4968 ** @return [FILE*] C file pointer for the file.
4969 **
4970 ** @release 6.0.0
4971 ** @@
4972 ******************************************************************************/
4973 
ajFilebuffGetFileptr(const AjPFilebuff buff)4974 FILE* ajFilebuffGetFileptr(const AjPFilebuff buff)
4975 {
4976     if(!buff)
4977         return NULL;
4978 
4979     return buff->File->fp;
4980 }
4981 
4982 
4983 
4984 
4985 /* @func ajFilebuffGetFirst ***************************************************
4986 **
4987 ** Returns the first line of a file buffer
4988 **
4989 ** @param [r] buff [const AjPFilebuff] File buffer
4990 ** @return [const AjPStr] First line
4991 **
4992 **
4993 ** @release 6.4.0
4994 ******************************************************************************/
4995 
ajFilebuffGetFirst(const AjPFilebuff buff)4996 const AjPStr ajFilebuffGetFirst(const AjPFilebuff buff)
4997 {
4998     if(!buff)
4999         return NULL;
5000 
5001     if(!buff->Lines)
5002         return NULL;
5003 
5004     return buff->Lines->Line;
5005 }
5006 
5007 
5008 
5009 
5010 /* @func ajFilebuffIsBuffered *************************************************
5011 **
5012 ** Tests whether an input file is buffered.
5013 **
5014 ** @param [r] buff [const AjPFilebuff] Buffered file object.
5015 ** @return [AjBool] ajTrue if the file was unbuffered before
5016 **
5017 ** @release 6.0.0
5018 ** @@
5019 ******************************************************************************/
5020 
ajFilebuffIsBuffered(const AjPFilebuff buff)5021 AjBool ajFilebuffIsBuffered(const AjPFilebuff buff)
5022 {
5023     if(!buff)
5024         return ajFalse;
5025 
5026     if(buff->Nobuff)
5027         return ajFalse;
5028 
5029     return ajTrue;
5030 }
5031 
5032 
5033 
5034 
5035 /* @func ajFilebuffIsEmpty ****************************************************
5036 **
5037 ** Tests whether a file buffer is empty, including testing for a
5038 ** possible next file
5039 **
5040 ** @param [r] buff [const AjPFilebuff] Buffered file.
5041 ** @return [AjBool] ajTrue if the buffer is empty.
5042 **
5043 ** @release 6.0.0
5044 ** @@
5045 ******************************************************************************/
5046 
ajFilebuffIsEmpty(const AjPFilebuff buff)5047 AjBool ajFilebuffIsEmpty(const AjPFilebuff buff)
5048 {
5049     /*ajDebug("ajFilebuffIsEmpty Size: %d Pos: %d End: %b Handle: %d "
5050       "Fp: %x List; %d\n",
5051       buff->Size, buff->Pos, buff->File->End, buff->File->Handle,
5052       buff->File->fp, ajListstrGetLength(buff->File->List));*/
5053 
5054     if(!buff)
5055         return ajTrue;
5056 
5057     if(!buff->File)
5058         return ajTrue;
5059 
5060     if(buff->Pos < buff->Size)
5061         return ajFalse;
5062 
5063     /* not open */
5064     if(!buff->File->fp || !buff->File->Handle)
5065         return ajTrue;
5066 
5067     if(buff->File->End && !ajListstrGetLength(buff->File->List))
5068         /* EOF and done */
5069         return ajTrue;
5070 
5071     ajDebug("ajFilebuffIsEmpty false\n");
5072 
5073     return ajFalse;
5074 }
5075 
5076 
5077 
5078 
5079 /* @func ajFilebuffIsEnded ****************************************************
5080 **
5081 ** Tests whether the current file is exhausted.
5082 ** This means end of file is reached and the buffer is empty.
5083 **
5084 ** It is possible that further files are defined in the input list
5085 ** (see ajFilebuffIsEmpty)
5086 **
5087 ** @param [r] buff [const AjPFilebuff] File buffer
5088 ** @return [AjBool] ajTrue if we already set end-of-file
5089 **
5090 ** @release 6.0.0
5091 ** @@
5092 ******************************************************************************/
5093 
ajFilebuffIsEnded(const AjPFilebuff buff)5094 AjBool ajFilebuffIsEnded(const AjPFilebuff buff)
5095 {
5096     if(!buff)
5097         return ajTrue;
5098 
5099     ajDebug("ajFilebuffIsEnded End: %B Size: %d\n",
5100             buff->File->End, buff->Size);
5101 
5102     /* not reached EOF yet */
5103     if(!buff->File->End)
5104         return ajFalse;
5105 
5106     /* Something in the buffer*/
5107     if(buff->Size != 0)
5108         return ajFalse;
5109 
5110     return ajTrue;
5111 }
5112 
5113 
5114 
5115 
5116 /* @func ajFilebuffIsEof ******************************************************
5117 **
5118 ** Tests whether we have reached end of file already
5119 **
5120 ** @param [r] buff [const AjPFilebuff] File buffer
5121 ** @return [AjBool] ajTrue if we already set end-of-file
5122 **
5123 ** @release 6.0.0
5124 ** @@
5125 ******************************************************************************/
5126 
ajFilebuffIsEof(const AjPFilebuff buff)5127 AjBool ajFilebuffIsEof(const AjPFilebuff buff)
5128 {
5129     if(!buff)
5130         return ajTrue;
5131 
5132     if(!buff->File)
5133         return ajTrue;
5134 
5135     return buff->File->End;
5136 }
5137 
5138 
5139 
5140 
5141 /* @section Buffered file debug ***********************************************
5142 **
5143 ** Report file object contents for debugging
5144 **
5145 **
5146 ** @nam3rule Trace    Print report to debug file (if any)
5147 ** @nam4rule TraceFull    Print full contents report to debug file (if any)
5148 ** @nam4rule TraceTitle    Print report with a set title
5149 **
5150 ** @argrule * buff [const AjPFilebuff]
5151 ** @argrule Full nlines [size_t] Maximum number of lines to report
5152 ** @argrule Full nfree [size_t] Maximum number of free lines to report
5153 ** @argrule Title title [const char*] Report title
5154 **
5155 ** @valrule * [void]
5156 **
5157 ** @fcategory misc
5158 ** @fdata [AjPFilebuff]
5159 **
5160 ******************************************************************************/
5161 
5162 
5163 
5164 
5165 /* @func ajFilebuffTrace ******************************************************
5166 **
5167 ** Writes debug messages to indicate the contents of a buffered file.
5168 **
5169 ** @param [r] buff [const AjPFilebuff] Buffered file.
5170 ** @return [void]
5171 **
5172 ** @release 6.0.0
5173 ** @@
5174 ******************************************************************************/
5175 
ajFilebuffTrace(const AjPFilebuff buff)5176 void ajFilebuffTrace(const AjPFilebuff buff)
5177 {
5178     AjPFilebufflist test;
5179     ajint i = 0;
5180     ajint j = -1;
5181 
5182     ajDebug("Trace buffer file '%S'\n"
5183             "             Pos: %d Size: %d FreeSize: %d Fpos: %Ld End: %b\n",
5184             buff->File->Name, buff->Pos, buff->Size,buff->FreeSize,
5185             buff->Fpos, buff->File->End);
5186 
5187     if(buff->Size)
5188     {
5189         ajDebug(" Lines: %u\n", buff->Size);
5190 
5191         if(buff->Curr)
5192             ajDebug("  Curr: %8Ld %x %x %u <%S>\n",
5193                     buff->Curr->Fpos,
5194                     buff->Curr->Line, buff->Curr->Next,
5195                     ajStrGetLen(buff->Curr->Line),
5196                     buff->Curr->Line);
5197         else
5198             ajDebug("  Curr: <null>\n");
5199 
5200         if(buff->Lines)
5201             ajDebug("  From: %8Ld %x %x %u <%S>\n",
5202                     buff->Lines->Fpos,
5203                     buff->Lines->Line, buff->Lines->Next,
5204                     ajStrGetLen(buff->Lines->Line),
5205                     buff->Lines->Line);
5206         else
5207             ajDebug("  From: <null>\n");
5208 
5209         if(buff->Last)
5210             ajDebug("    To: %8Ld %x %x %u <%S>\n",
5211                     buff->Last->Fpos,
5212                     buff->Last->Line, buff->Last->Next,
5213                     ajStrGetLen(buff->Last->Line),
5214                     buff->Last->Line);
5215         else
5216             ajDebug("    To: <null>\n");
5217     }
5218 
5219     if(buff->Freelines)
5220         for(test = buff->Freelines; test; test=test->Next)
5221         {
5222             i++;
5223 
5224             if(test == buff->Freelast)
5225                 j = i;
5226         }
5227 
5228     ajDebug(" Free: %d Last: %d\n", i, j);
5229 
5230     return;
5231 }
5232 
5233 
5234 
5235 
5236 /* @func ajFilebuffTraceFull **************************************************
5237 **
5238 ** Writes debug messages to show the full contents of a buffered file.
5239 **
5240 ** @param [r] buff [const AjPFilebuff] Buffered file.
5241 ** @param [r] nlines [size_t] Maximum number of lines to trace.
5242 ** @param [r] nfree [size_t] Maximum number of free lines to trace.
5243 ** @return [void]
5244 **
5245 ** @release 6.0.0
5246 ** @@
5247 ******************************************************************************/
5248 
ajFilebuffTraceFull(const AjPFilebuff buff,size_t nlines,size_t nfree)5249 void ajFilebuffTraceFull(const AjPFilebuff buff, size_t nlines,
5250                          size_t nfree)
5251 {
5252     ajint i;
5253     AjPFilebufflist line;
5254     AjBool last = ajFalse;
5255 
5256     ajDebug("Trace buffer file '%S' End: %B\n"
5257             "             Pos: %d Size: %d Nobuff: %B Fpos: %Ld\n",
5258             buff->File->Name, buff->File->End,
5259             buff->Pos, buff->Size, buff->Nobuff, buff->Fpos);
5260 
5261     line = buff->Lines;
5262 
5263     for(i=1; line && (i <= (ajint)nlines); i++)
5264     {
5265         if(line == buff->Curr)
5266             ajDebug("*Line %x %d: %5d %5d <%-20S>\n",
5267                     line->Line, i,
5268                     ajStrGetLen(line->Line), strlen(ajStrGetPtr(line->Line)),
5269                     line->Line);
5270         else
5271             ajDebug(" Line %x %d: %5d %5d <%-20S>\n",
5272                     line->Line, i,
5273                     ajStrGetLen(line->Line), strlen(ajStrGetPtr(line->Line)),
5274                     line->Line);
5275         line = line->Next;
5276     }
5277 
5278     line = buff->Freelines;
5279 
5280     for(i=1; line && (i <= (ajint)nfree);  i++)
5281     {
5282         if(line == buff->Freelast)
5283             last = ajTrue;
5284 
5285         ajDebug(" Free %x %d: %d bytes %B\n",
5286                 line->Line, i, ajStrGetRes(line->Line), last);
5287         line = line->Next;
5288     }
5289 
5290     return;
5291 }
5292 
5293 
5294 
5295 
5296 /* @func ajFilebuffTraceTitle *************************************************
5297 **
5298 ** Writes the full contents of a buffered file to the debug file
5299 **
5300 ** @param [r] buff [const AjPFilebuff] Buffered file.
5301 ** @param [r] title [const char*] Report title
5302 ** @return [void]
5303 **
5304 ** @release 6.0.0
5305 ** @@
5306 ******************************************************************************/
5307 
ajFilebuffTraceTitle(const AjPFilebuff buff,const char * title)5308 void ajFilebuffTraceTitle(const AjPFilebuff buff, const char* title)
5309 {
5310     ajint i;
5311     AjPFilebufflist line;
5312     ajint last = 0;
5313 
5314     ajDebug("=== File Buffer: %s ===\n", title);
5315     line = buff->Lines;
5316 
5317     for(i=1; line; i++)
5318     {
5319         ajStrAssignS(&fileTmpStr, line->Line);
5320         ajStrRemoveLastNewline(&fileTmpStr);
5321 
5322         if(line == buff->Curr)
5323             ajDebug("* %x %S\n", line->Line, fileTmpStr);
5324         else
5325             ajDebug("  %x %S\n", line->Line, fileTmpStr);
5326 
5327         line = line->Next;
5328     }
5329 
5330     line = buff->Freelines;
5331 
5332     for(i=1; line;  i++)
5333     {
5334         if(line == buff->Freelast)
5335             last = i;
5336 
5337         if(line == buff->Freelast)
5338             ajDebug("F %x %S\n", line->Line, fileTmpStr);
5339         else
5340             ajDebug("f %x %S\n", line->Line, fileTmpStr);
5341 
5342         line = line->Next;
5343     }
5344 
5345     if (!last)
5346         last = i;
5347     ajDebug("=== end of file, free list %d lines ===\n", last);
5348 
5349     return;
5350 }
5351 
5352 
5353 
5354 
5355 /* @funcstatic fileBuffLineDel ************************************************
5356 **
5357 ** Delete a line from a buffer.
5358 **
5359 ** @param [u] buff [AjPFilebuff] File buffer
5360 ** @return [void]
5361 **
5362 ** @release 2.5.0
5363 ******************************************************************************/
5364 
fileBuffLineDel(AjPFilebuff buff)5365 static void fileBuffLineDel(AjPFilebuff buff)
5366 {
5367     AjPFilebufflist saveprev;
5368 
5369     if(!buff->Curr)
5370         return;
5371 
5372     /*ajDebug("fileBuffLineDel removing line [%d%s%d], '%S' len %d\n",
5373       buff->Pos, SLASH_STRING, buff->Size, buff->Curr->Line,
5374       ajStrGetLen(buff->Curr->Line));*/
5375 
5376     /* first line */
5377     if(!buff->Prev)
5378     {
5379         buff->Prev = buff->Lines;
5380         buff->Curr = buff->Lines = buff->Lines->Next;
5381         ajStrDel(&buff->Prev->Line);
5382         AJFREE(buff->Prev);
5383         --buff->Size;
5384 
5385         return;
5386     }
5387 
5388     /* last line */
5389     if(!buff->Curr->Next)
5390     {
5391         saveprev = buff->Prev;
5392         buff->Prev = buff->Lines;
5393 
5394         while(buff->Prev && buff->Prev->Next != saveprev)
5395             buff->Prev = buff->Prev->Next;
5396 
5397         saveprev->Next = NULL;
5398 
5399         ajStrDel(&buff->Curr->Line);
5400         AJFREE(buff->Curr);
5401         buff->Curr = NULL;
5402         buff->Last = saveprev;
5403         --buff->Size;
5404         buff->Pos = buff->Size;
5405 
5406         return;
5407     }
5408 
5409     buff->Prev->Next = buff->Curr->Next;
5410     ajStrDel(&buff->Curr->Line);
5411     AJFREE(buff->Curr);
5412     buff->Curr = buff->Prev->Next;
5413     --buff->Size;
5414 
5415     return;
5416 }
5417 
5418 
5419 
5420 
5421 /* @funcstatic fileBuffLineNext ***********************************************
5422 **
5423 ** Steps the Curr pointer to the next line in a buffer.
5424 **
5425 ** Not for use when reading from a file. This steps through the buffer
5426 **
5427 ** @param [u] buff [AjPFilebuff] File buffer
5428 ** @return [AjBool] ajTrue if there was another line
5429 **
5430 ** @release 2.5.0
5431 ******************************************************************************/
5432 
fileBuffLineNext(AjPFilebuff buff)5433 static AjBool fileBuffLineNext(AjPFilebuff buff)
5434 {
5435     if(buff->Pos < buff->Size)
5436     {
5437         buff->Prev = buff->Curr;
5438         buff->Curr = buff->Curr->Next;
5439         buff->Pos++;
5440 
5441         return ajTrue;
5442     }
5443 
5444     return ajFalse;
5445 }
5446 
5447 
5448 
5449 
5450 /* @datasection [AjPOutfile] Output file object *******************************
5451 **
5452 ** Function is for manipulating output files
5453 ** and their attributes.
5454 **
5455 ** @nam2rule Outfile
5456 ******************************************************************************/
5457 
5458 
5459 
5460 
5461 /* @section Outfile constructors **********************************************
5462 **
5463 ** All constructors return a new open file by pointer. It is the responsibility
5464 ** of the user to first destroy any previous file pointer. The target pointer
5465 ** does not need to be initialised to NULL, but it is good programming practice
5466 ** to do so anyway.
5467 **
5468 ** To replace or reuse an existing file, see instead
5469 ** the {File Assignments} and {File Modifiers} functions.
5470 **
5471 ** The range of constructors is provided to allow flexibility in how
5472 ** applications can open files to read various kinds of data.
5473 **
5474 ** @nam3rule New Output file object constructor
5475 ** @suffix Name File name
5476 ** @suffix S File name as a string
5477 **
5478 ** @argrule S name [const AjPStr] Output filename
5479 **
5480 ** @valrule * [AjPOutfile] Output file
5481 **
5482 ** @fcategory new
5483 **
5484 ** @fdata [AjPOutfile]
5485 **
5486 ******************************************************************************/
5487 
5488 
5489 
5490 
5491 /* @func ajOutfileNewNameS ****************************************************
5492 **
5493 ** Creates a new formatted output file object with a specified name.
5494 **
5495 ** 'stdout' and 'stderr' are special names for standard output and
5496 ** standard error respectively.
5497 **
5498 ** @param [r] name [const AjPStr] File name.
5499 ** @return [AjPOutfile] New output file object.
5500 **
5501 ** @release 6.0.0
5502 ** @@
5503 ******************************************************************************/
5504 
ajOutfileNewNameS(const AjPStr name)5505 AjPOutfile ajOutfileNewNameS(const AjPStr name)
5506 {
5507     AjPOutfile thys;
5508     ajlong ipos;
5509     AjPStr tmpname = NULL;
5510 
5511     AJNEW0(thys);
5512 
5513     ipos = ajStrFindC(name, "::");
5514     if(ipos > 0)
5515     {
5516         ajStrAssignSubS(&thys->Formatstr, name, 0, ipos-1);
5517         ajStrAssignSubS(&tmpname, name, ipos+2, -1);
5518         thys->File = ajFileNewOutNameS(tmpname);
5519         ajStrDel(&tmpname);
5520     }
5521     else
5522     {
5523         thys->File = ajFileNewOutNameS(name);
5524     }
5525 
5526     if(!thys->File)
5527         return NULL;
5528 
5529     return thys;
5530 }
5531 
5532 
5533 
5534 
5535 /* @section Outfile destructors ***********************************************
5536 **
5537 ** Destruction is achieved by closing the file.
5538 **
5539 ** Unlike ANSI C, there are tests to ensure a file is not closed twice.
5540 **
5541 ** @nam3rule Close Close file and delete output file object
5542 **
5543 ** @argrule * Pfile [AjPOutfile*] Output file object pointer
5544 **
5545 ** @valrule * [void]
5546 **
5547 ** @fcategory delete
5548 **
5549 ** @fdata [AjPOutfile]
5550 **
5551 ******************************************************************************/
5552 
5553 
5554 
5555 
5556 /* @func ajOutfileClose *******************************************************
5557 **
5558 ** Close and free an outfile object.
5559 **
5560 ** @param [d] Pfile [AjPOutfile*] Output file.
5561 ** @return [void]
5562 **
5563 ** @release 2.9.0
5564 ** @@
5565 ******************************************************************************/
5566 
ajOutfileClose(AjPOutfile * Pfile)5567 void ajOutfileClose(AjPOutfile* Pfile)
5568 {
5569     AjPOutfile thys;
5570 
5571     thys = Pfile ? *Pfile : 0;
5572 
5573     if(!Pfile)
5574         return;
5575 
5576     if(!*Pfile)
5577         return;
5578 
5579     fileClose(thys->File);
5580     AJFREE(thys->File);
5581     ajStrDel(&thys->Type);
5582     ajStrDel(&thys->Formatstr);
5583     AJFREE(*Pfile);
5584 
5585     return;
5586 }
5587 
5588 
5589 
5590 
5591 /* @section Outfile casts *****************************************************
5592 **
5593 ** These functions examine the contents of an outfile object and return some
5594 ** derived information. Some of them provide access to the internal
5595 ** components of a file object. They are provided for programming convenience
5596 ** but should be used with caution.
5597 **
5598 ** @nam3rule Get Return an output file attribute value
5599 ** @nam4rule GetFile Return the file object
5600 ** @nam4rule GetFileptr Return the C file pointer
5601 ** @nam4rule GetFormat Return the output format name
5602 ** @nam4rule GetFormatindex Return the output format index number
5603 **
5604 ** @argrule * file [const AjPOutfile] Output file object
5605 **
5606 ** @valrule GetFile [AjPFile] File object
5607 ** @valrule GetFileptr [FILE*] C file pointer
5608 ** @valrule GetFormat [const AjPStr] Filename as a string
5609 ** @valrule GetFormatindex [ajuint] Index in internal formats
5610 **
5611 ** @fcategory cast
5612 **
5613 ** @fdata [AjPOutfile]
5614 **
5615 ******************************************************************************/
5616 
5617 
5618 
5619 
5620 /* @func ajOutfileGetFile *****************************************************
5621 **
5622 ** Returns the AjPFile for an AjPOutfile object
5623 **
5624 ** @param [r] file [const AjPOutfile] Outfile object
5625 ** @return [AjPFile] AjPFile object
5626 **
5627 ** @release 6.0.0
5628 ******************************************************************************/
5629 
ajOutfileGetFile(const AjPOutfile file)5630 AjPFile ajOutfileGetFile (const AjPOutfile file)
5631 {
5632     return file->File;
5633 }
5634 
5635 
5636 
5637 
5638 /* @func ajOutfileGetFileptr **************************************************
5639 **
5640 ** Returns the C FILE* for an AjPOutfile object
5641 **
5642 ** @param [r] file [const AjPOutfile] Outfile object
5643 ** @return [FILE*] C file pointer
5644 **
5645 ** @release 6.0.0
5646 ******************************************************************************/
5647 
ajOutfileGetFileptr(const AjPOutfile file)5648 FILE* ajOutfileGetFileptr (const AjPOutfile file)
5649 {
5650     return file->File->fp;
5651 }
5652 
5653 
5654 
5655 
5656 /* @func ajOutfileGetFormat ***************************************************
5657 **
5658 ** Returns the file format name for an AjPOutfile object
5659 **
5660 ** @param [r] file [const AjPOutfile] Outfile object
5661 ** @return [const AjPStr] Format name
5662 **
5663 ** @release 6.0.0
5664 ******************************************************************************/
5665 
ajOutfileGetFormat(const AjPOutfile file)5666 const AjPStr ajOutfileGetFormat (const AjPOutfile file)
5667 {
5668     return file->Formatstr;
5669 }
5670 
5671 
5672 
5673 
5674 /* @func ajOutfileGetFormatindex **********************************************
5675 **
5676 ** Returns the file format name for an AjPOutfile object
5677 **
5678 ** @param [r] file [const AjPOutfile] Outfile object
5679 ** @return [ajuint] Format name
5680 **
5681 ** @release 6.4.0
5682 ******************************************************************************/
5683 
ajOutfileGetFormatindex(const AjPOutfile file)5684 ajuint ajOutfileGetFormatindex (const AjPOutfile file)
5685 {
5686     return file->Format;
5687 }
5688 
5689 
5690 
5691 
5692 /* @section Outfile modifiers *************************************************
5693 **
5694 ** These functions modify an output file object and its asociated output file
5695 **
5696 ** @nam3rule Reset
5697 **
5698 ** @argrule * outf [AjPOutfile] Output file object
5699 **
5700 ** @valrule * [void]
5701 **
5702 ** @fcategory modify
5703 **
5704 ** @fdata [AjPOutfile]
5705 **
5706 ******************************************************************************/
5707 
5708 
5709 
5710 
5711 /* @func ajOutfileReset *******************************************************
5712 **
5713 ** Close and free an outfile object.
5714 **
5715 ** @param [u] outf [AjPOutfile] Output file.
5716 ** @return [void]
5717 **
5718 ** @release 6.5.0
5719 ** @@
5720 ******************************************************************************/
5721 
ajOutfileReset(AjPOutfile outf)5722 void ajOutfileReset(AjPOutfile outf)
5723 {
5724     if(!outf)
5725         return;
5726 
5727     if(!outf->Cleanup)
5728         return;
5729 
5730     outf->Cleanup(outf);
5731 
5732     return;
5733 }
5734 
5735 
5736 
5737 
5738 /* @datasection [AjPStr] Filename functions ***********************************
5739 **
5740 ** Functions operating on strings containing filenames
5741 **
5742 ** @nam2rule Filename Operations on filename strings
5743 **
5744 ******************************************************************************/
5745 
5746 
5747 
5748 
5749 /* @section Filename tests ****************************************************
5750 **
5751 ** Tests on filenames and searching the file system
5752 **
5753 ** @nam3rule Exists tests whether file exists in current directory
5754 ** @nam4rule Dir Tests whether file exists and is a directory
5755 ** @nam4rule Exec Tests whether file exists and is executable by the user
5756 ** @nam4rule Read Tests whether file exists and is readable by the user
5757 ** @nam4rule Write Tests whether file exists and is writable by the user
5758 ** @nam3rule Get Return a filename element
5759 ** @nam4rule GetSize Return the file size
5760 ** @nam3rule Has Filename contains element
5761 ** @nam4rule Ext Filename extension
5762 ** @nam4rule Path Directory path
5763 ** @nam3rule Test Test a filename
5764 ** @nam4rule TestExclude Test a filename against a list of files to include.
5765 **                       Any file not in the list is excluded.
5766 ** @nam4rule TestInclude Test a filename against a list of files to exclude
5767 **                       Any file not in the list is included.
5768 ** @suffix Path Include the file path in tests
5769 **
5770 ** @argrule * filename [const AjPStr] Filename string
5771 ** @argrule Stat mode [ajint] Mode
5772 ** @argrule Test exclude [const AjPStr] Excluded filenames wildcard
5773 ** @argrule Test include [const AjPStr] Included filenames wildcard
5774 **
5775 ** @valrule Exists [AjBool] True if file exists with any requested access
5776 ** @valrule GetSize [ajlong] File size or -1 if not found
5777 ** @valrule Has [AjBool] True if file has attribute
5778 ** @valrule Test [AjBool] True if file passed test
5779 ** @fcategory use
5780 **
5781 ** @fdata [AjPStr]
5782 **
5783 ******************************************************************************/
5784 
5785 
5786 
5787 
5788 /* @func ajFilenameExists *****************************************************
5789 **
5790 ** Returns true if file exists
5791 **
5792 ** @param [r] filename [const AjPStr] Filename.
5793 ** @return [AjBool] ajTrue on success
5794 **
5795 ** @release 6.0.0
5796 ** @@
5797 ******************************************************************************/
5798 
ajFilenameExists(const AjPStr filename)5799 AjBool ajFilenameExists(const AjPStr filename)
5800 {
5801 #if defined(AJ_IRIXLF)
5802     struct stat64 buf;
5803 #else /* !AJ_IRIXLF */
5804     struct stat buf;
5805 #endif /* AJ_IRIXLF */
5806 
5807     if(ajStrMatchC(filename, "stdin"))
5808             return ajTrue;
5809 
5810     if(
5811 #if defined(AJ_IRIXLF)
5812         !stat64(ajStrGetPtr(filename), &buf)
5813 #else /* !AJ_IRIXLF */
5814         !stat(ajStrGetPtr(filename), &buf)
5815 #endif /* AJ_IRIXLF */
5816        )
5817         return ajTrue;
5818 
5819     return ajFalse;
5820 }
5821 
5822 
5823 
5824 
5825 /* @func ajFilenameExistsDir **************************************************
5826 **
5827 ** Returns true if file exists and is a directory
5828 **
5829 ** @param [r] filename [const AjPStr] Filename.
5830 ** @return [AjBool] ajTrue on success
5831 **
5832 ** @release 6.0.0
5833 ** @@
5834 ******************************************************************************/
5835 
ajFilenameExistsDir(const AjPStr filename)5836 AjBool ajFilenameExistsDir(const AjPStr filename)
5837 {
5838 #if defined(AJ_IRIXLF)
5839     struct stat64 buf;
5840 #else /* !AJ_IRIXLF */
5841     struct stat buf;
5842 #endif /* AJ_IRIXLF */
5843 
5844 #ifdef WIN32
5845     if(!ajStrGetLen(filename))
5846         return ajTrue;
5847 #endif /* WIN32 */
5848 
5849     if(
5850 #if defined(AJ_IRIXLF)
5851         !stat64(ajStrGetPtr(filename), &buf)
5852 #else /* !AJ_IRIXLF */
5853         !stat(ajStrGetPtr(filename), &buf)
5854 #endif /* AJ_IRIXLF */
5855        )
5856         if((ajuint)buf.st_mode & AJ_FILE_DIR)
5857             return ajTrue;
5858 
5859     return ajFalse;
5860 }
5861 
5862 
5863 
5864 
5865 /* @func ajFilenameExistsExec *************************************************
5866 **
5867 ** Returns true if file exists and is executable by the user
5868 **
5869 ** @param [r] filename [const AjPStr] Filename.
5870 ** @return [AjBool] ajTrue on success
5871 **
5872 ** @release 6.0.0
5873 ** @@
5874 ******************************************************************************/
5875 
ajFilenameExistsExec(const AjPStr filename)5876 AjBool ajFilenameExistsExec(const AjPStr filename)
5877 {
5878 #if defined(AJ_IRIXLF)
5879     struct stat64 buf;
5880 #else /* !AJ_IRIXLF */
5881     struct stat buf;
5882 #endif /* AJ_IRIXLF */
5883 
5884     if(
5885 #if defined(AJ_IRIXLF)
5886         !stat64(ajStrGetPtr(filename), &buf)
5887 #else /* !AJ_IRIXLF */
5888         !stat(ajStrGetPtr(filename), &buf)
5889 #endif /* AJ_IRIXLF */
5890        )
5891         if((ajuint)buf.st_mode & AJ_FILE_X)
5892             return ajTrue;
5893 
5894     return ajFalse;
5895 }
5896 
5897 
5898 
5899 
5900 /* @func ajFilenameExistsRead *************************************************
5901 **
5902 ** Returns true if file exists and is readable by the user
5903 **
5904 ** @param [r] filename [const AjPStr] Filename.
5905 ** @return [AjBool] ajTrue on success
5906 **
5907 ** @release 6.0.0
5908 ** @@
5909 ******************************************************************************/
5910 
ajFilenameExistsRead(const AjPStr filename)5911 AjBool ajFilenameExistsRead(const AjPStr filename)
5912 {
5913 #if defined(AJ_IRIXLF)
5914     struct stat64 buf;
5915 #else /* !AJ_IRIXLF */
5916     struct stat buf;
5917 #endif /* AJ_IRIXLF */
5918 
5919     if(
5920 #if defined(AJ_IRIXLF)
5921         !stat64(ajStrGetPtr(filename), &buf)
5922 #else /* !AJ_IRIXLF */
5923         !stat(ajStrGetPtr(filename), &buf)
5924 #endif /* AJ_IRIXLF */
5925        )
5926         if((ajuint)buf.st_mode & AJ_FILE_R)
5927             return ajTrue;
5928 
5929     return ajFalse;
5930 }
5931 
5932 
5933 
5934 
5935 /* @func ajFilenameExistsWrite ************************************************
5936 **
5937 ** Returns true if file exists and is writable by the user
5938 **
5939 ** @param [r] filename [const AjPStr] Filename.
5940 ** @return [AjBool] ajTrue on success
5941 **
5942 ** @release 6.0.0
5943 ** @@
5944 ******************************************************************************/
5945 
ajFilenameExistsWrite(const AjPStr filename)5946 AjBool ajFilenameExistsWrite(const AjPStr filename)
5947 {
5948 #if defined(AJ_IRIXLF)
5949     struct stat64 buf;
5950 #else /* !AJ_IRIXLF */
5951     struct stat buf;
5952 #endif /* AJ_IRIXLF */
5953 
5954     if(
5955 #if defined(AJ_IRIXLF)
5956         !stat64(ajStrGetPtr(filename), &buf)
5957 #else /* !AJ_IRIXLF */
5958         !stat(ajStrGetPtr(filename), &buf)
5959 #endif /* AJ_IRIXLF */
5960        )
5961         if((ajuint)buf.st_mode & AJ_FILE_W)
5962             return ajTrue;
5963 
5964     return ajFalse;
5965 }
5966 
5967 
5968 
5969 
5970 /* @func ajFilenameGetSize ****************************************************
5971 **
5972 ** Returns the length of a file
5973 **
5974 ** @param [r] filename [const AjPStr] Filename.
5975 ** @return [ajlong] length or -1 if file doesn't exist
5976 **
5977 ** @release 6.0.0
5978 ** @@
5979 ******************************************************************************/
5980 
ajFilenameGetSize(const AjPStr filename)5981 ajlong ajFilenameGetSize(const AjPStr filename)
5982 {
5983 #if defined(AJ_IRIXLF)
5984     struct stat64 buf;
5985 #else /* !AJ_IRIXLF */
5986     struct stat buf;
5987 #endif /* AJ_IRIXLF */
5988 
5989 #if defined(AJ_IRIXLF)
5990     if(!stat64(ajStrGetPtr(filename), &buf))
5991         return (ajlong)buf.st_size;
5992 #else /* !AJ_IRIXLF */
5993     if(!stat(ajStrGetPtr(filename), &buf))
5994         return (ajlong)buf.st_size;
5995 #endif /* AJ_IRIXLF */
5996 
5997     return -1;
5998 }
5999 
6000 
6001 
6002 
6003 /* @func ajFilenameHasPath ****************************************************
6004 **
6005 ** Tests whether a filename includes a directory specification.
6006 **
6007 ** @param [r] filename [const AjPStr] File name.
6008 ** @return [AjBool] ajTrue if directory filename syntax was found
6009 **
6010 ** @release 6.0.0
6011 ** @@
6012 ******************************************************************************/
6013 
ajFilenameHasPath(const AjPStr filename)6014 AjBool ajFilenameHasPath(const AjPStr filename)
6015 {
6016     if(ajStrFindC(filename, SLASH_STRING) < 0)
6017         return ajFalse;
6018 
6019     return ajTrue;
6020 }
6021 
6022 
6023 
6024 
6025 /* @func ajFilenameTestExclude ************************************************
6026 **
6027 ** Tests a filename against wildcard
6028 ** lists of file names to be included and excluded.
6029 **
6030 ** The path (if any) is removed before checking.
6031 **
6032 ** By default files are excluded. The inclusion list is used to select
6033 ** files, and the exclusion list is then used to exclude selected
6034 ** files again.
6035 **
6036 ** @param [r] filename [const AjPStr] File to test
6037 ** @param [r] exclude [const AjPStr] List of wildcard names to exclude
6038 ** @param [r] include [const AjPStr] List of wildcard names to include
6039 ** @return [AjBool] ajTrue if the filename is accepted.
6040 **
6041 ** @release 6.0.0
6042 ** @@
6043 ******************************************************************************/
6044 
ajFilenameTestExclude(const AjPStr filename,const AjPStr exclude,const AjPStr include)6045 AjBool ajFilenameTestExclude(const AjPStr filename,
6046                              const AjPStr exclude,
6047                              const AjPStr include)
6048 {
6049     AjBool ret = ajFalse;
6050 
6051     AjPStrTok handle = NULL;
6052     AjPStr token     = NULL;
6053 
6054     ajDebug("ajFilenameTestExclude "
6055             "filename '%S' exclude '%S' include '%S'\n",
6056             filename, exclude, include);
6057 
6058     ajStrAssignS(&fileNameTmp, filename);
6059     ajFilenameTrimPath(&fileNameTmp);
6060 
6061     if(ajStrGetLen(include))
6062     {
6063         ajStrTokenAssignC(&handle, include, " \t,;\n");
6064 
6065         while(ajStrTokenNextParse(handle, &token))
6066             if(ajStrMatchWildS(filename, token) ||
6067                ajStrMatchWildS(fileNameTmp, token))
6068                 ret = ajTrue;
6069 
6070         ajStrTokenReset(handle);
6071     }
6072 
6073     if(ajStrGetLen(exclude))
6074     {   /* nokeep, test exclude last */
6075         ajStrTokenAssignC(&handle, exclude, " \t,;\n");
6076 
6077         while(ajStrTokenNextParse(handle, &token))
6078             if(ajStrMatchWildS(filename, token) ||
6079                ajStrMatchWildS(fileNameTmp, token))
6080                 ret = ajFalse;
6081 
6082         ajStrTokenReset(handle);
6083     }
6084 
6085     ajStrTokenDel(&handle);
6086     ajStrDel(&token);
6087 
6088     return ret;
6089 }
6090 
6091 
6092 
6093 
6094 /* @func ajFilenameTestExcludePath ********************************************
6095 **
6096 ** Tests a full path filename against wildcard
6097 ** lists of file names to be included and excluded.
6098 **
6099 ** The full path is retained and included in the tests.
6100 **
6101 ** By default files are excluded. The inclusion list is used to select
6102 ** files, and the exclusion list is then used to exclude selected
6103 ** files again.
6104 **
6105 ** @param [r] filename [const AjPStr] File to test
6106 ** @param [r] exclude [const AjPStr] List of wildcard names to exclude
6107 ** @param [r] include [const AjPStr] List of wildcard names to include
6108 ** @return [AjBool] ajTrue if the filename is accepted.
6109 **
6110 ** @release 6.0.0
6111 ** @@
6112 ******************************************************************************/
6113 
ajFilenameTestExcludePath(const AjPStr filename,const AjPStr exclude,const AjPStr include)6114 AjBool ajFilenameTestExcludePath(const AjPStr filename,
6115                                  const AjPStr exclude,
6116                                  const AjPStr include)
6117 {
6118     AjBool ret = ajFalse;
6119 
6120     AjPStrTok handle = NULL;
6121     AjPStr token     = NULL;
6122 
6123     ajDebug("ajFilenameTestExcludePath "
6124             "filename '%S' exclude '%S' include '%S'\n",
6125             filename, exclude, include);
6126 
6127     if(ajStrGetLen(include))
6128     {
6129         ajStrTokenAssignC(&handle, include, " \t,;\n");
6130 
6131         while(ajStrTokenNextParse(handle, &token))
6132             if(ajStrMatchWildS(filename, token))
6133                 ret = ajTrue;
6134 
6135         ajStrTokenReset(handle);
6136     }
6137 
6138     if(ajStrGetLen(exclude))
6139     {   /* nokeep, test exclude last */
6140         ajStrTokenAssignC(&handle, exclude, " \t,;\n");
6141 
6142         while(ajStrTokenNextParse(handle, &token))
6143             if(ajStrMatchWildS(filename, token))
6144                 ret = ajFalse;
6145 
6146         ajStrTokenReset(handle);
6147     }
6148 
6149     ajStrTokenDel(&handle);
6150     ajStrDel(&token);
6151 
6152     return ret;
6153 }
6154 
6155 
6156 
6157 
6158 /* @func ajFilenameTestInclude ************************************************
6159 **
6160 ** Tests a filename against wildcard
6161 ** lists of file names to be included and excluded.
6162 **
6163 ** By default files are included. The exclusion list is used to trim
6164 ** out files, and the inclusion list is then used to add selected
6165 ** files again.
6166 **
6167 ** @param [r] filename [const AjPStr] File to test
6168 ** @param [r] exclude [const AjPStr] List of wildcard names to exclude
6169 ** @param [r] include [const AjPStr] List of wildcard names to include
6170 ** @return [AjBool] ajTrue if the filename is accepted.
6171 **
6172 ** @release 6.0.0
6173 ** @@
6174 ******************************************************************************/
6175 
ajFilenameTestInclude(const AjPStr filename,const AjPStr exclude,const AjPStr include)6176 AjBool ajFilenameTestInclude(const AjPStr filename,
6177                              const AjPStr exclude,
6178                              const AjPStr include)
6179 {
6180     AjBool ret = ajTrue;
6181 
6182     AjPStrTok handle = NULL;
6183     AjPStr token     = NULL;
6184 
6185     ajStrAssignS(&fileNameTmp, filename);
6186     ajFilenameTrimPath(&fileNameTmp);
6187 
6188     ajDebug("ajFilenameTestInclude "
6189             "filename '%S' exclude '%S' include '%S'\n",
6190             filename, exclude, include);
6191 
6192     if(ajStrGetLen(exclude))
6193     {
6194         /* keep, so test exclude first */
6195         ajStrTokenAssignC(&handle, exclude, " \t,;\n");
6196 
6197         while(ajStrTokenNextParse(handle, &token))
6198             if(ajStrMatchWildS(filename, token) ||
6199                ajStrMatchWildS(fileNameTmp, token))
6200                 ret = ajFalse;
6201 
6202         ajStrTokenReset(handle);
6203     }
6204 
6205     if(ajStrGetLen(include))
6206     {
6207         ajStrTokenAssignC(&handle, include, " \t,;\n");
6208 
6209         while(ajStrTokenNextParse(handle, &token))
6210             if(ajStrMatchWildS(filename, token) ||
6211                ajStrMatchWildS(fileNameTmp, token))
6212                 ret = ajTrue;
6213 
6214         ajStrTokenReset(handle);
6215     }
6216 
6217     ajStrTokenDel(&handle);
6218     ajStrDel(&token);
6219 
6220     return ret;
6221 }
6222 
6223 
6224 
6225 
6226 /* @func ajFilenameTestIncludePath ********************************************
6227 **
6228 ** Tests a filename against wildcard
6229 ** lists of file names to be included and excluded.
6230 **
6231 ** By default files are included. The exclusion list is used to trim
6232 ** out files, and the inclusion list is then used to add selected
6233 ** files again.
6234 **
6235 ** @param [r] filename [const AjPStr] File to test
6236 ** @param [r] exclude [const AjPStr] List of wildcard names to exclude
6237 ** @param [r] include [const AjPStr] List of wildcard names to include
6238 ** @return [AjBool] ajTrue if the filename is accepted.
6239 **
6240 ** @release 6.0.0
6241 ** @@
6242 ******************************************************************************/
6243 
ajFilenameTestIncludePath(const AjPStr filename,const AjPStr exclude,const AjPStr include)6244 AjBool ajFilenameTestIncludePath(const AjPStr filename,
6245                                  const AjPStr exclude,
6246                                  const AjPStr include)
6247 {
6248     AjBool ret = ajTrue;
6249 
6250     AjPStrTok handle = NULL;
6251     AjPStr token     = NULL;
6252 
6253     ajDebug("ajFilenameTestIncludePath "
6254             "filename '%S' exclukde '%S' include '%S\n",
6255             filename, exclude, include);
6256 
6257     if(ajStrGetLen(exclude))
6258     {
6259         /* keep, so test exclude first */
6260         ajStrTokenAssignC(&handle, exclude, " \t,;\n");
6261 
6262         while(ajStrTokenNextParse(handle, &token))
6263             if(ajStrMatchWildS(filename, token))
6264                 ret = ajFalse;
6265 
6266         ajStrTokenReset(handle);
6267     }
6268 
6269     if(ajStrGetLen(include))
6270     {
6271         ajStrTokenAssignC(&handle, include, " \t,;\n");
6272 
6273         while(ajStrTokenNextParse(handle, &token))
6274             if(ajStrMatchWildS(filename, token))
6275                 ret = ajTrue;
6276 
6277         ajStrTokenReset(handle);
6278     }
6279 
6280     ajStrTokenDel(&handle);
6281     ajStrDel(&token);
6282 
6283     return ret;
6284 }
6285 
6286 
6287 
6288 
6289 /* @section Filename modifiers ************************************************
6290 **
6291 ** These functions overwrite a previous filename
6292 **
6293 ** @nam3rule Replace Replace part of a filename
6294 ** @nam3rule Set     Set undefined part of a filename
6295 ** @nam4rule Tempname Set a new temporary filename
6296 ** @nam3rule Trim    Remove part of a filename
6297 ** @nam4rule TrimAll  Remove path and extension and trailing :identifier
6298 **                    to leave the file basename
6299 **
6300 ** @suffix Ext Filename extension
6301 ** @suffix Path Filename path
6302 ** @suffix C New character value
6303 ** @suffix S New string value
6304 **
6305 ** @argrule * Pfilename [AjPStr*] Filename
6306 ** @argrule C txt [const char*] New character value
6307 ** @argrule S str [const AjPStr] New string value
6308 **
6309 ** @valrule * [AjBool] True on success
6310 **
6311 ** @fcategory modify
6312 **
6313 ** @fdata [AjPStr]
6314 **
6315 ******************************************************************************/
6316 
6317 
6318 
6319 
6320 /* @func ajFilenameReplaceExtC ************************************************
6321 **
6322 ** Replaces the extension part of a filename
6323 **
6324 ** @param [u] Pfilename [AjPStr*] Filename.
6325 ** @param [r] txt [const char*] New file extension
6326 ** @return [AjBool] ajTrue if the replacement succeeded.
6327 **
6328 ** @release 6.0.0
6329 ** @@
6330 ******************************************************************************/
6331 
ajFilenameReplaceExtC(AjPStr * Pfilename,const char * txt)6332 AjBool ajFilenameReplaceExtC(AjPStr* Pfilename, const char* txt)
6333 {
6334     AjBool doext;
6335     char *p = NULL;
6336 
6337     doext = ajTrue;
6338     if(!txt || !*txt)
6339         doext = ajFalse;
6340 
6341 
6342     /*ajDebug("ajFilenameReplaceExtC '%S' '%s'\n", *Pfilename, txt);*/
6343 
6344     ajStrAssignS(&fileTmpStr,*Pfilename);
6345 
6346     /* Skip any directory path */
6347     p = strrchr(ajStrGetuniquePtr(&fileTmpStr),SLASH_CHAR);
6348 
6349     if (!p)
6350         p = ajStrGetuniquePtr(&fileTmpStr);
6351 
6352     p = strrchr(p,'.');
6353 
6354     if(p)
6355     {
6356         *p='\0';
6357         fileTmpStr->Len = p - ajStrGetPtr(fileTmpStr);
6358     }
6359 
6360 
6361     if(doext)
6362     {
6363         ajStrAppendC(&fileTmpStr,".");
6364         ajStrAppendC(&fileTmpStr,txt);
6365     }
6366 
6367     ajStrAssignS(Pfilename,fileTmpStr);
6368 
6369     /*ajDebug("result '%S'\n", *Pfilename);*/
6370 
6371     return ajTrue;
6372 }
6373 
6374 
6375 
6376 
6377 /* @func ajFilenameReplaceExtS ************************************************
6378 **
6379 ** Replaces the extension part of a filename
6380 **
6381 ** @param [u] Pfilename [AjPStr*] Filename.
6382 ** @param [r] str [const AjPStr] New file extension
6383 ** @return [AjBool] ajTrue if the replacement succeeded.
6384 **
6385 ** @release 6.0.0
6386 ** @@
6387 ******************************************************************************/
6388 
ajFilenameReplaceExtS(AjPStr * Pfilename,const AjPStr str)6389 AjBool ajFilenameReplaceExtS(AjPStr* Pfilename, const AjPStr str)
6390 {
6391     if(!str)
6392         return ajFilenameReplaceExtC(Pfilename, NULL);
6393 
6394     return ajFilenameReplaceExtC(Pfilename, ajStrGetPtr(str));
6395 }
6396 
6397 
6398 
6399 
6400 /* @func ajFilenameReplacePathC ***********************************************
6401 **
6402 ** Sets the directory part of a filename
6403 **
6404 ** @param [u] Pfilename [AjPStr*] Filename.
6405 ** @param [r] txt [const char*] Directory
6406 ** @return [AjBool] ajTrue if the replacement succeeded.
6407 **
6408 ** @release 6.0.0
6409 ** @@
6410 ******************************************************************************/
6411 
ajFilenameReplacePathC(AjPStr * Pfilename,const char * txt)6412 AjBool ajFilenameReplacePathC(AjPStr* Pfilename, const char* txt)
6413 {
6414     AjPStr tmpname = NULL;
6415     AjPStr tmpdir = NULL;
6416 
6417     if(!txt)
6418         return ajFalse;
6419 
6420     if(!fileFilenameExp)
6421 #ifndef WIN32
6422         fileFilenameExp = ajRegCompC("(.*/)?([^/]+)$");
6423 #else /* WIN32 */
6424     fileFilenameExp = ajRegCompC("(.*[/\\\\])?([^/\\\\]+)$");
6425 #endif /* !WIN32 */
6426 
6427     if(ajRegExec(fileFilenameExp, *Pfilename))
6428     {
6429         ajRegSubI(fileFilenameExp, 1, &tmpdir);
6430 
6431         /* we already have a directory */
6432         if(ajStrGetLen(tmpdir))
6433         {
6434             ajStrDel(&tmpdir);
6435             return ajFalse;
6436         }
6437 
6438         ajRegSubI(fileFilenameExp, 2, &tmpname);
6439 
6440         if(txt[strlen(txt)-1] == SLASH_CHAR)
6441             ajFmtPrintS(Pfilename, "%s%S", txt, tmpname);
6442         else
6443             ajFmtPrintS(Pfilename, "%s%s%S", txt, SLASH_STRING,tmpname);
6444 
6445         ajStrDel(&tmpname);
6446     }
6447 
6448     return ajTrue;
6449 }
6450 
6451 
6452 
6453 
6454 /* @func ajFilenameReplacePathS ***********************************************
6455 **
6456 ** Sets the directory part of a filename
6457 **
6458 ** @param [u] Pfilename [AjPStr*] Filename.
6459 ** @param [r] str [const AjPStr] New directory
6460 ** @return [AjBool] ajTrue if the replacement succeeded.
6461 **
6462 ** @release 6.0.0
6463 ** @@
6464 ******************************************************************************/
6465 
ajFilenameReplacePathS(AjPStr * Pfilename,const AjPStr str)6466 AjBool ajFilenameReplacePathS(AjPStr* Pfilename, const AjPStr str)
6467 {
6468     if(!ajStrGetLen(str))
6469         return ajFalse;
6470 
6471     return ajFilenameReplacePathC(Pfilename, ajStrGetPtr(str));
6472 }
6473 
6474 
6475 
6476 
6477 /* @func ajFilenameSetExtC ****************************************************
6478 **
6479 ** Sets the extension part of a filename
6480 **
6481 ** @param [u] Pfilename [AjPStr*] Filename.
6482 ** @param [r] txt [const char*] New file extension
6483 ** @return [AjBool] ajTrue if the replacement succeeded.
6484 **
6485 ** @release 6.3.0
6486 ** @@
6487 ******************************************************************************/
6488 
ajFilenameSetExtC(AjPStr * Pfilename,const char * txt)6489 AjBool ajFilenameSetExtC(AjPStr* Pfilename, const char* txt)
6490 {
6491     char *p = NULL;
6492 
6493     if(!txt || !*txt)
6494         return ajFalse;
6495 
6496     /*ajDebug("ajFilenameSetExtC '%S' '%s'\n", *Pfilename, txt);*/
6497 
6498     ajStrAssignS(&fileTmpStr,*Pfilename);
6499 
6500     /* Skip any directory path */
6501     p = strrchr(ajStrGetuniquePtr(&fileTmpStr),SLASH_CHAR);
6502 
6503     if (!p)
6504         p = ajStrGetuniquePtr(&fileTmpStr);
6505 
6506     ajStrAppendC(&fileTmpStr,".");
6507     ajStrAppendC(&fileTmpStr,txt);
6508 
6509     ajStrAssignS(Pfilename,fileTmpStr);
6510 
6511     /*ajDebug("result '%S'\n", *Pfilename);*/
6512 
6513     return ajTrue;
6514 }
6515 
6516 
6517 
6518 
6519 /* @func ajFilenameSetExtS ****************************************************
6520 **
6521 ** Sets the extension part of a base filename
6522 **
6523 ** @param [u] Pfilename [AjPStr*] Filename.
6524 ** @param [r] str [const AjPStr] New file extension
6525 ** @return [AjBool] ajTrue if the replacement succeeded.
6526 **
6527 ** @release 6.3.0
6528 ** @@
6529 ******************************************************************************/
6530 
ajFilenameSetExtS(AjPStr * Pfilename,const AjPStr str)6531 AjBool ajFilenameSetExtS(AjPStr* Pfilename, const AjPStr str)
6532 {
6533     if(!str)
6534         return ajFalse;
6535 
6536     return ajFilenameSetExtC(Pfilename, ajStrGetPtr(str));
6537 }
6538 
6539 
6540 
6541 
6542 /* @func ajFilenameSetTempname ************************************************
6543 **
6544 ** Returns an available temporary filename that can be opened for writing
6545 ** Filename will be of the form progname-time.randomnumber
6546 ** Tries 5 times to find a new filename. Returns ajFalse if not
6547 ** successful or the file cannot be opened for writing.
6548 ** This function returns only the filename, not a file pointer.
6549 **
6550 ** @param [w] Pfilename [AjPStr*] Filename of new temporary file
6551 ** @return [AjBool] True on success
6552 **
6553 ** @release 6.0.0
6554 ** @@
6555 ******************************************************************************/
6556 
ajFilenameSetTempname(AjPStr * Pfilename)6557 AjBool ajFilenameSetTempname(AjPStr* Pfilename)
6558 {
6559 #if defined(AJ_IRIXLF)
6560     struct  stat64 buf;
6561 #else /* !AJ_IRIXLF */
6562     struct  stat buf;
6563 #endif /* AJ_IRIXLF */
6564     ajint   retry;
6565     AjBool  ok;
6566     AjPFile outf;
6567 
6568     if(!fileTempFilename)
6569         fileTempFilename = ajStrNew();
6570 
6571     ajStrAssignC(&fileDirectory,".");
6572     ajDirnameFix(&fileDirectory);
6573 
6574     ajFmtPrintS(&fileTempFilename,
6575                 "%S%S-%d.%d",fileDirectory,ajUtilGetProgram(),time(0),
6576                 ajRandomNumber());
6577 
6578     retry = 5;
6579     ok    = ajTrue;
6580 
6581     while(
6582 #if defined(AJ_IRIXLF)
6583         !stat64(ajStrGetPtr(fileTempFilename),&buf) && retry
6584 #else /* !AJ_IRIXLF */
6585         !stat(ajStrGetPtr(fileTempFilename),&buf) && retry
6586 #endif /* AJ_IRIXLF */
6587           )
6588     {
6589         ajFmtPrintS(&fileTempFilename,
6590                     "%S%S-%d.%d",fileDirectory,ajUtilGetProgram(),time(0),
6591                     ajRandomNumber());
6592         --retry;
6593     }
6594 
6595     if(!retry)
6596     {
6597         ajDebug("Cannot find a unique filename [last try %S]\n",
6598                 fileTempFilename);
6599         ok = ajFalse;
6600     }
6601 
6602     if(!(outf = ajFileNewOutNameS(fileTempFilename)))
6603     {
6604         ajDebug("Cannot write to file %S\n",fileTempFilename);
6605         ok = ajFalse;
6606     }
6607     else
6608     {
6609         ajFileClose(&outf);
6610         ajSysFileUnlinkS(fileTempFilename);
6611     }
6612 
6613     ajStrAssignS(Pfilename,fileTempFilename);
6614 
6615     return ok;
6616 }
6617 
6618 
6619 
6620 
6621 /* @func ajFilenameSetTempnamePathC *******************************************
6622 **
6623 ** Returns an available temporary filename that can be opened for writing
6624 ** Filename will be of the form progname-time.randomnumber
6625 ** Tries 5 times to find a new filename. Returns ajFalse if not
6626 ** successful or the file cannot be opened for writing.
6627 ** This function returns only the filename, not a file pointer.
6628 **
6629 ** @param [w] Pfilename [AjPStr*] Filename of new temporary file
6630 ** @param [r] txt [const char*] Directory path
6631 ** @return [AjBool] True on success
6632 **
6633 ** @release 6.0.0
6634 ** @@
6635 ******************************************************************************/
6636 
ajFilenameSetTempnamePathC(AjPStr * Pfilename,const char * txt)6637 AjBool ajFilenameSetTempnamePathC(AjPStr* Pfilename, const char* txt)
6638 {
6639 #if defined(AJ_IRIXLF)
6640     struct  stat64 buf;
6641 #else /* !AJ_IRIXLF */
6642     struct  stat buf;
6643 #endif /* AJ_IRIXLF */
6644     ajint   retry;
6645     AjBool  ok;
6646     AjPFile outf;
6647 
6648     if(!fileTempFilename)
6649         fileTempFilename = ajStrNew();
6650 
6651     ajStrAssignC(&fileDirectory,txt);
6652     ajDirnameFix(&fileDirectory);
6653 
6654     ajFmtPrintS(&fileTempFilename,
6655                 "%S%S-%d.%d",fileDirectory,ajUtilGetProgram(),time(0),
6656                 ajRandomNumber());
6657 
6658     retry = 5;
6659     ok    = ajTrue;
6660 
6661     while(
6662 #if defined(AJ_IRIXLF)
6663         !stat64(ajStrGetPtr(fileTempFilename),&buf) && retry
6664 #else /* !AJ_IRIXLF */
6665         !stat(ajStrGetPtr(fileTempFilename),&buf) && retry
6666 #endif /* AJ_IRIXLF */
6667           )
6668     {
6669         ajFmtPrintS(&fileTempFilename,
6670                     "%S%S-%d.%d",fileDirectory,ajUtilGetProgram(),time(0),
6671                     ajRandomNumber());
6672         --retry;
6673     }
6674 
6675     if(!retry)
6676     {
6677         ajDebug("Cannot find a unique filename [last try %S]\n",
6678                 fileTempFilename);
6679         ok = ajFalse;
6680     }
6681 
6682     if(!(outf = ajFileNewOutNameS(fileTempFilename)))
6683     {
6684         ajDebug("Cannot write to file %S\n",fileTempFilename);
6685         ok = ajFalse;
6686     }
6687     else
6688     {
6689         ajFileClose(&outf);
6690         ajSysFileUnlinkS(fileTempFilename);
6691     }
6692 
6693     ajStrAssignS(Pfilename,fileTempFilename);
6694 
6695     return ok;
6696 }
6697 
6698 
6699 
6700 
6701 /* @func ajFilenameSetTempnamePathS *******************************************
6702 **
6703 ** Returns an available temporary filename that can be opened for writing
6704 ** Filename will be of the form progname-time.randomnumber
6705 ** Tries 5 times to find a new filename. Returns ajFalse if not
6706 ** successful or the file cannot be opened for writing.
6707 ** This function returns only the filename, not a file pointer.
6708 **
6709 ** @param [w] Pfilename [AjPStr*] Filename of new temporary file
6710 ** @param [r] str [const AjPStr] Directory path
6711 ** @return [AjBool] True on success
6712 **
6713 ** @release 6.0.0
6714 ** @@
6715 ******************************************************************************/
6716 
ajFilenameSetTempnamePathS(AjPStr * Pfilename,const AjPStr str)6717 AjBool ajFilenameSetTempnamePathS(AjPStr* Pfilename, const AjPStr str)
6718 {
6719 #if defined(AJ_IRIXLF)
6720     struct  stat64 buf;
6721 #else /* !AJ_IRIXLF */
6722     struct  stat buf;
6723 #endif /* AJ_IRIXLF */
6724     ajint   retry;
6725     AjBool  ok;
6726     AjPFile outf;
6727 
6728     if(!fileTempFilename)
6729         fileTempFilename = ajStrNew();
6730 
6731     ajStrAssignS(&fileDirectory,str);
6732     ajDirnameFix(&fileDirectory);
6733 
6734     ajFmtPrintS(&fileTempFilename,
6735                 "%S%S-%d.%d",fileDirectory,ajUtilGetProgram(),time(0),
6736                 ajRandomNumber());
6737 
6738     retry = 5;
6739     ok    = ajTrue;
6740 
6741     while(
6742 #if defined(AJ_IRIXLF)
6743         !stat64(ajStrGetPtr(fileTempFilename),&buf) && retry
6744 #else /* !AJ_IRIXLF */
6745         !stat(ajStrGetPtr(fileTempFilename),&buf) && retry
6746 #endif /* AJ_IRIXLF */
6747           )
6748     {
6749         ajFmtPrintS(&fileTempFilename,
6750                     "%S%S-%d.%d",fileDirectory,ajUtilGetProgram(),time(0),
6751                     ajRandomNumber());
6752         --retry;
6753     }
6754 
6755     if(!retry)
6756     {
6757         ajDebug("Cannot find a unique filename [last try %S]\n",
6758                 fileTempFilename);
6759         ok = ajFalse;
6760     }
6761 
6762     if(!(outf = ajFileNewOutNameS(fileTempFilename)))
6763     {
6764         ajDebug("Cannot write to file %S\n",fileTempFilename);
6765         ok = ajFalse;
6766     }
6767     else
6768     {
6769         ajFileClose(&outf);
6770         ajSysFileUnlinkS(fileTempFilename);
6771     }
6772 
6773     ajStrAssignS(Pfilename,fileTempFilename);
6774 
6775     return ok;
6776 }
6777 
6778 
6779 
6780 
6781 /* @func ajFilenameTrimAll ****************************************************
6782 **
6783 ** Truncates a filename to a basic file name.
6784 **
6785 ** @param [uP] Pfilename [AjPStr*] File name
6786 ** @return [AjBool] ajTrue on success, and returns a filename.
6787 **                  ajFalse on failure, and returns an empty string.
6788 **
6789 ** @release 6.0.0
6790 ** @@
6791 ******************************************************************************/
6792 
ajFilenameTrimAll(AjPStr * Pfilename)6793 AjBool ajFilenameTrimAll(AjPStr* Pfilename)
6794 {
6795     /* entryname at end */
6796     if(!fileEntryExp)
6797         fileEntryExp = ajRegCompC(":([A-Za-z0-9_-]+)$");
6798 
6799     if(ajRegExec(fileEntryExp, *Pfilename))
6800     {
6801         ajRegSubI(fileEntryExp, 1, Pfilename);
6802         return ajTrue;
6803     }
6804 
6805     /* name.ext */
6806     if(!fileFileExp)
6807         fileFileExp = ajRegCompC("([A-Za-z0-9_-]+)[.][A-Za-z0-9_-]+$");
6808 
6809     if(ajRegExec(fileFileExp, *Pfilename))
6810     {
6811         ajRegSubI(fileFileExp, 1, Pfilename);
6812         return ajTrue;
6813     }
6814 
6815     /* last valid word */
6816     if(!fileRestExp)
6817         fileRestExp = ajRegCompC("([A-Za-z0-9_-]+)[^A-Za-z0-9_-]*$");
6818 
6819     if(ajRegExec(fileRestExp, *Pfilename))
6820     {
6821         ajRegSubI(fileRestExp, 1, Pfilename);
6822         return ajTrue;
6823     }
6824 
6825     ajStrAssignClear(Pfilename);
6826 
6827     return ajFalse;
6828 }
6829 
6830 
6831 
6832 
6833 /* @func ajFilenameTrimExt ****************************************************
6834 **
6835 ** Trims the extension (if any) from a filename
6836 **
6837 ** @param [u] Pfilename [AjPStr*] Filename
6838 ** @return [AjBool] ajTrue is there was an extension
6839 **
6840 ** @release 6.0.0
6841 ******************************************************************************/
6842 
ajFilenameTrimExt(AjPStr * Pfilename)6843 AjBool ajFilenameTrimExt(AjPStr* Pfilename)
6844 {
6845     ajlong i;
6846     ajlong len;
6847 
6848     if(!ajStrGetLen(*Pfilename))
6849         return ajFalse;
6850 
6851     len = ajStrGetLen(*Pfilename);
6852     i = ajStrFindlastC(*Pfilename, ".");
6853 
6854     if(i < 0)
6855         return ajFalse;
6856 
6857     ajStrCutEnd(Pfilename, (size_t) (len-i));
6858 
6859     return ajTrue;
6860 }
6861 
6862 
6863 
6864 
6865 /* @func ajFilenameTrimPath ***************************************************
6866 **
6867 ** Trims the directory path (if any) from a filename
6868 **
6869 ** @param [u] Pfilename [AjPStr*] Filename
6870 ** @return [AjBool] ajTrue is there was a directory
6871 **
6872 ** @release 6.0.0
6873 ******************************************************************************/
6874 
ajFilenameTrimPath(AjPStr * Pfilename)6875 AjBool ajFilenameTrimPath(AjPStr* Pfilename)
6876 {
6877     ajlong i;
6878 
6879     if(!ajStrGetLen(*Pfilename))
6880         return ajFalse;
6881 
6882     i = ajStrFindlastC(*Pfilename, SLASH_STRING);
6883 
6884     if(i < 0)
6885         return ajFalse;
6886 
6887     ajStrCutStart(Pfilename, (size_t) (i+1));
6888 
6889     return ajTrue;
6890 }
6891 
6892 
6893 
6894 
6895 /* @func ajFilenameTrimPathExt ************************************************
6896 **
6897 ** Trims the directory path (if any) and extension (if any) from a filename.
6898 **
6899 ** @param [u] Pfilename [AjPStr*] Filename
6900 ** @return [AjBool] ajTrue is there was a directory path or extension.
6901 **
6902 ** @release 6.0.0
6903 ******************************************************************************/
6904 
ajFilenameTrimPathExt(AjPStr * Pfilename)6905 AjBool ajFilenameTrimPathExt(AjPStr* Pfilename)
6906 {
6907     ajlong i;
6908     ajlong j;
6909     ajlong len;
6910 
6911     if(!ajStrGetLen(*Pfilename))
6912         return ajFalse;
6913 
6914     i = ajStrFindlastC(*Pfilename, SLASH_STRING);
6915 
6916     if(i >= 0)
6917         ajStrCutStart(Pfilename, (size_t) (i+1));
6918 
6919     len = ajStrGetLen(*Pfilename);
6920     j = ajStrFindlastC(*Pfilename, ".");
6921 
6922     if(j >= 0)
6923         ajStrCutEnd(Pfilename, (size_t) (len-j));
6924 
6925     if((i < 0) && (j < 0))
6926         return ajFalse;
6927 
6928     return ajTrue;
6929 }
6930 
6931 
6932 
6933 
6934 /* @datasection [AjPStr] Filename wildcard functions **************************
6935 **
6936 ** Functions operating on strings containing filenames with possible wildcards
6937 **
6938 ** @nam2rule Filewildname Operations on wildcard filename strings
6939 **
6940 ******************************************************************************/
6941 
6942 
6943 
6944 
6945 /* @section Filename tests ****************************************************
6946 **
6947 ** Tests on filenames and searching the file system
6948 **
6949 ** @nam3rule Exists tests whether file exists in current directory
6950 ** @nam4rule Dir Tests whether file exists and is a directory
6951 **
6952 ** @argrule * wildname [const AjPStr] Filename string
6953 ** @argrule Dir path [const AjPStr] Directory path
6954 **
6955 ** @valrule Exists [AjBool] True if file exists with any requested access
6956 ** @fcategory use
6957 **
6958 ** @fdata [AjPStr]
6959 **
6960 ******************************************************************************/
6961 
6962 
6963 
6964 
6965 /* @func ajFilewildnameExists *************************************************
6966 **
6967 ** Returns true if wildcard filename matches an existing file
6968 **
6969 ** @param [r] wildname [const AjPStr] Wildcard filename.
6970 ** @return [AjBool] ajTrue on success
6971 **
6972 ** @release 6.6.0
6973 ** @@
6974 ******************************************************************************/
6975 
ajFilewildnameExists(const AjPStr wildname)6976 AjBool ajFilewildnameExists(const AjPStr wildname)
6977 {
6978     AjBool ret = ajFalse;
6979 
6980     AjPStr userstr = NULL;
6981     AjPStr reststr = NULL;
6982 
6983     AjPStr dirname        = NULL;
6984     AjPStr wildfilename   = NULL;
6985 
6986     char *hdir = NULL;
6987 
6988     ajDebug("ajFilewildnameExists '%S'\n", wildname);
6989 
6990     if(ajStrMatchC(wildname, "stdin"))
6991         return ajTrue;
6992 
6993     if(ajStrGetCharLast(wildname) == '|')   /* pipe character at end */
6994         return ajTrue;
6995 
6996     /* keep a copy of the filename */
6997 
6998     ajStrAssignS(&fileNameTmp, wildname);
6999 
7000     /* replace ~user/ or ~/ with directory */
7001 
7002     if(ajStrGetCharFirst(fileNameTmp) == '~')
7003     {
7004         ajDebug("starts with '~'\n");
7005 
7006         if(!fileUserExp)
7007             fileUserExp = ajRegCompC("^~([^/\\\\]*)");
7008 
7009         ajRegExec(fileUserExp, fileNameTmp);
7010         ajRegSubI(fileUserExp, 1, &userstr);
7011         ajRegPost(fileUserExp, &reststr);
7012         ajDebug("  user: '%S' rest: '%S'\n", userstr, reststr);
7013 
7014         if(ajStrGetLen(userstr))
7015         {
7016             /* username specified */
7017             hdir = ajSysGetHomedirFromName(ajStrGetPtr(userstr));
7018 
7019             if(!hdir)
7020             {
7021                 ajStrDel(&userstr);
7022                 ajStrDelStatic(&fileNameTmp);
7023                 ajStrDel(&reststr);
7024 
7025                 return ajFalse;
7026             }
7027 
7028             ajFmtPrintS(&fileNameTmp, "%s%S", hdir, reststr);
7029             AJFREE(hdir);
7030 
7031             ajDebug("use getpwnam: '%S'\n", fileNameTmp);
7032         }
7033         else
7034         {
7035             /* just ~/ */
7036             hdir = ajSysGetHomedir();
7037 
7038             if(hdir)
7039             {
7040                 ajFmtPrintS(&fileNameTmp, "%s%S", hdir, reststr);
7041                 AJFREE(hdir);
7042             }
7043             else
7044                 ajFmtPrintS(&fileNameTmp,"%S",reststr);
7045 
7046             ajDebug("use HOME: '%S'\n", fileNameTmp);
7047         }
7048 
7049         ajStrDel(&userstr);
7050         ajStrDel(&reststr);
7051     }
7052 
7053 
7054     if(!fileWildExp)
7055         fileWildExp = ajRegCompC("(.*/)?([^/]*[*?][^/]*)$");
7056 
7057     /* wildcard file names (directory names do not allow wildcards) */
7058 
7059     if(ajRegExec(fileWildExp, fileNameTmp))
7060     {
7061         ajRegSubI(fileWildExp, 1, &dirname);
7062         ajRegSubI(fileWildExp, 2, &wildfilename);
7063         ajDebug("wild dir '%S' files '%S'\n", dirname, wildfilename);
7064         ret = ajFilewildnameExistsDir(wildfilename, dirname);
7065         ajStrDelStatic(&fileNameTmp);
7066         ajStrDel(&dirname);
7067         ajStrDel(&wildfilename);
7068 
7069         return ret;
7070     }
7071 
7072 #ifdef WIN32
7073     if(ajStrMatchC(wildname, "/dev/null"))
7074     {
7075         ajStrDelStatic(&fileNameTmp);
7076         return ajTrue;
7077     }
7078     else
7079 #endif /* WIN32 */
7080 
7081     ret = ajFilenameExists(fileNameTmp);
7082     ajStrDelStatic(&fileNameTmp);
7083 
7084     return ret;
7085 }
7086 
7087 
7088 
7089 
7090 /* @func ajFilewildnameExistsDir **********************************************
7091 **
7092 ** Opens directory "dir"
7093 ** Looks for file(s) matching wildcard filename
7094 **
7095 ** @param [r] wildname [const AjPStr] Wildcard filename.
7096 ** @param [r] path [const AjPStr] Directory
7097 ** @return [AjBool] True if one or more files matched.
7098 **
7099 ** @release 6.6.0
7100 ** @@
7101 ******************************************************************************/
7102 
ajFilewildnameExistsDir(const AjPStr wildname,const AjPStr path)7103 AjBool ajFilewildnameExistsDir(const AjPStr wildname, const AjPStr path)
7104 {
7105     DIR* dp;
7106 #if defined(AJ_IRIXLF)
7107     struct dirent64 *de;
7108 #else /* !AJ_IRIXLF */
7109     struct dirent* de;
7110 #endif /* AJ_IRIXLF */
7111 
7112 #ifdef _POSIX_C_SOURCE
7113     char buf[sizeof(struct dirent)+MAXNAMLEN];
7114 #endif /* _POSIX_C_SOURCE */
7115 
7116     if(ajStrGetLen(path))
7117         ajStrAssignS(&fileDirfixTmp, path);
7118     else
7119         ajStrAssignC(&fileDirfixTmp, CURRENT_DIR);
7120 
7121     if(ajStrGetCharLast(fileDirfixTmp) != SLASH_CHAR)
7122         ajStrAppendC(&fileDirfixTmp, SLASH_STRING);
7123 
7124     dp = fileOpenDir(&fileDirfixTmp);
7125 
7126     if(!dp)
7127         return ajFalse;
7128 
7129     while(
7130 #if defined(AJ_IRIXLF)
7131 #ifdef _POSIX_C_SOURCE
7132         !readdir64_r(dp,(struct dirent64 *)buf,&de)
7133 #else /* !_POSIX_C_SOURCE */
7134         (de=readdir64(dp))
7135 #endif /* _POSIX_C_SOURCE */
7136 #else /* !AJ_IRIXLF */
7137 #ifdef _POSIX_C_SOURCE
7138         !readdir_r(dp,(struct dirent *)buf,&de)
7139 #else /* _POSIX_C_SOURCE */
7140         (de=readdir(dp))
7141 #endif /* _POSIX_C_SOURCE */
7142 #endif /* AJ_IRIXLF */
7143           )
7144     {
7145 #ifdef _POSIX_C_SOURCE
7146         if(!de)
7147             break;
7148 #endif /* _POSIX_C_SOURCE */
7149         /* skip deleted files with inode zero */
7150 #ifndef __CYGWIN__
7151         if(!de->d_ino)
7152             continue;
7153 #endif /* !__CYGWIN__ */
7154 
7155         if(ajCharMatchC(de->d_name, "."))
7156             continue;
7157 
7158         if(ajCharMatchC(de->d_name, ".."))
7159             continue;
7160 
7161         if(!ajCharMatchWildS(de->d_name, wildname))
7162             continue;
7163 
7164         ajDebug("accept '%s'\n", de->d_name);
7165         closedir(dp);
7166         return ajTrue;
7167     }
7168 
7169     ajDebug("no files for '%S' '%S'\n", path, wildname);
7170     closedir(dp);
7171 
7172     return ajFalse;
7173 }
7174 
7175 
7176 
7177 
7178 /* @datasection [AjPStr] Directory name functions *****************************
7179 **
7180 ** Functions operating on strings containing directory names
7181 **
7182 ** @nam2rule Dirname Operations on directory name strings
7183 **
7184 ******************************************************************************/
7185 
7186 
7187 
7188 
7189 /* @section Directory name modifiers ******************************************
7190 **
7191 ** These functions overwrite a previous filename
7192 **
7193 ** @nam3rule Fill    Fill in all parts of incomplete directory name
7194 ** @nam3rule Fix     Fix incomplete directory name
7195 ** @nam4rule FixExists Fix incomplete directory name and test it can be opened
7196 ** @nam3rule Up      Change to parent directory
7197 **
7198 ** @suffix Ext Filename extension
7199 ** @suffix Path Filename path
7200 ** @suffix C New character value
7201 ** @suffix S New string value
7202 **
7203 ** @argrule * Pdirname [AjPStr*] Filename
7204 ** @argrule C txt [const char*] New character value
7205 ** @argrule S str [const AjPStr] New string value
7206 **
7207 ** @valrule * [void]
7208 ** @valrule *Exists [AjBool] True on success
7209 ** @valrule *Fill [AjBool] True on success
7210 ** @valrule *Up [AjBool] True on success
7211 **
7212 ** @fcategory modify
7213 **
7214 ** @fdata [AjPStr]
7215 **
7216 ******************************************************************************/
7217 
7218 
7219 
7220 
7221 /* @func ajDirnameFillPath ****************************************************
7222 **
7223 ** Checks that a string is a valid directory, and makes sure it has the
7224 ** full path definition.
7225 **
7226 ** @param [u] Pdirname [AjPStr*] Directory path
7227 ** @return [AjBool] true if a valid directory.
7228 **
7229 ** @release 6.0.0
7230 ** @@
7231 ******************************************************************************/
7232 
ajDirnameFillPath(AjPStr * Pdirname)7233 AjBool ajDirnameFillPath(AjPStr* Pdirname)
7234 {
7235     DIR* odir;
7236     AjPStr cwdpath = NULL;
7237 
7238     ajDebug("ajDirnameFillPath '%S'\n", *Pdirname);
7239 
7240     /* appends trailing slash if needed */
7241     odir = fileOpenDir(Pdirname);
7242 
7243     if(!odir)
7244         return ajFalse;
7245 
7246     free(odir);
7247 
7248     ajDebug("So far '%S'\n", *Pdirname);
7249 
7250     /* full path already */
7251     if(*ajStrGetPtr(*Pdirname) == SLASH_CHAR)
7252         return ajTrue;
7253 
7254     /* current directory */
7255     if(ajStrMatchC(*Pdirname, CURRENT_DIR))
7256     {
7257         ajStrAssignS(Pdirname, ajFileValueCwd());
7258         ajDebug("Current '%S'\n", *Pdirname);
7259 
7260         return ajTrue;
7261     }
7262 
7263     /*  going up */
7264     ajStrAssignS(&cwdpath, ajFileValueCwd());
7265 
7266     while(ajStrPrefixC(*Pdirname, UP_DIR))
7267     {
7268         ajDirnameUp(&cwdpath);
7269         ajStrKeepRange(Pdirname, 3, -1);
7270         ajDebug("Going up '%S' '%S'\n", *Pdirname, cwdpath);
7271     }
7272 
7273     ajStrInsertS(Pdirname, 0, cwdpath);
7274 
7275     ajDebug("Full path '%S'\n", *Pdirname);
7276 
7277     ajStrDel(&cwdpath);
7278 
7279     return ajTrue;
7280 }
7281 
7282 
7283 
7284 
7285 /* @func ajDirnameFix *********************************************************
7286 **
7287 ** If the directory name has no trailing slash (on Unix) then one is
7288 ** added. This is why the directory name must be writable.
7289 **
7290 ** @param [u] Pdirname [AjPStr*] Directory name.
7291 ** @return [void]
7292 **
7293 ** @release 6.0.0
7294 ** @@
7295 ******************************************************************************/
7296 
ajDirnameFix(AjPStr * Pdirname)7297 void ajDirnameFix(AjPStr* Pdirname)
7298 {
7299     if(ajStrGetCharLast(*Pdirname) != SLASH_CHAR)
7300         ajStrAppendC(Pdirname, SLASH_STRING);
7301 
7302     return;
7303 }
7304 
7305 
7306 
7307 
7308 /* @func ajDirnameFixExists ***************************************************
7309 **
7310 ** Checks that a string is a valid existing directory, and appends a
7311 ** trailing '/' if it is missing.
7312 **
7313 ** @param [u] Pdirname [AjPStr*] Directory path
7314 ** @return [AjBool] true if a valid directory.
7315 **
7316 ** @release 6.0.0
7317 ** @@
7318 ******************************************************************************/
7319 
ajDirnameFixExists(AjPStr * Pdirname)7320 AjBool ajDirnameFixExists(AjPStr* Pdirname)
7321 {
7322     DIR* odir;
7323 
7324     odir = fileOpenDir(Pdirname);       /* appends trailing slash if needed */
7325 
7326     if(!odir)
7327         return ajFalse;
7328 
7329     closedir(odir);
7330 
7331     return ajTrue;
7332 }
7333 
7334 
7335 
7336 
7337 /* @func ajDirnameUp **********************************************************
7338 **
7339 ** Changes directory name to one level up
7340 **
7341 ** @param [u] Pdirname [AjPStr*] Directory name.
7342 ** @return [AjBool] ajTrue on success.
7343 **
7344 ** @release 6.0.0
7345 ** @@
7346 ******************************************************************************/
7347 
ajDirnameUp(AjPStr * Pdirname)7348 AjBool ajDirnameUp(AjPStr* Pdirname)
7349 {
7350     AjBool modded = ajFalse;
7351 
7352     const char *p;
7353     const char *q;
7354     ajint len;
7355 
7356     len = ajStrGetLen(*Pdirname);
7357     p   = ajStrGetPtr(*Pdirname);
7358     q   = p + len -2;
7359 
7360     if(q > p)
7361     {
7362         while(q!=p && *q==SLASH_CHAR)
7363             --q;
7364 
7365         while(q!=p && *q!=SLASH_CHAR)
7366             --q;
7367 
7368         if(q-p > 1)
7369         {
7370             ajStrCutEnd(Pdirname, len-(q-p)-1);
7371             modded = ajTrue;
7372         }
7373     }
7374 
7375     return modded;
7376 }
7377 
7378 
7379 
7380 
7381 /* @section Directory name functions ******************************************
7382 **
7383 ** Functions using a directory name
7384 **
7385 ** @nam3rule Print Print directory or filenames
7386 ** @nam4rule Recursive Step through subdirectories
7387 **
7388 ** @suffix Ignore Process list of sub directory names to ignore
7389 ** @argrule * path [const AjPStr] directory name
7390 ** @argrule Ignore ignorelist [AjPList] List of names to ignore
7391 ** @argrule Print outfile [AjPFile] Output file
7392 **
7393 ** @valrule * [void]
7394 **
7395 ** @fcategory use
7396 **
7397 ** @fdata [AjPStr]
7398 **
7399 ******************************************************************************/
7400 
7401 
7402 
7403 
7404 /* @func ajDirnamePrintRecursiveIgnore ****************************************
7405 **
7406 ** Recursively scan through a directory, printing directory and file names
7407 **
7408 ** @param [r] path [const AjPStr] Directory to scan
7409 ** @param [u] ignorelist [AjPList] List of directories to ignore
7410 ** @param [u] outfile [AjPFile] File for "show" results (or NULL)
7411 **
7412 ** @return [void]
7413 **
7414 ** @release 6.0.0
7415 ** @@
7416 ******************************************************************************/
7417 
ajDirnamePrintRecursiveIgnore(const AjPStr path,AjPList ignorelist,AjPFile outfile)7418 void ajDirnamePrintRecursiveIgnore(const AjPStr path,
7419                                    AjPList ignorelist, AjPFile outfile)
7420 {
7421     AjPList dirs = NULL;
7422     AjIList iter = NULL;
7423     DIR *indir;
7424 #if defined(AJ_IRIXLF)
7425     struct dirent64 *dp;
7426 #else /* !AJ_IRIXLF */
7427     struct dirent *dp;
7428 #endif /* AJ_IRIXLF */
7429     AjPStr s = NULL;
7430     AjPStr t = NULL;
7431 
7432     AjPStr tstr = NULL;
7433 
7434     AjBool flag;
7435     AjPStr tpath = NULL;
7436     AjPList plist = NULL;
7437 
7438 #ifdef _POSIX_C_SOURCE
7439     char buf[sizeof(struct dirent)+MAXNAMLEN];
7440 #endif /* _POSIX_C_SOURCE */
7441 
7442     tpath = ajStrNewS(path);
7443 
7444     ajFmtPrintF(outfile,"\n\nDIRECTORY: %S\n\n",path);
7445 
7446     if(!ajDirnameFixExists(&tpath))
7447     {
7448         ajStrDel(&tpath);
7449 
7450         return;
7451     }
7452 
7453 
7454     if(!(indir=opendir(ajStrGetPtr(tpath))))
7455     {
7456         ajStrDel(&tpath);
7457 
7458         return;
7459     }
7460 
7461 
7462     s = ajStrNew();
7463     dirs = ajListNew();
7464     plist = ajListNew();
7465 
7466     while(
7467 #if defined(AJ_IRIXLF)
7468 #ifdef _POSIX_C_SOURCE
7469         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
7470 #else /* !_POSIX_C_SOURCE */
7471         (dp=readdir64(indir))
7472 #endif /* _POSIX_C_SOURCE */
7473 #else /* !AJ_IRIXLF */
7474 #ifdef _POSIX_C_SOURCE
7475         !readdir_r(indir,(struct dirent *)buf,&dp)
7476 #else /* !_POSIX_C_SOURCE */
7477         (dp=readdir(indir))
7478 #endif /* _POSIX_C_SOURCE */
7479 #endif /* AJ_IRIXLF */
7480           )
7481     {
7482 #ifdef _POSIX_C_SOURCE
7483         if(!dp)
7484             break;
7485 #endif /* _POSIX_C_SOURCE */
7486 #ifndef __CYGWIN__
7487         if(!dp->d_ino ||
7488            !strcmp(dp->d_name,".") ||
7489            !strcmp(dp->d_name,".."))
7490             continue;
7491 #else /* __CYGWIN__ */
7492         if(!strcmp(dp->d_name,".") ||
7493            !strcmp(dp->d_name,".."))
7494             continue;
7495 #endif /* !__CYGWIN__ */
7496         ajStrAssignS(&s,tpath);
7497         /*      ajStrAppendC(&s,SLASH_STRING);*/
7498         ajStrAppendC(&s,dp->d_name);
7499 
7500         /* Its a directory */
7501         if(ajFilenameExistsDir(s))
7502         {
7503             /* Ignore selected directories */
7504             if(ajListGetLength(ignorelist))
7505             {
7506                 flag = ajFalse;
7507                 iter = ajListIterNewread(ignorelist);
7508 
7509                 while(!ajListIterDone(iter))
7510                 {
7511                     t = ajListIterGet(iter);
7512 
7513                     if(!strcmp(ajStrGetPtr(t),dp->d_name))
7514                     {
7515                         flag = ajTrue;
7516                         break;
7517                     }
7518                 }
7519 
7520                 ajListIterDel(&iter);
7521 
7522                 if(flag)
7523                     continue;
7524             }
7525 
7526             if(!ajFilenameExistsRead(s) || !ajFilenameExistsExec(s))
7527                 continue;
7528 
7529             t = ajStrNewC(ajStrGetPtr(s));
7530             ajListPushAppend(dirs,(void *)t);
7531         }
7532         else if(ajFilenameExistsRead(s))
7533         {
7534             tstr = ajStrNew();
7535             ajStrAssignC(&tstr,dp->d_name);
7536             ajListPush(plist, (void *)tstr);
7537 
7538 
7539         }
7540     }
7541 
7542     closedir(indir);
7543 
7544     ajListSort(plist, &ajStrVcmp);
7545     while(ajListPop(plist,(void **)&tstr))
7546     {
7547         ajFmtPrintF(outfile,"  %S\n",tstr);
7548         ajStrDel(&tstr);
7549     }
7550 
7551     ajListFree(&plist);
7552 
7553     while(ajListPop(dirs,(void **)&t))
7554     {
7555         ajDirnamePrintRecursiveIgnore(t, ignorelist, outfile);
7556         ajStrDel(&t);
7557     }
7558 
7559     ajStrDel(&s);
7560     ajStrDel(&tpath);
7561     ajListFree(&dirs);
7562 
7563 
7564     return;
7565 }
7566 
7567 
7568 
7569 
7570 /* @datasection [AjPlist] Lists of filenames **********************************
7571 **
7572 ** Functions building and managing lists of filenames
7573 **
7574 ** @nam2rule Filelist
7575 **
7576 ******************************************************************************/
7577 
7578 
7579 
7580 
7581 /* @section File list addition ************************************************
7582 **
7583 ** Functions that add filenames to a list
7584 **
7585 ** @nam3rule Add Adds names to a list
7586 ** @nam4rule Path Directory path provided
7587 ** @nam5rule Wild Wildcard filename provided
7588 ** @suffix Recursive Process subdirectories
7589 ** @suffix Ignore List of subdirectories to be ignored
7590 ** @suffix Directory Directory object provided
7591 ** @suffix Dir Include directories in the list
7592 ** @nam4rule Listname List of files or lists
7593 **
7594 ** @argrule * list [AjPList] Filename list
7595 ** @argrule Listname listname [const AjPStr] Commandline list of filenames
7596 ** @argrule Directory dir [const AjPDir] Directory object
7597 ** @argrule Path path [const AjPStr] Pathname of directory
7598 ** @argrule Wild wildname [const AjPStr] Wildcard filename to add
7599 ** @argrule Ignore ignorelist [AjPList] Subdirectory name list to ignore
7600 **
7601 ** @valrule * [ajint] Number of entries added to the list
7602 **
7603 ** @fcategory modify
7604 **
7605 ** @fdata [AjPlist]
7606 **
7607 ******************************************************************************/
7608 
7609 
7610 
7611 
7612 /* @func ajFilelistAddDirectory ***********************************************
7613 **
7614 ** Scan through a directory object returning all filenames that are
7615 ** not directories. Uses the file extension and any other attributes
7616 ** of the directory object. An empty string as a file extension accepts
7617 ** only files that have no extension.
7618 **
7619 ** @param [u] list [AjPList] List for matching entries
7620 ** @param [r] dir [const AjPDir] Directory to scan
7621 **
7622 ** @return [ajint] number of entries in list
7623 **
7624 ** @release 6.3.0
7625 ** @@
7626 ******************************************************************************/
7627 
ajFilelistAddDirectory(AjPList list,const AjPDir dir)7628 ajint ajFilelistAddDirectory(AjPList list,
7629                              const AjPDir dir)
7630 {
7631     ajulong oldsize;
7632     DIR *indir;
7633 #if defined(AJ_IRIXLF)
7634     struct dirent64 *dp;
7635 #else /* !AJ_IRIXLF */
7636     struct dirent *dp;
7637 #endif /* AJ_IRIXLF */
7638     AjPStr f = NULL;
7639     AjPStr s = NULL;
7640     AjPStr t = NULL;
7641     AjPStr e = NULL;
7642 
7643     AjPStr tpath = NULL;
7644 #ifdef _POSIX_C_SOURCE
7645     char buf[sizeof(struct dirent)+MAXNAMLEN];
7646 #endif /* _POSIX_C_SOURCE */
7647 
7648     AjBool doprefix = AJFALSE;
7649     AjBool doextension = AJFALSE;
7650 
7651     if(!dir)
7652         return 0;
7653 
7654     if(dir->Prefix)
7655         doprefix = ajTrue;
7656     if(dir->Extension)
7657     {
7658         if(ajStrGetCharFirst(dir->Extension) == '.')
7659             e = ajStrNewS(dir->Extension);
7660         else if(ajStrGetLen(dir->Extension))
7661             ajFmtPrintS(&e, ".%S", dir->Extension);
7662 
7663         doextension = ajTrue;
7664     }
7665 
7666     oldsize = ajListGetLength(list);
7667 
7668     tpath = ajStrNewS(dir->Name);
7669 
7670     ajDebug("ajFilelistAddDir '%S' oldsize:%Lu\n",
7671             tpath, oldsize);
7672 
7673     if(!ajDirnameFixExists(&tpath))
7674     {
7675         ajDebug("... not a directory '%S'\n", tpath);
7676         ajStrDel(&tpath);
7677 
7678         return 0;
7679     }
7680 
7681 
7682     if(!(indir=opendir(ajStrGetPtr(tpath))))
7683     {
7684         ajDebug("... failed to open directory '%S'\n", tpath);
7685         ajStrDel(&tpath);
7686 
7687         return 0;
7688     }
7689 
7690 
7691     s = ajStrNew();
7692     f = ajStrNew();
7693 
7694     while(
7695 #if defined(AJ_IRIXLF)
7696 #ifdef _POSIX_C_SOURCE
7697         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
7698 #else /* !_POSIX_C_SOURCE */
7699         (dp=readdir64(indir))
7700 #endif /* _POSIX_C_SOURCE */
7701 #else /* !AJ_IRIXLF */
7702 #ifdef _POSIX_C_SOURCE
7703         !readdir_r(indir,(struct dirent *)buf,&dp)
7704 #else /* !_POSIX_C_SOURCE */
7705         (dp=readdir(indir))
7706 #endif /* _POSIX_C_SOURCE */
7707 #endif /* AJ_IRIXLF */
7708           )
7709     {
7710 #ifdef _POSIX_C_SOURCE
7711         if(!dp)
7712             break;
7713 #endif /* _POSIX_C_SOURCE */
7714 #ifndef __CYGWIN__
7715         if(!dp->d_ino ||
7716            !strcmp(dp->d_name,".") ||
7717            !strcmp(dp->d_name,".."))
7718             continue;
7719 #else /* __CYGWIN__ */
7720         if(!strcmp(dp->d_name,".") ||
7721            !strcmp(dp->d_name,".."))
7722             continue;
7723 #endif /* !__CYGWIN__ */
7724 
7725         ajStrAssignC(&f,dp->d_name);
7726 
7727         if(doprefix && !ajStrPrefixS(f, dir->Prefix))
7728             continue;
7729 
7730         if(doextension)
7731         {
7732             if(e)
7733             {
7734                 if(!ajStrSuffixS(f, e))
7735                     continue;
7736             }
7737             else
7738             {
7739                 if(ajStrFindAnyK(f,'.') >= 0)
7740                     continue;
7741             }
7742         }
7743 
7744         ajStrAssignS(&s,tpath);
7745         ajStrAppendS(&s,f);
7746 
7747         if(ajFilenameExistsDir(s))
7748             continue;
7749 
7750         ajDebug("... add to list '%S'\n",
7751                 s);
7752 
7753         t = ajStrNewS(s);
7754         ajListPushAppend(list,(void *)t);
7755 
7756     }
7757     closedir(indir);
7758 
7759 
7760     ajStrDel(&e);
7761     ajStrDel(&f);
7762     ajStrDel(&s);
7763     ajStrDel(&tpath);
7764 
7765     return (ajuint) (ajListGetLength(list) - oldsize);
7766 }
7767 
7768 
7769 
7770 
7771 /* @func ajFilelistAddListname ************************************************
7772 **
7773 ** Adds to a list of files that match a comma-separated string of
7774 ** filenames which can include wildcards or listfiles
7775 **
7776 ** @param [u] list [AjPList] List of filenames
7777 ** @param [r] listname [const AjPStr] comma-separated filename list
7778 **
7779 ** @return [ajint] Number of entries added to list
7780 **
7781 ** @release 6.0.0
7782 ** @@
7783 ******************************************************************************/
7784 
ajFilelistAddListname(AjPList list,const AjPStr listname)7785 ajint ajFilelistAddListname(AjPList list, const AjPStr listname)
7786 {
7787     ajulong oldsize;
7788     AjPStr *fstr = NULL;
7789     ajint  ncl;
7790     ajint  i;
7791     ajint  rlevel = 0;
7792 
7793     oldsize = ajListGetLength(list);
7794     ncl = ajArrCommaList(listname,&fstr);
7795 
7796     for(i=0;i<ncl;++i)
7797     {
7798         fileListRecurs(fstr[i],list,&rlevel);
7799         ajStrDel(&fstr[i]);
7800     }
7801 
7802     AJFREE(fstr);
7803 
7804     return (ajuint) (ajListGetLength(list) - oldsize);
7805 }
7806 
7807 
7808 
7809 
7810 /* @func ajFilelistAddPath ****************************************************
7811 **
7812 ** Scan through a directory returning all filenames excluding directory names
7813 **
7814 ** @param [u] list [AjPList] List for matching entries
7815 ** @param [r] path [const AjPStr] Directory to scan
7816 **
7817 ** @return [ajint] number of entries in list
7818 **
7819 ** @release 6.0.0
7820 ** @@
7821 ******************************************************************************/
7822 
ajFilelistAddPath(AjPList list,const AjPStr path)7823 ajint ajFilelistAddPath(AjPList list,
7824                         const AjPStr path)
7825 {
7826     ajulong oldsize;
7827     DIR *indir;
7828 #if defined(AJ_IRIXLF)
7829     struct dirent64 *dp;
7830 #else /* !AJ_IRIXLF */
7831     struct dirent *dp;
7832 #endif /* AJ_IRIXLF */
7833     AjPStr s = NULL;
7834     AjPStr t = NULL;
7835     AjPStr tpath = NULL;
7836 #ifdef _POSIX_C_SOURCE
7837     char buf[sizeof(struct dirent)+MAXNAMLEN];
7838 #endif /* _POSIX_C_SOURCE */
7839 
7840     oldsize = ajListGetLength(list);
7841 
7842     tpath = ajStrNewS(path);
7843 
7844     ajDebug("ajFilelistAddPath '%S' oldsize:%Lu\n",
7845             path, oldsize);
7846 
7847     if(!ajDirnameFixExists(&tpath))
7848     {
7849         ajDebug("... not a directory '%S'\n", tpath);
7850         ajStrDel(&tpath);
7851 
7852         return 0;
7853     }
7854 
7855 
7856     if(!(indir=opendir(ajStrGetPtr(tpath))))
7857     {
7858         ajDebug("... failed to open directory '%S'\n", tpath);
7859         ajStrDel(&tpath);
7860 
7861         return 0;
7862     }
7863 
7864 
7865     s = ajStrNew();
7866 
7867     while(
7868 #if defined(AJ_IRIXLF)
7869 #ifdef _POSIX_C_SOURCE
7870         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
7871 #else /* !_POSIX_C_SOURCE */
7872         (dp=readdir64(indir))
7873 #endif /* _POSIX_C_SOURCE */
7874 #else /* !AJ_IRIXLF */
7875 #ifdef _POSIX_C_SOURCE
7876         !readdir_r(indir,(struct dirent *)buf,&dp)
7877 #else /* !_POSIX_C_SOURCE */
7878         (dp=readdir(indir))
7879 #endif /* _POSIX_C_SOURCE */
7880 #endif /* AJ_IRIXLF */
7881           )
7882     {
7883 #ifdef _POSIX_C_SOURCE
7884         if(!dp)
7885             break;
7886 #endif /* _POSIX_C_SOURCE */
7887 #ifndef __CYGWIN__
7888         if(!dp->d_ino ||
7889            !strcmp(dp->d_name,".") ||
7890            !strcmp(dp->d_name,".."))
7891             continue;
7892 #else /* __CYGWIN__ */
7893         if(!strcmp(dp->d_name,".") ||
7894            !strcmp(dp->d_name,".."))
7895             continue;
7896 #endif /* !__CYGWIN__ */
7897         ajStrAssignS(&s,tpath);
7898         ajStrAppendC(&s,dp->d_name);
7899 
7900         ajDebug("... testing '%S'\n",
7901                 s);
7902 
7903         if(ajFilenameExistsDir(s))
7904         {
7905             ajDebug("... rejected: directory '%S'\n",
7906                     s);
7907             continue;
7908         }
7909 
7910         ajDebug("... add to list '%S'\n",
7911                 s);
7912 
7913         t = ajStrNewS(s);
7914         ajListPushAppend(list,(void *)t);
7915 
7916     }
7917 
7918     closedir(indir);
7919 
7920 
7921     ajStrDel(&s);
7922     ajStrDel(&tpath);
7923 
7924     return (ajuint) (ajListGetLength(list) - oldsize);
7925 }
7926 
7927 
7928 
7929 
7930 /* @func ajFilelistAddPathDir *************************************************
7931 **
7932 ** Scan through a directory returning all filenames and directory names
7933 ** except '.' and '..', including directories
7934 **
7935 ** @param [u] list [AjPList] List for matching entries
7936 ** @param [r] path [const AjPStr] Directory to scan
7937 **
7938 ** @return [ajint] number of entries in list
7939 **
7940 ** @release 6.0.0
7941 ** @@
7942 ******************************************************************************/
7943 
ajFilelistAddPathDir(AjPList list,const AjPStr path)7944 ajint ajFilelistAddPathDir(AjPList list,
7945                            const AjPStr path)
7946 {
7947     ajulong oldsize;
7948     DIR *indir;
7949 #if defined(AJ_IRIXLF)
7950     struct dirent64 *dp;
7951 #else /* !AJ_IRIXLF */
7952     struct dirent *dp;
7953 #endif /* AJ_IRIXLF */
7954     AjPStr s = NULL;
7955     AjPStr t = NULL;
7956     AjPStr tpath = NULL;
7957 #ifdef _POSIX_C_SOURCE
7958     char buf[sizeof(struct dirent)+MAXNAMLEN];
7959 #endif /* _POSIX_C_SOURCE */
7960 
7961     oldsize = ajListGetLength(list);
7962 
7963     tpath = ajStrNewS(path);
7964 
7965     ajDebug("ajFilelistAddPath '%S' oldsize:%Lu\n",
7966             path, oldsize);
7967 
7968     if(!ajDirnameFixExists(&tpath))
7969     {
7970         ajDebug("... not a directory '%S'\n", tpath);
7971         ajStrDel(&tpath);
7972 
7973         return 0;
7974     }
7975 
7976 
7977     if(!(indir=opendir(ajStrGetPtr(tpath))))
7978     {
7979         ajDebug("... failed to open directory '%S'\n", tpath);
7980         ajStrDel(&tpath);
7981 
7982         return 0;
7983     }
7984 
7985 
7986     s = ajStrNew();
7987 
7988     while(
7989 #if defined(AJ_IRIXLF)
7990 #ifdef _POSIX_C_SOURCE
7991         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
7992 #else /* !_POSIX_C_SOURCE */
7993         (dp=readdir64(indir))
7994 #endif /* _POSIX_C_SOURCE */
7995 #else /* !AJ_IRIXLF */
7996 #ifdef _POSIX_C_SOURCE
7997         !readdir_r(indir,(struct dirent *)buf,&dp)
7998 #else /* !_POSIX_C_SOURCE */
7999         (dp=readdir(indir))
8000 #endif /* _POSIX_C_SOURCE */
8001 #endif /* AJ_IRIXLF */
8002           )
8003     {
8004 #ifdef _POSIX_C_SOURCE
8005         if(!dp)
8006             break;
8007 #endif /* _POSIX_C_SOURCE */
8008 #ifndef __CYGWIN__
8009         if(!dp->d_ino ||
8010            !strcmp(dp->d_name,".") ||
8011            !strcmp(dp->d_name,".."))
8012             continue;
8013 #else /* __CYGWIN__ */
8014         if(!strcmp(dp->d_name,".") ||
8015            !strcmp(dp->d_name,".."))
8016             continue;
8017 #endif /* !__CYGWIN__ */
8018         ajStrAssignS(&s,tpath);
8019         ajStrAppendC(&s,dp->d_name);
8020 
8021         ajDebug("... add to list '%S'\n",
8022                 s);
8023 
8024         t = ajStrNewS(s);
8025         ajListPushAppend(list,(void *)t);
8026 
8027     }
8028     closedir(indir);
8029 
8030 
8031     ajStrDel(&s);
8032     ajStrDel(&tpath);
8033 
8034     return (ajuint) (ajListGetLength(list) - oldsize);
8035 }
8036 
8037 
8038 
8039 
8040 /* @func ajFilelistAddPathWild ************************************************
8041 **
8042 ** Scan through a directory returning all filenames matching a
8043 ** wildcard filename
8044 **
8045 ** @param [w] list [AjPList] List for matching entries
8046 ** @param [r] path [const AjPStr] Directory to scan
8047 ** @param [r] wildname [const AjPStr] Filename to search for
8048 **
8049 ** @return [ajint] number of entries in list
8050 **
8051 ** @release 6.0.0
8052 ** @@
8053 ******************************************************************************/
8054 
ajFilelistAddPathWild(AjPList list,const AjPStr path,const AjPStr wildname)8055 ajint ajFilelistAddPathWild(AjPList list,
8056                             const AjPStr path,
8057                             const AjPStr wildname)
8058 {
8059     ajulong oldsize;
8060     DIR *indir;
8061 #if defined(AJ_IRIXLF)
8062     struct dirent64 *dp;
8063 #else /* !AJ_IRIXLF */
8064     struct dirent *dp;
8065 #endif /* AJ_IRIXLF */
8066     AjPStr s = NULL;
8067     AjPStr t = NULL;
8068     AjPStr tpath = NULL;
8069 #ifdef _POSIX_C_SOURCE
8070     char buf[sizeof(struct dirent)+MAXNAMLEN];
8071 #endif /* _POSIX_C_SOURCE */
8072 
8073     oldsize = ajListGetLength(list);
8074 
8075     tpath = ajStrNew();
8076     ajStrAssignS(&tpath,path);
8077 
8078 
8079     if(!ajDirnameFixExists(&tpath))
8080     {
8081         ajStrDel(&tpath);
8082 
8083         return 0;
8084     }
8085 
8086 
8087     if(!(indir=opendir(ajStrGetPtr(tpath))))
8088     {
8089         ajStrDel(&tpath);
8090 
8091         return 0;
8092     }
8093 
8094 
8095     s = ajStrNew();
8096 
8097     while(
8098 #if defined(AJ_IRIXLF)
8099 #ifdef _POSIX_C_SOURCE
8100         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
8101 #else /* !_POSIX_C_SOURCE */
8102         (dp=readdir64(indir))
8103 #endif /* _POSIX_C_SOURCE */
8104 #else /* !AJ_IRIXLF */
8105 #ifdef _POSIX_C_SOURCE
8106         !readdir_r(indir,(struct dirent *)buf,&dp)
8107 #else /* !_POSIX_C_SOURCE */
8108         (dp=readdir(indir))
8109 #endif /* _POSIX_C_SOURCE */
8110 #endif /* AJ_IRIXLF */
8111           )
8112     {
8113 #ifdef _POSIX_C_SOURCE
8114         if(!dp)
8115             break;
8116 #endif /* _POSIX_C_SOURCE */
8117 #ifndef __CYGWIN__
8118         if(!dp->d_ino ||
8119            !strcmp(dp->d_name,".") ||
8120            !strcmp(dp->d_name,".."))
8121             continue;
8122 #else /* __CYGWIN__ */
8123         if(!strcmp(dp->d_name,".") ||
8124            !strcmp(dp->d_name,".."))
8125             continue;
8126 #endif /* !__CYGWIN__ */
8127         ajStrAssignS(&s,tpath);
8128         ajStrAppendC(&s,dp->d_name);
8129 
8130         if(ajFilenameExistsDir(s))
8131             continue;
8132 
8133         if(ajCharMatchWildS(dp->d_name,wildname))
8134         {
8135             t = ajStrNewS(s);
8136             ajListPushAppend(list,(void *)t);
8137         }
8138     }
8139     closedir(indir);
8140 
8141 
8142     ajStrDel(&s);
8143     ajStrDel(&tpath);
8144 
8145     return (ajuint) (ajListGetLength(list) - oldsize);
8146 }
8147 
8148 
8149 
8150 
8151 /* @func ajFilelistAddPathWildDir *********************************************
8152 **
8153 ** Scan through a directory returning all filenames matching a
8154 ** wildcard filename, including directories
8155 **
8156 ** @param [w] list [AjPList] List for matching entries
8157 ** @param [r] path [const AjPStr] Directory to scan
8158 ** @param [r] wildname [const AjPStr] Filename to search for
8159 **
8160 ** @return [ajint] number of entries in list
8161 **
8162 ** @release 6.0.0
8163 ** @@
8164 ******************************************************************************/
8165 
ajFilelistAddPathWildDir(AjPList list,const AjPStr path,const AjPStr wildname)8166 ajint ajFilelistAddPathWildDir(AjPList list,
8167                                const AjPStr path,
8168                                const AjPStr wildname)
8169 {
8170     ajulong oldsize;
8171     DIR *indir;
8172 #if defined(AJ_IRIXLF)
8173     struct dirent64 *dp;
8174 #else /* !AJ_IRIXLF */
8175     struct dirent *dp;
8176 #endif /* AJ_IRIXLF */
8177     AjPStr s = NULL;
8178     AjPStr t = NULL;
8179     AjPStr tpath = NULL;
8180 #ifdef _POSIX_C_SOURCE
8181     char buf[sizeof(struct dirent)+MAXNAMLEN];
8182 #endif /* _POSIX_C_SOURCE */
8183 
8184     oldsize = ajListGetLength(list);
8185 
8186     tpath = ajStrNew();
8187     ajStrAssignS(&tpath,path);
8188 
8189 
8190     if(!ajDirnameFixExists(&tpath))
8191     {
8192         ajStrDel(&tpath);
8193 
8194         return 0;
8195     }
8196 
8197 
8198     if(!(indir=opendir(ajStrGetPtr(tpath))))
8199     {
8200         ajStrDel(&tpath);
8201 
8202         return 0;
8203     }
8204 
8205 
8206     s = ajStrNew();
8207 
8208     while(
8209 #if defined(AJ_IRIXLF)
8210 #ifdef _POSIX_C_SOURCE
8211         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
8212 #else /* !_POSIX_C_SOURCE */
8213         (dp=readdir64(indir))
8214 #endif /* _POSIX_C_SOURCE */
8215 #else /* !AJ_IRIXLF */
8216 #ifdef _POSIX_C_SOURCE
8217         !readdir_r(indir,(struct dirent *)buf,&dp)
8218 #else /* !_POSIX_C_SOURCE */
8219         (dp=readdir(indir))
8220 #endif /* _POSIX_C_SOURCE */
8221 #endif /* AJ_IRIXLF */
8222           )
8223     {
8224 #ifdef _POSIX_C_SOURCE
8225         if(!dp)
8226             break;
8227 #endif /* _POSIX_C_SOURCE */
8228 #ifndef __CYGWIN__
8229         if(!dp->d_ino ||
8230            !strcmp(dp->d_name,".") ||
8231            !strcmp(dp->d_name,".."))
8232             continue;
8233 #else /* __CYGWIN__ */
8234         if(!strcmp(dp->d_name,".") ||
8235            !strcmp(dp->d_name,".."))
8236             continue;
8237 #endif /* !__CYGWIN__ */
8238         ajStrAssignS(&s,tpath);
8239         ajStrAppendC(&s,dp->d_name);
8240 
8241         if(ajCharMatchWildS(dp->d_name,wildname))
8242         {
8243             t = ajStrNewS(s);
8244             ajListPushAppend(list,(void *)t);
8245         }
8246     }
8247 
8248     closedir(indir);
8249 
8250 
8251     ajStrDel(&s);
8252     ajStrDel(&tpath);
8253 
8254     return (ajuint) (ajListGetLength(list) - oldsize);
8255 }
8256 
8257 
8258 
8259 
8260 /* @funcstatic fileListRecurs  ************************************************
8261 **
8262 ** Add a filename, expanded wildcard filenames and list file contents to
8263 ** a list
8264 **
8265 ** @param [r] srcfile [const AjPStr] filename, wild filename or list filename
8266 ** @param [u] list [AjPList] result filename list
8267 ** @param [u] recurs [ajint *] recursion level counter
8268 **
8269 ** @return [void]
8270 **
8271 ** @release 2.5.0
8272 ** @@
8273 ******************************************************************************/
8274 
fileListRecurs(const AjPStr srcfile,AjPList list,ajint * recurs)8275 static void fileListRecurs(const AjPStr srcfile, AjPList list, ajint *recurs)
8276 {
8277     char c;
8278     AjPStr ptr = NULL;
8279     AjPStr dir = NULL;
8280     char   *p;
8281     AjPList dlist;
8282     AjPFile inf;
8283     AjPStr  line = NULL;
8284     AjPStr file  = NULL;
8285 
8286     ++(*recurs);
8287 
8288     if(*recurs > FILERECURSLV)
8289         ajFatal("Filelist maximum recursion level reached");
8290 
8291     ajStrAssignS(&file, srcfile);
8292     ajStrTrimWhite(&file);
8293     c = *ajStrGetPtr(file);
8294 
8295     dir   = ajStrNew();
8296     line  = ajStrNew();
8297     dlist = ajListNew();
8298 
8299 
8300     if(ajStrIsWild(file))
8301     {
8302         if(!(p=strrchr(ajStrGetPtr(file),(int)SLASH_CHAR)))
8303             ajStrAssignC(&dir,CURRENT_DIR);
8304         else
8305             ajStrAssignSubC(&dir,ajStrGetPtr(file),0,p-ajStrGetPtr(file));
8306 
8307         ajFilelistAddPathWild(dlist, dir, file);
8308 
8309         while(ajListPop(dlist,(void **)&ptr))
8310         {
8311             if(ajStrPrefixC(ptr,CURRENT_DIR))
8312                 ajStrCutStart(&ptr,2);
8313 
8314             ajListPushAppend(list,(void *)ptr);
8315         }
8316     }
8317     else if(c=='@')
8318     {
8319         if((inf=ajFileNewInNameC(ajStrGetPtr(file)+1)))
8320             while(ajReadlineTrim(inf,&line))
8321                 fileListRecurs(line,list,recurs);
8322         if(inf)
8323             ajFileClose(&inf);
8324     }
8325     else if(ajStrPrefixC(file,"list::"))
8326     {
8327         if((inf=ajFileNewInNameC(ajStrGetPtr(file)+6)))
8328             while(ajReadlineTrim(inf,&line))
8329                 fileListRecurs(line,list,recurs);
8330         if(inf)
8331             ajFileClose(&inf);
8332     }
8333     else
8334     {
8335         ptr = ajStrNewC(ajStrGetPtr(file));
8336         ajListPushAppend(list,(void *)ptr);
8337     }
8338 
8339 
8340     ajListFree(&dlist);
8341     ajStrDel(&dir);
8342     ajStrDel(&line);
8343     ajStrDel(&file);
8344 
8345     --(*recurs);
8346 
8347     return;
8348 }
8349 
8350 
8351 
8352 
8353 /* @func ajFilelistAddPathWildRecursiveIgnore *********************************
8354 **
8355 ** Recursively scan through a directory
8356 **
8357 ** @param [u] list [AjPList] List for matching filenames
8358 ** @param [r] path [const AjPStr] Directory to scan
8359 ** @param [r] wildname [const AjPStr] Filename to search for (or NULL)
8360 ** @param [u] ignorelist [AjPList] List of directories to ignore
8361 **
8362 ** @return [ajint] number of new entries in list
8363 **
8364 ** @release 6.0.0
8365 ** @@
8366 ******************************************************************************/
8367 
ajFilelistAddPathWildRecursiveIgnore(AjPList list,const AjPStr path,const AjPStr wildname,AjPList ignorelist)8368 ajint ajFilelistAddPathWildRecursiveIgnore(AjPList list,
8369                                            const AjPStr path,
8370                                            const AjPStr wildname,
8371                                            AjPList ignorelist)
8372 {
8373     ajulong oldsize;
8374     AjPList dirs = NULL;
8375     AjIList iter = NULL;
8376     DIR *indir;
8377 #if defined(AJ_IRIXLF)
8378     struct dirent64 *dp;
8379 #else /* !AJ_IRIXLF */
8380     struct dirent *dp;
8381 #endif /* AJ_IRIXLF */
8382     AjPStr s = NULL;
8383     AjPStr t = NULL;
8384     AjBool flag;
8385     AjPStr tpath = NULL;
8386 #ifdef _POSIX_C_SOURCE
8387     char buf[sizeof(struct dirent)+MAXNAMLEN];
8388 #endif /* _POSIX_C_SOURCE */
8389 
8390     oldsize = ajListGetLength(list);
8391 
8392     tpath = ajStrNew();
8393     ajStrAssignS(&tpath,path);
8394 
8395     if(!ajDirnameFixExists(&tpath))
8396     {
8397         ajStrDel(&tpath);
8398 
8399         return 0;
8400     }
8401 
8402 
8403     if(!(indir=opendir(ajStrGetPtr(tpath))))
8404     {
8405         ajStrDel(&tpath);
8406 
8407         return 0;
8408     }
8409 
8410 
8411     s = ajStrNew();
8412     dirs = ajListNew();
8413 
8414     while(
8415 #if defined(AJ_IRIXLF)
8416 #ifdef _POSIX_C_SOURCE
8417         !readdir64_r(indir,(struct dirent64 *)buf,&dp)
8418 #else /* !_POSIX_C_SOURCE */
8419         (dp=readdir64(indir))
8420 #endif /* _POSIX_C_SOURCE */
8421 #else /* !AJ_IRIXLF */
8422 #ifdef _POSIX_C_SOURCE
8423         !readdir_r(indir,(struct dirent *)buf,&dp)
8424 #else /* !_POSIX_C_SOURCE */
8425         (dp=readdir(indir))
8426 #endif /* _POSIX_C_SOURCE */
8427 #endif /* AJ_IRIXLF */
8428           )
8429     {
8430 #ifdef _POSIX_C_SOURCE
8431         if(!dp)
8432             break;
8433 #endif /* _POSIX_C_SOURCE */
8434 #ifndef __CYGWIN__
8435         if(!dp->d_ino ||
8436            !strcmp(dp->d_name,".") ||
8437            !strcmp(dp->d_name,".."))
8438             continue;
8439 #else /* __CYGWIN__ */
8440         if(!strcmp(dp->d_name,".") ||
8441            !strcmp(dp->d_name,".."))
8442             continue;
8443 #endif /* !__CYGWIN__ */
8444         ajStrAssignS(&s,tpath);
8445         /*      ajStrAppendC(&s,SLASH_STRING);*/
8446         ajStrAppendC(&s,dp->d_name);
8447 
8448         /* Its a directory */
8449         if(ajFilenameExistsDir(s))
8450         {
8451             /* Ignore selected directories */
8452             if(ajListGetLength(ignorelist))
8453             {
8454                 flag = ajFalse;
8455                 iter = ajListIterNewread(ignorelist);
8456 
8457                 while(!ajListIterDone(iter))
8458                 {
8459                     t = ajListIterGet(iter);
8460 
8461                     if(!strcmp(ajStrGetPtr(t),dp->d_name))
8462                     {
8463                         flag = ajTrue;
8464                         break;
8465                     }
8466                 }
8467 
8468                 ajListIterDel(&iter);
8469 
8470                 if(flag)
8471                     continue;
8472             }
8473 
8474             if(!ajFilenameExistsRead(s) || !ajFilenameExistsExec(s))
8475                 continue;
8476 
8477             t = ajStrNewC(ajStrGetPtr(s));
8478             ajListPushAppend(dirs,(void *)t);
8479         }
8480         else if(ajFilenameExistsRead(s))
8481         {
8482             if(ajStrGetLen(wildname))
8483                 if(ajCharMatchWildS(dp->d_name,wildname))
8484                 {
8485                     t = ajStrNewS(s);
8486                     ajListPushAppend(list,(void *)t);
8487                 }
8488 
8489             /*ajDebug("  %s\n",dp->d_name);*/
8490         }
8491     }
8492 
8493     closedir(indir);
8494 
8495     while(ajListPop(dirs,(void **)&t))
8496     {
8497         ajFilelistAddPathWildRecursiveIgnore(list, t,wildname, ignorelist);
8498         ajStrDel(&t);
8499     }
8500 
8501     ajStrDel(&s);
8502     ajStrDel(&tpath);
8503     ajListFree(&dirs);
8504 
8505     return (ajuint) (ajListGetLength(list) - oldsize);
8506 }
8507 
8508 
8509 
8510 
8511 /* @datasection [none] File internal values ***********************************
8512 **
8513 ** Functions returning internal values and system parameters
8514 **
8515 ** @nam2rule File
8516 **
8517 ******************************************************************************/
8518 
8519 
8520 
8521 
8522 /* @section Internal values ***************************************************
8523 **
8524 ** Internal values and system parameters
8525 **
8526 ** @nam3rule Value Return a value
8527 ** @nam4rule Buffsize Internal buffer size default
8528 ** @nam4rule Cwd Current working directory
8529 ** @nam4rule Redirect Test whether a system file is redirected to
8530 **                    a file object
8531 ** @nam5rule RedirectStderr Test redirection of standard error
8532 ** @nam5rule RedirectStdin  Test redirection of standard input
8533 ** @nam5rule RedirectStdout Test redirection of standard output
8534 **
8535 ** @valrule *Cwd [const AjPStr] True on success
8536 ** @valrule *Buffsize [ajuint] Buffer size
8537 ** @valrule Redirect [AjBool] True if file is redirected.
8538 **
8539 ** @fcategory misc
8540 **
8541 ** @fdata [none]
8542 **
8543 ******************************************************************************/
8544 
8545 
8546 
8547 
8548 /* @func ajFileValueBuffsize **************************************************
8549 **
8550 ** Returns the default buffer size for a file
8551 **
8552 ** @return [ajuint] Buffer size default value
8553 **
8554 ** @release 6.0.0
8555 ******************************************************************************/
8556 
ajFileValueBuffsize(void)8557 ajuint ajFileValueBuffsize(void)
8558 {
8559     return fileBuffSize;
8560 }
8561 
8562 
8563 
8564 
8565 /* @func ajFileValueCwd *******************************************************
8566 **
8567 ** Returns the current directory
8568 **
8569 ** @return [const AjPStr] Directory name.
8570 **
8571 ** @release 6.0.0
8572 ** @@
8573 ******************************************************************************/
8574 
ajFileValueCwd(void)8575 const AjPStr ajFileValueCwd(void)
8576 {
8577     char cwd[PATH_MAX+1];
8578 
8579     if(!getcwd(cwd,PATH_MAX))
8580     {
8581         ajStrAssignClear(&fileCwd);
8582 
8583         return fileCwd;
8584     }
8585 
8586 
8587     ajStrAssignC(&fileCwd, cwd);
8588 
8589     if(!ajStrSuffixC(fileCwd, SLASH_STRING))
8590         ajStrAppendC(&fileCwd, SLASH_STRING);
8591 
8592     return fileCwd;
8593 }
8594 
8595 
8596 
8597 
8598 /* @func ajFileValueRedirectStderr ********************************************
8599 **
8600 ** Tests whether stderr is in use by an internal file
8601 **
8602 ** @return [AjBool] ajTrue if the file matches stderr.
8603 **
8604 ** @release 6.0.0
8605 ** @@
8606 ******************************************************************************/
8607 
ajFileValueRedirectStderr(void)8608 AjBool ajFileValueRedirectStderr(void)
8609 {
8610     return fileUsedStderr;
8611 }
8612 
8613 
8614 
8615 
8616 /* @func ajFileValueRedirectStdin *********************************************
8617 **
8618 ** Tests whether stdin is in use by an internal file
8619 **
8620 ** @return [AjBool] ajTrue if the file matches stdin.
8621 **
8622 ** @release 6.0.0
8623 ** @@
8624 ******************************************************************************/
8625 
ajFileValueRedirectStdin(void)8626 AjBool ajFileValueRedirectStdin(void)
8627 {
8628     return fileUsedStdin;
8629 }
8630 
8631 
8632 
8633 
8634 /* @func ajFileValueRedirectStdout ********************************************
8635 **
8636 ** Tests whether stdout is in use by an internal file
8637 **
8638 ** @return [AjBool] ajTrue if the file matches stdout.
8639 **
8640 ** @release 6.0.0
8641 ** @@
8642 ******************************************************************************/
8643 
ajFileValueRedirectStdout(void)8644 AjBool ajFileValueRedirectStdout(void)
8645 {
8646     return fileUsedStdout;
8647 }
8648 
8649 
8650 
8651 
8652 /* @funcstatic filePrintname **************************************************
8653 **
8654 ** Create a printable version of a filename
8655 **
8656 ** @param [r] name [const AjPStr] File name
8657 ** @param [w] Pprintname [AjPStr*] Printable filename
8658 ** @return [void]
8659 **
8660 ** @release 6.4.0
8661 ******************************************************************************/
8662 
filePrintname(const AjPStr name,AjPStr * Pprintname)8663 static void filePrintname(const AjPStr name, AjPStr* Pprintname)
8664 {
8665 
8666     ajStrAssignS(Pprintname, name);
8667 #ifdef WIN32
8668     ajStrExchangeKK(Pprintname, '/', '\\');
8669     if(ajStrPrefixC(*Pprintname, ".\\"))
8670         ajStrCutStart(Pprintname, 2);
8671 #else /* !WIN32 */
8672     ajStrExchangeCC(Pprintname, "//", "/");
8673 #endif /* WIN32 */
8674 
8675     return;
8676 }
8677 
8678 
8679 
8680 
8681 #ifdef AJ_COMPILE_DEPRECATED_BOOK
8682 #endif
8683 
8684 
8685 
8686 
8687 #ifdef AJ_COMPILE_DEPRECATED
8688 /* @obsolete ajDirOutNewSS
8689 ** @remove Use ajDiroutNewPathExt (prefix not relevant)
8690 */
ajDirOutNewSS(const AjPStr name,const AjPStr prefix,const AjPStr ext)8691 __deprecated AjPDir ajDirOutNewSS(const AjPStr name,
8692                                   const AjPStr prefix, const AjPStr ext)
8693 {
8694     (void) name;
8695     (void) prefix;
8696     (void) ext;
8697 
8698     return NULL;
8699 }
8700 
8701 
8702 
8703 
8704 /* @obsolete ajDirNew
8705 ** @rename ajDirNewPath
8706 */
ajDirNew(const AjPStr name)8707 __deprecated AjPDir ajDirNew(const AjPStr name)
8708 {
8709     return ajDirNewPath(name);
8710 }
8711 
8712 
8713 
8714 
8715 /* @obsolete ajDirNewS
8716 ** @rename ajDirNewPathExt
8717 */
ajDirNewS(const AjPStr name,const AjPStr ext)8718 __deprecated AjPDir ajDirNewS(const AjPStr name, const AjPStr ext)
8719 {
8720     return ajDirNewPathExt(name, ext);
8721 }
8722 
8723 
8724 
8725 
8726 /* @obsolete ajDirNewSS
8727 ** @rename ajDirNewPathPreExt
8728 */
ajDirNewSS(const AjPStr name,const AjPStr prefix,const AjPStr ext)8729 __deprecated AjPDir ajDirNewSS(const AjPStr name,
8730                                const AjPStr prefix, const AjPStr ext)
8731 {
8732     return ajDirNewPathPreExt(name,prefix,ext);
8733 }
8734 
8735 
8736 
8737 
8738 /* @obsolete ajDirExt
8739 ** @rename ajDirGetExt
8740 */
ajDirExt(const AjPDir thys)8741 __deprecated const AjPStr ajDirExt(const AjPDir thys)
8742 {
8743     return ajDirGetExt(thys);
8744 }
8745 
8746 
8747 
8748 
8749 /* @obsolete ajDirName
8750 ** @rename ajDirGetPath
8751 */
ajDirName(const AjPDir thys)8752 __deprecated const AjPStr ajDirName(const AjPDir thys)
8753 {
8754     return ajDirGetPath(thys);
8755 }
8756 
8757 
8758 
8759 
8760 /* @obsolete ajDirOutNew
8761 ** @remove Use ajDiroutNewPath
8762 */
ajDirOutNew(const AjPStr name)8763 __deprecated AjPDir ajDirOutNew(const AjPStr name)
8764 {
8765     (void)name;
8766     return NULL;
8767 }
8768 
8769 
8770 
8771 
8772 /* @obsolete ajDirOutNewS
8773 ** @remove Use ajDiroutNewPathExt
8774 */
ajDirOutNewS(const AjPStr name,const AjPStr ext)8775 __deprecated AjPDir ajDirOutNewS(const AjPStr name, const AjPStr ext)
8776 {
8777     (void)name;
8778     (void)ext;
8779 
8780     return NULL;
8781 }
8782 
8783 
8784 
8785 
8786 /* @obsolete ajFileStat
8787 ** @remove Use ajFilenameExists ajFileNameExistsRead ajFilenameExistsWrite
8788 **             or ajFileNameExistsExec
8789 */
ajFileStat(const AjPStr fname,ajint mode)8790 __deprecated AjBool ajFileStat(const AjPStr fname, ajint mode)
8791 {
8792 #if defined(AJ_IRIXLF)
8793     struct stat64 buf;
8794 #else /* !AJ_IRIXLF */
8795     struct stat buf;
8796 #endif /* AJ_IRIXLF */
8797 
8798     if(
8799 #if defined(AJ_IRIXLF)
8800         !stat64(ajStrGetPtr(fname), &buf)
8801 #else /* !AJ_IRIXLF */
8802         !stat(ajStrGetPtr(fname), &buf)
8803 #endif /* AJ_IRIXLF */
8804        )
8805         if((ajuint)buf.st_mode & mode)
8806             return ajTrue;
8807 
8808     return ajFalse;
8809 }
8810 
8811 
8812 
8813 
8814 /* @obsolete ajFileNameValid
8815 ** @rename ajFilenameExistsRead
8816 */
ajFileNameValid(const AjPStr fname)8817 __deprecated AjBool ajFileNameValid (const AjPStr fname)
8818 {
8819     return ajFilenameExistsRead(fname);
8820 }
8821 
8822 
8823 
8824 
8825 /* @obsolete ajFileLength
8826 ** @rename ajFilenameGetSize
8827 */
ajFileLength(const AjPStr fname)8828 __deprecated ajlong ajFileLength(const AjPStr fname)
8829 {
8830     return ajFilenameGetSize(fname);
8831 }
8832 
8833 
8834 
8835 
8836 /* @obsolete ajFileHasDir
8837 ** @rename ajFilenameHasPath
8838 */
ajFileHasDir(const AjPStr name)8839 __deprecated AjBool ajFileHasDir(const AjPStr name)
8840 {
8841     return ajFilenameHasPath(name);
8842 }
8843 
8844 
8845 
8846 
8847 /* @obsolete ajFileTestSkip
8848 ** @remove Use ajFilenameTestExclude ajFilenameTestInclude and *Path
8849 */
ajFileTestSkip(const AjPStr fullname,const AjPStr exc,const AjPStr inc,AjBool keep,AjBool ignoredirectory)8850 __deprecated AjBool ajFileTestSkip(const AjPStr fullname,
8851                                    const AjPStr exc, const AjPStr inc,
8852                                    AjBool keep, AjBool ignoredirectory)
8853 {
8854     if(ignoredirectory)
8855     {
8856         if(keep)
8857             return ajFilenameTestInclude(fullname, exc, inc);
8858         else
8859             return ajFilenameTestExclude(fullname, exc, inc);
8860     }
8861 
8862     if(keep)
8863         return ajFilenameTestIncludePath(fullname, exc, inc);
8864 
8865     return ajFilenameTestExcludePath(fullname, exc, inc);
8866 }
8867 
8868 
8869 
8870 
8871 /* @obsolete ajFileNameExtC
8872 ** @rename ajFilenameReplaceExtC
8873 */
ajFileNameExtC(AjPStr * filename,const char * extension)8874 __deprecated AjBool ajFileNameExtC(AjPStr* filename, const char* extension)
8875 {
8876     return ajFilenameReplaceExtC(filename, extension);
8877 }
8878 
8879 
8880 
8881 
8882 /* @obsolete ajFileNameExt
8883 ** @rename ajFilenameReplaceExtS
8884 */
ajFileNameExt(AjPStr * filename,const AjPStr extension)8885 __deprecated AjBool ajFileNameExt(AjPStr* filename, const AjPStr extension)
8886 {
8887     return ajFilenameReplaceExtS(filename, extension);
8888 }
8889 
8890 
8891 
8892 
8893 /* @obsolete ajFileNameDirSetC
8894 ** @rename ajFilenameReplacePathC
8895 */
ajFileNameDirSetC(AjPStr * filename,const char * dir)8896 __deprecated AjBool ajFileNameDirSetC(AjPStr* filename, const char* dir)
8897 {
8898     return ajFilenameReplacePathC(filename, dir);
8899 }
8900 
8901 
8902 
8903 
8904 /* @obsolete ajFileNameDirSet
8905 ** @rename ajFilenameReplacePathS
8906 */
ajFileNameDirSet(AjPStr * filename,const AjPStr dir)8907 __deprecated AjBool ajFileNameDirSet(AjPStr* filename, const AjPStr dir)
8908 {
8909     return ajFilenameReplacePathS(filename, dir);
8910 }
8911 
8912 
8913 
8914 
8915 /* @obsolete ajFileSetDir
8916 ** @rename ajFilenameReplacePathS
8917 */
ajFileSetDir(AjPStr * pname,const AjPStr dir)8918 __deprecated AjBool ajFileSetDir (AjPStr *pname, const AjPStr dir)
8919 
8920 {
8921     return ajFilenameReplacePathS(pname, dir);
8922 }
8923 
8924 
8925 
8926 
8927 /* @obsolete ajFileNewF
8928 ** @rename ajFileNewFromCfile
8929 */
ajFileNewF(FILE * file)8930 __deprecated AjPFile ajFileNewF(FILE* file)
8931 {
8932     return ajFileNewFromCfile(file);
8933 }
8934 
8935 
8936 
8937 
8938 /* @obsolete ajFileTempName
8939 ** @remove Use ajFilenameSetTempname or ajFilenameSetTempnamePath
8940 */
ajFileTempName(const char * dir)8941 __deprecated const char* ajFileTempName(const char *dir)
8942 {
8943     AjPStr tmpstr = NULL;
8944 
8945     (void) dir;
8946     ajFilenameSetTempname(&tmpstr);
8947 
8948     return ajStrGetPtr(tmpstr);
8949 }
8950 
8951 
8952 
8953 
8954 /* @obsolete ajFileNameShorten
8955 ** @rename ajFilenameTrimAll
8956 */
ajFileNameShorten(AjPStr * fname)8957 __deprecated AjBool ajFileNameShorten(AjPStr* fname)
8958 {
8959     return ajFilenameTrimAll(fname);
8960 }
8961 
8962 
8963 
8964 
8965 /* @obsolete ajFileExtnTrim
8966 ** @rename ajFilenameTrimExt
8967 */
ajFileExtnTrim(AjPStr * name)8968 __deprecated AjBool ajFileExtnTrim(AjPStr* name)
8969 {
8970     return ajFilenameTrimExt(name);
8971 }
8972 
8973 
8974 
8975 
8976 /* @obsolete ajFileNew
8977 ** @remove Use a constructor that opens a real file
8978 */
8979 
ajFileNew(void)8980 __deprecated AjPFile ajFileNew(void)
8981 {
8982     return fileNew();
8983 }
8984 
8985 
8986 
8987 
8988 /* @obsolete ajFileNewInC
8989 ** @rename ajFileNewInNameC
8990 */
8991 
ajFileNewInC(const char * name)8992 __deprecated AjPFile ajFileNewInC(const char *name)
8993 {
8994     return ajFileNewInNameC(name);
8995 }
8996 
8997 
8998 
8999 
9000 /* @obsolete ajFileNewIn
9001 ** @rename ajFileNewInNameS
9002 */
ajFileNewIn(const AjPStr name)9003 __deprecated AjPFile ajFileNewIn(const AjPStr name)
9004 {
9005 
9006     return ajFileNewInNameS(name);
9007 }
9008 
9009 
9010 
9011 
9012 /* @obsolete ajFileNewDC
9013 ** @remove Use ajFileNewInNamePathS
9014 */
ajFileNewDC(const AjPStr dir,const char * filename)9015 __deprecated AjPFile ajFileNewDC(const AjPStr dir, const char* filename)
9016 {
9017     ajStrAssignC(&fileNameStrTmp, filename);
9018     return ajFileNewInNamePathS(fileNameStrTmp, dir);
9019 }
9020 
9021 
9022 
9023 
9024 /* @obsolete ajFileNewDF
9025 ** @replace ajFileNewInNamePathS (1,2/2,1)
9026 */
ajFileNewDF(const AjPStr dir,const AjPStr filename)9027 __deprecated AjPFile ajFileNewDF(const AjPStr dir, const AjPStr filename)
9028 {
9029     return ajFileNewInNamePathS(filename, dir);
9030 }
9031 
9032 
9033 
9034 
9035 /* @obsolete ajFileNewInList
9036 ** @rename ajFileNewListinList
9037 */
9038 
ajFileNewInList(AjPList list)9039 __deprecated AjPFile ajFileNewInList(AjPList list)
9040 {
9041     return ajFileNewListinList(list);
9042 }
9043 
9044 
9045 
9046 
9047 /* @obsolete ajFileNewDirF
9048 ** @rename ajFileNewListinDirPre
9049 */
ajFileNewDirF(const AjPDir dir,const AjPStr filename)9050 __deprecated AjPFile ajFileNewDirF(const AjPDir dir, const AjPStr filename)
9051 {
9052     return ajFileNewListinDirPre(dir,filename);
9053 }
9054 
9055 
9056 
9057 
9058 /* @obsolete ajFileNewDW
9059 ** @rename ajFileNewListinPathWild
9060 */
9061 
ajFileNewDW(const AjPStr dir,const AjPStr wildfile)9062 __deprecated AjPFile ajFileNewDW(const AjPStr dir, const AjPStr wildfile)
9063 {
9064     return ajFileNewListinPathWild(dir, wildfile);
9065 }
9066 
9067 
9068 
9069 
9070 /* @obsolete ajFileNewDWE
9071 ** @rename ajFileNewListinPathWildExclude
9072 */
ajFileNewDWE(const AjPStr dir,const AjPStr wildfile,const AjPStr exclude)9073 __deprecated AjPFile ajFileNewDWE(const AjPStr dir, const AjPStr wildfile,
9074                                   const AjPStr exclude)
9075 {
9076     return ajFileNewListinPathWildExclude(dir, wildfile, exclude);
9077 }
9078 
9079 
9080 
9081 
9082 /* @obsolete ajFileNewOut
9083 ** @rename ajFileNewOutNameS
9084 */
ajFileNewOut(const AjPStr name)9085 __deprecated AjPFile ajFileNewOut(const AjPStr name)
9086 {
9087     return ajFileNewOutNameS(name);
9088 }
9089 
9090 
9091 
9092 
9093 /* @obsolete ajFileNewOutDir
9094 ** @replace ajFileNewOutNameDirS (1,2/2,1)
9095 */
ajFileNewOutDir(const AjPDirout dir,const AjPStr name)9096 __deprecated AjPFile ajFileNewOutDir(const AjPDirout dir, const AjPStr name)
9097 {
9098     return ajFileNewOutNameDirS(name, dir);
9099 }
9100 
9101 
9102 
9103 
9104 /* @obsolete ajFileNewOutD
9105 ** @replace ajFileNewOutNamePathS (1,2/2,1)
9106 */
ajFileNewOutD(const AjPStr dir,const AjPStr name)9107 __deprecated AjPFile ajFileNewOutD(const AjPStr dir, const AjPStr name)
9108 {
9109     return ajFileNewOutNamePathS(name, dir);
9110 }
9111 
9112 
9113 
9114 
9115 /* @obsolete ajFileNewApp
9116 ** @rename ajFileNewOutappendNameS
9117 */
ajFileNewApp(const AjPStr name)9118 __deprecated AjPFile ajFileNewApp(const AjPStr name)
9119 {
9120 
9121     return ajFileNewOutappendNameS(name);
9122 }
9123 
9124 
9125 
9126 
9127 /* @obsolete ajFileReopen
9128 ** @rename ajFileReopenName
9129 */
ajFileReopen(AjPFile thys,const AjPStr name)9130 __deprecated FILE* ajFileReopen(AjPFile thys, const AjPStr name)
9131 {
9132     ajFileReopenName(thys, name);
9133 
9134     return thys->fp;
9135 }
9136 
9137 
9138 
9139 
9140 /* @obsolete ajFileNext
9141 ** @rename ajFileReopenNext
9142 */
ajFileNext(AjPFile thys)9143 __deprecated AjBool ajFileNext(AjPFile thys)
9144 {
9145     return ajFileReopenNext(thys);
9146 }
9147 
9148 
9149 
9150 
9151 /* @obsolete ajFileTell
9152 ** @rename ajFileResetPos
9153 */
ajFileTell(AjPFile file)9154 __deprecated ajlong ajFileTell(AjPFile file)
9155 {
9156     return ajFileResetPos(file);
9157 }
9158 
9159 
9160 
9161 
9162 /* @obsolete ajFileUnbuffer
9163 ** @rename ajFileSetUnbuffer
9164 */
ajFileUnbuffer(AjPFile thys)9165 __deprecated void ajFileUnbuffer(AjPFile thys)
9166 {
9167     ajFileSetUnbuffer(thys);
9168 
9169     return;
9170 }
9171 
9172 
9173 
9174 
9175 /* @obsolete ajFileFp
9176 ** @rename ajFileGetFileptr
9177 */
ajFileFp(const AjPFile thys)9178 __deprecated FILE* ajFileFp(const AjPFile thys)
9179 {
9180     return ajFileGetFileptr(thys);
9181 }
9182 
9183 
9184 
9185 
9186 /* @obsolete ajFileName
9187 ** @rename ajFileGetNameC
9188 */
ajFileName(const AjPFile file)9189 __deprecated const char* ajFileName(const AjPFile file)
9190 {
9191     return ajFileGetNameC(file);
9192 }
9193 
9194 
9195 
9196 
9197 /* @obsolete ajFileNameS
9198 ** @rename ajFileGetNameS
9199 */
ajFileNameS(const AjPFile file)9200 __deprecated const AjPStr ajFileNameS(const AjPFile file)
9201 {
9202     return ajFileGetNameS(file);
9203 }
9204 
9205 
9206 
9207 
9208 /* @obsolete ajFileGetName
9209 ** @rename ajFileGetNameS
9210 */
ajFileGetName(const AjPFile file)9211 __deprecated const AjPStr ajFileGetName(const AjPFile file)
9212 {
9213     return ajFileGetNameS(file);
9214 }
9215 
9216 
9217 
9218 
9219 /* @obsolete ajFileGetApp
9220 ** @rename ajFileIsAppend
9221 */
ajFileGetApp(const AjPFile thys)9222 __deprecated AjBool ajFileGetApp(const AjPFile thys)
9223 {
9224     return ajFileIsAppend(thys);
9225 }
9226 
9227 
9228 
9229 
9230 /* @obsolete ajFileEof
9231 ** @rename ajFileIsEof
9232 */
ajFileEof(const AjPFile thys)9233 __deprecated AjBool ajFileEof(const AjPFile thys)
9234 {
9235     return ajFileIsEof(thys);
9236 }
9237 
9238 
9239 
9240 
9241 /* @obsolete ajFileStderr
9242 ** @rename ajFileIsStderr
9243 */
ajFileStderr(const AjPFile file)9244 __deprecated AjBool ajFileStderr(const AjPFile file)
9245 {
9246     return ajFileIsStderr(file);
9247 }
9248 
9249 
9250 
9251 
9252 /* @obsolete ajFileStdin
9253 ** @rename ajFileIsStdin
9254 */
ajFileStdin(const AjPFile file)9255 __deprecated AjBool ajFileStdin(const AjPFile file)
9256 {
9257     return ajFileIsStdin(file);
9258 }
9259 
9260 
9261 
9262 
9263 
9264 /* @obsolete ajFileStdout
9265 ** @rename ajFileIsStdout
9266 */
ajFileStdout(const AjPFile file)9267 __deprecated AjBool ajFileStdout(const AjPFile file)
9268 {
9269     return ajFileIsStdout(file);
9270 }
9271 
9272 
9273 
9274 
9275 /* @obsolete ajFileBuffNewF
9276 ** @rename ajFilebuffNewFromCfile
9277 */
ajFileBuffNewF(FILE * fp)9278 __deprecated AjPFilebuff ajFileBuffNewF(FILE* fp)
9279 {
9280     return ajFilebuffNewFromCfile(fp);
9281 }
9282 
9283 
9284 
9285 
9286 /* @obsolete ajFileBuffNewFile
9287 ** @rename ajFilebuffNewFromFile
9288 */
ajFileBuffNewFile(AjPFile file)9289 __deprecated AjPFilebuff ajFileBuffNewFile(AjPFile file)
9290 {
9291     return ajFilebuffNewFromFile(file);
9292 }
9293 
9294 
9295 
9296 
9297 /* @obsolete ajFileBuffNewS
9298 ** @rename ajFilebuffNewLine
9299 */
ajFileBuffNewS(const AjPStr data)9300 __deprecated AjPFilebuff ajFileBuffNewS(const AjPStr data)
9301 {
9302     return ajFilebuffNewLine(data);
9303 }
9304 
9305 
9306 
9307 
9308 /* @obsolete ajFileBuffNewList
9309 ** @rename ajFilebuffNewListinList
9310 */
9311 
ajFileBuffNewList(AjPList list)9312 __deprecated AjPFilebuff ajFileBuffNewList(AjPList list)
9313 {
9314     return ajFilebuffNewListinList(list);
9315 }
9316 
9317 
9318 
9319 
9320 /* @obsolete ajFileBuffNewIn
9321 ** @rename ajFilebuffNewNameS
9322 */
ajFileBuffNewIn(const AjPStr name)9323 __deprecated AjPFilebuff ajFileBuffNewIn(const AjPStr name)
9324 {
9325     return ajFilebuffNewNameS(name);
9326 }
9327 
9328 
9329 
9330 
9331 /* @obsolete ajFileBuffNewDC
9332 ** @replace ajFileBuffNewNamePathC (1,2/2,1)
9333 */
ajFileBuffNewDC(const AjPStr dir,const char * filename)9334 __deprecated AjPFilebuff ajFileBuffNewDC(const AjPStr dir,
9335                                          const char* filename)
9336 {
9337     return ajFilebuffNewNamePathC(filename, dir);
9338 }
9339 
9340 
9341 
9342 
9343 /* @obsolete ajFileBuffNewDF
9344 ** @replace ajFilebuffNewNamePathS (1,2/2,1)
9345 */
ajFileBuffNewDF(const AjPStr dir,const AjPStr filename)9346 __deprecated AjPFilebuff ajFileBuffNewDF(const AjPStr dir,
9347                                          const AjPStr filename)
9348 {
9349     return ajFilebuffNewNamePathS(filename, dir);
9350 }
9351 
9352 
9353 
9354 
9355 
9356 /* @obsolete ajFileBuffNew
9357 ** @rename ajFilebuffNewNofile
9358 */
ajFileBuffNew(void)9359 __deprecated AjPFilebuff ajFileBuffNew(void)
9360 {
9361     return ajFilebuffNewNofile();
9362 }
9363 
9364 
9365 
9366 
9367 /* @obsolete ajFileBuffNewDW
9368 ** @rename ajFilebuffNewPathWild
9369 */
9370 
ajFileBuffNewDW(const AjPStr dir,const AjPStr wildfile)9371 __deprecated AjPFilebuff ajFileBuffNewDW(const AjPStr dir,
9372                                          const AjPStr wildfile)
9373 {
9374     return ajFilebuffNewPathWild(dir, wildfile);
9375 }
9376 
9377 
9378 
9379 
9380 /* @obsolete ajFileBuffNewDWE
9381 ** @rename ajFilebuffNewPathWildExclude
9382 */
9383 
ajFileBuffNewDWE(const AjPStr dir,const AjPStr wildfile,const AjPStr exclude)9384 __deprecated AjPFilebuff ajFileBuffNewDWE(const AjPStr dir,
9385                                           const AjPStr wildfile,
9386                                           const AjPStr exclude)
9387 {
9388     return ajFilebuffNewPathWildExclude(dir, wildfile, exclude);
9389 }
9390 
9391 
9392 
9393 
9394 /* @obsolete ajFileBuffDel
9395 ** @rename ajFilebuffDel
9396 */
ajFileBuffDel(AjPFilebuff * Pbuff)9397 __deprecated void ajFileBuffDel(AjPFilebuff* Pbuff)
9398 {
9399     ajFilebuffDel(Pbuff);
9400 }
9401 
9402 
9403 
9404 
9405 /* @obsolete ajFileBuffSetFile
9406 ** @remove Use ajFilebuffReopenFile or ajFilebuffClear
9407 */
ajFileBuffSetFile(AjPFilebuff * pthys,AjPFile file,AjBool samefile)9408 __deprecated AjBool ajFileBuffSetFile(AjPFilebuff* pthys,
9409                                       AjPFile file, AjBool samefile)
9410 {
9411     if(samefile)
9412         ajFilebuffClear(*pthys, -1);
9413     else
9414         ajFilebuffReopenFile(pthys, file);
9415 
9416     return ajTrue;
9417 }
9418 
9419 
9420 
9421 
9422 /* @obsolete ajFileBuffClear
9423 ** @rename ajFilebuffClear
9424 */
ajFileBuffClear(AjPFilebuff buff,ajint lines)9425 __deprecated void ajFileBuffClear(AjPFilebuff buff, ajint lines)
9426 {
9427     ajFilebuffClear(buff, lines);
9428 }
9429 
9430 
9431 
9432 
9433 /* @obsolete ajFileBuffClearStore
9434 ** @rename ajFilebuffClearStore
9435 */
ajFileBuffClearStore(AjPFilebuff buff,ajint lines,const AjPStr rdline,AjBool store,AjPStr * astr)9436 __deprecated void ajFileBuffClearStore(AjPFilebuff buff, ajint lines,
9437                                        const AjPStr rdline, AjBool store, AjPStr *astr)
9438 {
9439     ajFilebuffClearStore(buff, lines, rdline, store, astr);
9440 
9441     return;
9442 }
9443 
9444 
9445 
9446 
9447 /* @obsolete ajFileBuffFix
9448 ** @rename ajFilebuffFix
9449 */
ajFileBuffFix(AjPFilebuff buff)9450 __deprecated void ajFileBuffFix(AjPFilebuff buff)
9451 {
9452     ajFilebuffFix(buff);
9453 
9454     return;
9455 }
9456 
9457 
9458 
9459 
9460 /* @obsolete ajFileBuffReset
9461 ** @rename ajFilebuffReset
9462 */
ajFileBuffReset(AjPFilebuff buff)9463 __deprecated void ajFileBuffReset(AjPFilebuff buff)
9464 {
9465     ajFilebuffReset(buff);
9466 
9467     return;
9468 }
9469 
9470 
9471 
9472 
9473 /* @obsolete ajFileBuffResetPos
9474 ** @rename ajFilebuffResetPos
9475 */
ajFileBuffResetPos(AjPFilebuff buff)9476 __deprecated void ajFileBuffResetPos(AjPFilebuff buff)
9477 {
9478     ajFilebuffResetPos(buff);
9479 
9480     return;
9481 }
9482 
9483 
9484 
9485 
9486 /* @obsolete ajFileBuffResetStore
9487 ** @rename ajFilebuffResetStore
9488 */
ajFileBuffResetStore(AjPFilebuff buff,AjBool store,AjPStr * astr)9489 __deprecated void ajFileBuffResetStore(AjPFilebuff buff,
9490                                        AjBool store, AjPStr *astr)
9491 {
9492     ajFilebuffResetStore(buff, store, astr);
9493 
9494     return;
9495 }
9496 
9497 
9498 
9499 
9500 /* @obsolete ajFileBuffBuff
9501 ** @rename ajFilebuffSetBuffered
9502 */
ajFileBuffBuff(AjPFilebuff buff)9503 __deprecated AjBool ajFileBuffBuff(AjPFilebuff buff)
9504 {
9505     return ajFilebuffSetBuffered(buff);
9506 }
9507 
9508 
9509 
9510 
9511 /* @obsolete ajFileBuffNobuff
9512 ** @rename ajFilebuffSetUnbuffered
9513 */
ajFileBuffNobuff(AjPFilebuff buff)9514 __deprecated AjBool ajFileBuffNobuff(AjPFilebuff buff)
9515 {
9516     return ajFilebuffSetUnbuffered(buff);
9517 }
9518 
9519 
9520 
9521 
9522 /* @obsolete ajFileBuffStripHtmlPre
9523 ** @rename ajFileBuffHtmlPre
9524 */
ajFileBuffStripHtmlPre(AjPFilebuff buff)9525 __deprecated AjBool ajFileBuffStripHtmlPre(AjPFilebuff buff)
9526 {
9527     return ajFilebuffHtmlPre(buff);
9528 }
9529 
9530 
9531 
9532 
9533 /* @obsolete ajFileBuffStripHtml
9534 ** @rename ajFilebuffHtmlStrip
9535 */
ajFileBuffStripHtml(AjPFilebuff buff)9536 __deprecated void ajFileBuffStripHtml(AjPFilebuff buff)
9537 {
9538     ajFilebuffHtmlStrip(buff);
9539 
9540     return;
9541 }
9542 
9543 
9544 
9545 
9546 /* @obsolete ajFileBuffLoadC
9547 ** @rename ajFilebuffLoadC
9548 */
ajFileBuffLoadC(AjPFilebuff buff,const char * line)9549 __deprecated void ajFileBuffLoadC(AjPFilebuff buff, const char* line)
9550 {
9551     ajFilebuffLoadC(buff, line);
9552 
9553     return;
9554 }
9555 
9556 
9557 
9558 
9559 /* @obsolete ajFileBuffLoadS
9560 ** @rename ajFilebuffLoadS
9561 */
ajFileBuffLoadS(AjPFilebuff buff,const AjPStr line)9562 __deprecated void ajFileBuffLoadS(AjPFilebuff buff, const AjPStr line)
9563 {
9564     ajFilebuffLoadS(buff, line);
9565 
9566     return;
9567 }
9568 
9569 
9570 
9571 
9572 /* @obsolete ajFileBuffLoad
9573 ** @rename ajFilebuffLoadAll
9574 */
ajFileBuffLoad(AjPFilebuff buff)9575 __deprecated void ajFileBuffLoad(AjPFilebuff buff)
9576 {
9577     ajFilebuffLoadAll(buff);
9578 }
9579 
9580 
9581 
9582 
9583 /* @obsolete ajFileBuffFile
9584 ** @rename ajFilebuffGetFile
9585 */
ajFileBuffFile(const AjPFilebuff buff)9586 __deprecated AjPFile ajFileBuffFile(const AjPFilebuff buff)
9587 {
9588     return ajFilebuffGetFile(buff);
9589 }
9590 
9591 
9592 
9593 
9594 /* @obsolete ajFileBuffSize
9595 ** @rename ajFileValueBuffsize
9596 */
ajFileBuffSize(void)9597 __deprecated ajint ajFileBuffSize(void)
9598 {
9599     return ajFileValueBuffsize();
9600 }
9601 
9602 
9603 
9604 
9605 /* @obsolete ajFileBuffFp
9606 ** @rename ajFilebuffGetFileptr
9607 */
ajFileBuffFp(const AjPFilebuff buff)9608 __deprecated FILE* ajFileBuffFp(const AjPFilebuff buff)
9609 {
9610     return ajFilebuffGetFileptr(buff);
9611 }
9612 
9613 
9614 
9615 
9616 /* @obsolete ajFileBuffIsBuffered
9617 ** @rename ajFilebuffIsBuffered
9618 */
ajFileBuffIsBuffered(const AjPFilebuff buff)9619 __deprecated AjBool ajFileBuffIsBuffered(const AjPFilebuff buff)
9620 {
9621     return ajFilebuffIsBuffered(buff);
9622 }
9623 
9624 
9625 
9626 
9627 /* @obsolete ajFileBuffEmpty
9628 ** @rename ajFilebuffIsEmpty
9629 */
ajFileBuffEmpty(const AjPFilebuff buff)9630 __deprecated AjBool ajFileBuffEmpty(const AjPFilebuff buff)
9631 {
9632     return ajFilebuffIsEmpty(buff);
9633 }
9634 
9635 
9636 
9637 
9638 /* @obsolete ajFileBuffEnd
9639 ** @rename ajFilebuffIsEnded
9640 */
ajFileBuffEnd(const AjPFilebuff buff)9641 __deprecated AjBool ajFileBuffEnd(const AjPFilebuff buff)
9642 {
9643     return ajFilebuffIsEnded(buff);
9644 }
9645 
9646 
9647 
9648 
9649 /* @obsolete ajFileBuffEof
9650 ** @rename ajFilebuffIsEof
9651 */
ajFileBuffEof(const AjPFilebuff buff)9652 __deprecated AjBool ajFileBuffEof(const AjPFilebuff buff)
9653 {
9654     return ajFilebuffIsEof(buff);
9655 }
9656 
9657 
9658 
9659 
9660 /* @obsolete ajFileBuffTrace
9661 ** @rename ajFilebuffTrace
9662 */
ajFileBuffTrace(const AjPFilebuff buff)9663 __deprecated void ajFileBuffTrace(const AjPFilebuff buff)
9664 {
9665     ajFilebuffTrace(buff);
9666 
9667     return;
9668 }
9669 
9670 
9671 
9672 
9673 /* @obsolete ajFileBuffTraceFull
9674 ** @rename ajFilebuffTraceFull
9675 */
ajFileBuffTraceFull(const AjPFilebuff buff,size_t nlines,size_t nfree)9676 __deprecated void ajFileBuffTraceFull(const AjPFilebuff buff, size_t nlines,
9677                                       size_t nfree)
9678 {
9679     ajFilebuffTraceFull(buff, nlines, nfree);
9680 
9681     return;
9682 }
9683 
9684 
9685 
9686 
9687 /* @obsolete ajFileBuffPrint
9688 ** @rename ajFilebuffTraceTitle
9689 */
ajFileBuffPrint(const AjPFilebuff buff,const char * title)9690 __deprecated void ajFileBuffPrint(const AjPFilebuff buff, const char* title)
9691 {
9692     ajFilebuffTraceTitle(buff, title);
9693 
9694     return;
9695 }
9696 
9697 
9698 
9699 
9700 /* @obsolete ajOutfileNew
9701 ** @rename ajOutfileNewNameS
9702 */
ajOutfileNew(const AjPStr name)9703 __deprecated AjPOutfile ajOutfileNew(const AjPStr name)
9704 {
9705     return ajOutfileNewNameS(name);
9706 }
9707 
9708 
9709 
9710 
9711 /* @obsolete ajOutfileDel
9712 ** @rename ajOutfileClose
9713 */
ajOutfileDel(AjPOutfile * pthis)9714 __deprecated void ajOutfileDel(AjPOutfile* pthis)
9715 {
9716     ajOutfileClose(pthis);
9717     return;
9718 }
9719 
9720 
9721 
9722 
9723 /* @obsolete ajOutfileFile
9724 ** @rename ajOutfileGetFile
9725 */
ajOutfileFile(const AjPOutfile thys)9726 __deprecated AjPFile ajOutfileFile (const AjPOutfile thys)
9727 {
9728     return thys->File;
9729 }
9730 
9731 
9732 
9733 
9734 /* @obsolete ajOutfileFp
9735 ** @rename ajOutfileGetFileptr
9736 */
ajOutfileFp(const AjPOutfile thys)9737 __deprecated FILE* ajOutfileFp (const AjPOutfile thys)
9738 {
9739     return ajOutfileGetFileptr(thys);
9740 }
9741 
9742 
9743 
9744 
9745 /* @obsolete ajOutfileFormat
9746 ** @rename ajOutfileGetFormat
9747 */
ajOutfileFormat(const AjPOutfile thys)9748 __deprecated AjPStr ajOutfileFormat (const AjPOutfile thys)
9749 {
9750     return thys->Formatstr;
9751 }
9752 
9753 
9754 
9755 
9756 /* @obsolete ajFileNameTrim
9757 ** @rename ajFilenameTrimPath
9758 */
ajFileNameTrim(AjPStr * fname)9759 __deprecated AjBool ajFileNameTrim(AjPStr* fname)
9760 {
9761     char *p;
9762 
9763     if((p = strrchr(ajStrGetPtr(*fname),(ajint)SLASH_CHAR)))
9764     {
9765         ajStrAssignC(&fileTmpStr,p+1);
9766         ajStrAssignS(fname,fileTmpStr);
9767     }
9768 
9769     return ajTrue;
9770 }
9771 
9772 
9773 
9774 
9775 /* @obsolete ajFileDirTrim
9776 ** @rename ajFilenameTrimPath
9777 */
ajFileDirTrim(AjPStr * name)9778 __deprecated AjBool ajFileDirTrim(AjPStr* name)
9779 {
9780     return ajFilenameTrimPath(name);
9781 }
9782 
9783 
9784 
9785 
9786 /* @obsolete ajFileDirExtnTrim
9787 ** @rename ajFilenameTrimPathExt
9788 */
ajFileDirExtnTrim(AjPStr * name)9789 __deprecated AjBool ajFileDirExtnTrim(AjPStr* name)
9790 {
9791     return ajFilenameTrimPathExt(name);
9792 }
9793 
9794 
9795 
9796 
9797 /* @obsolete ajFileDirPath
9798 ** @rename ajDirnameFillPath
9799 */
ajFileDirPath(AjPStr * dir)9800 __deprecated AjBool ajFileDirPath(AjPStr* dir)
9801 {
9802     return ajDirnameFillPath(dir);
9803 }
9804 
9805 
9806 
9807 
9808 /* @obsolete ajFileDirFix
9809 ** @rename ajDirnameFix
9810 */
ajFileDirFix(AjPStr * dir)9811 __deprecated void ajFileDirFix(AjPStr* dir)
9812 {
9813     ajDirnameFix(dir);
9814 
9815     return;
9816 }
9817 
9818 
9819 
9820 
9821 /* @obsolete ajFileDir
9822 ** @rename ajDirnameFixExists
9823 */
ajFileDir(AjPStr * dir)9824 __deprecated AjBool ajFileDir(AjPStr* dir)
9825 {
9826     return ajDirnameFixExists(dir);
9827 }
9828 
9829 
9830 
9831 
9832 /* @obsolete ajFileDirUp
9833 ** @rename ajDirnameUp
9834 */
ajFileDirUp(AjPStr * dir)9835 __deprecated AjBool ajFileDirUp(AjPStr* dir)
9836 {
9837     return ajDirnameUp(dir);
9838 }
9839 
9840 
9841 
9842 
9843 /* @obsolete ajFileScan
9844 ** @remove Use ajFilelistAddPathWild and others
9845 */
ajFileScan(const AjPStr path,const AjPStr filename,AjPList * result,AjBool show,AjBool dolist,AjPList * list,AjPList rlist,AjBool recurs,AjPFile outf)9846 __deprecated ajint ajFileScan(const AjPStr path,
9847                               const AjPStr filename, AjPList *result,
9848                               AjBool show, AjBool dolist, AjPList *list,
9849                               AjPList rlist, AjBool recurs, AjPFile outf)
9850 {
9851     (void)dolist;
9852     (void)list;
9853 
9854     if(show)
9855     {
9856         ajDirnamePrintRecursiveIgnore(path, rlist, outf);
9857 
9858         return 0;
9859     }
9860 
9861     if(recurs)
9862         return ajFilelistAddPathWildRecursiveIgnore(*result,
9863                                                     path, filename, rlist);
9864 
9865     return ajFilelistAddPathWild(*result, path, filename);
9866 }
9867 
9868 
9869 
9870 
9871 /* @obsolete ajDirScan
9872 ** @remove Use ajFilelistAddPathWildDir
9873 */
ajDirScan(const AjPStr path,const AjPStr filename,AjPList * result)9874 __deprecated ajint ajDirScan(const AjPStr path,
9875                              const AjPStr filename, AjPList *result)
9876 {
9877     return ajFilelistAddPathWildDir(*result, path, filename);
9878 }
9879 
9880 
9881 
9882 
9883 /* @obsolete ajFileGetwd
9884 ** @remove Use ajFileValueCwd
9885 */
ajFileGetwd(AjPStr * dir)9886 __deprecated AjBool ajFileGetwd(AjPStr* dir)
9887 {
9888     ajStrAssignS(dir, ajFileValueCwd());
9889 
9890     return ajTrue;
9891 }
9892 
9893 #endif
9894