/[ascend]/trunk/ascend/general/ospath.c
ViewVC logotype

Annotation of /trunk/ascend/general/ospath.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2335 - (hide annotations) (download) (as text)
Sun Dec 26 03:24:37 2010 UTC (12 years, 9 months ago) by jpye
File MIME type: text/x-csrc
File size: 27553 byte(s)
Fixed bug with ospath_isroot.
1 johnpye 607 /* ASCEND modelling environment
2 jpye 2326 Copyright (C) 2006-2010 Carnegie Mellon University
3 johnpye 607
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2, or (at your option)
7     any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place - Suite 330,
17     Boston, MA 02111-1307, USA.
18 ben.allan 704 *//**
19 johnpye 607 @file
20     Platform-agnostic filesystem path manipulation functions.
21     By John Pye.
22     */
23    
24 johnpye 741 #if defined(WIN32) || defined(__WIN32) || defined(_MSC_VER)
25     # ifndef __WIN32__
26     # define __WIN32__
27     # endif
28     #endif
29    
30 ben.allan 704 #include <string.h>
31 jpye 1660 #include <stdlib.h>
32 ballan 2036 #include <stddef.h>
33 ben.allan 704 #include <stdio.h>
34     #include <ctype.h>
35 johnpye 542
36 johnpye 741 #ifndef __WIN32__
37     # include <unistd.h>
38     #endif
39    
40 ben.allan 704 #include "ospath.h"
41    
42 jpye 2335 //#define OSPATH_DEBUG
43 ben.allan 704
44 johnpye 998 #ifndef __GNUC__
45     # ifndef __FUNCTION__
46     # define __FUNCTION__ "<ospath>"
47     # endif
48 johnpye 954 #endif
49 ben.allan 704
50 johnpye 954
51 johnpye 662 /* #define VERBOSE */
52 johnpye 542
53 jpye 2335 #if !defined(VERBOSE)
54 ben.allan 704 #ifndef NDEBUG
55     # define NDEBUG
56     #endif
57     #endif
58    
59 johnpye 741 #ifdef _MSC_VER
60     # define STAT _stat
61     #else
62     # define STAT stat
63     #endif
64    
65 johnpye 542 //#define TRY_GETPWUID
66    
67     #define DO_FIXSLASHES
68    
69 ben.allan 704 #ifndef NDEBUG
70     # include <assert.h>
71     # define M(MSG) fprintf(stderr,"%s:%d: (%s) %s\n",__FILE__,__LINE__,__FUNCTION__,MSG);fflush(stderr);fflush(stderr)
72     # define MC(CLR,MSG) fprintf(stderr,"%c[%sm%s:%d: (%s) %s%c[0m\n",27,CLR,__FILE__,__LINE__,__FUNCTION__,MSG,27);fflush(stderr)
73     # define MM(MSG) MC("34",MSG)
74     # define X(VAR) fprintf(stderr,"%s:%d: (%s) %s=%s\n",__FILE__,__LINE__,__FUNCTION__,#VAR,VAR);fflush(stderr)
75     # define C(VAR) fprintf(stderr,"%s:%d: (%s) %s=%c\n",__FILE__,__LINE__,__FUNCTION__,#VAR,VAR);fflush(stderr)
76     # define V(VAR) fprintf(stderr,"%s:%d: (%s) %s=%d\n",__FILE__,__LINE__,__FUNCTION__,#VAR,(VAR));fflush(stderr)
77 johnpye 998 # define P(VAR) fprintf(stderr,"%s:%d: (%s) %s=%p\n",__FILE__,__LINE__,__FUNCTION__,#VAR,(VAR));fflush(stderr)
78 ben.allan 704 # define D(VAR) fprintf(stderr,"%s:%d: (%s) %s=",__FILE__,__LINE__,__FUNCTION__,#VAR);ospath_debug(VAR);fflush(stderr)
79     # define DD(VAR) fprintf(stderr,"%c[34;1m%s:%d: (%s)%c[0m %s=",27,__FILE__,__LINE__,__FUNCTION__,27,#VAR);ospath_debug(VAR);fflush(stderr)
80     #else
81     # include <assert.h>
82     # define M(MSG) ((void)0)
83     # define MC(CLR,MSG) ((void)0)
84     # define X(VAR) ((void)0)
85     # define C(VAR) ((void)0)
86     # define V(VAR) ((void)0)
87     # define D(VAR) ((void)0)
88 johnpye 998 # define P(VAR) ((void)0)
89 ben.allan 704 # define DD(VAR) ((void)0)
90     # define MM(VAR) ((void)0)
91     #endif
92    
93     #if defined(__WIN32__) && !defined(__MINGW32__)
94     # define STRCPY strcpy
95     # define STRNCPY(dest,src,n) strncpy_s(dest,n,src,n)
96     # define STRCAT strcat
97     # define STRNCAT strncat
98     # define STRTOK(STR,PAT,VAR) strtok_s(STR,PAT,&VAR)
99     # define STRTOKVAR(VAR) char *VAR
100     # define GETCWD _getcwd
101     # define GETENV(VAR) getenv(VAR)
102 jpye 2334 #elif defined(linux)
103     # define STRCPY strcpy
104     # define STRNCPY(dest,src,n) strncpy(dest,src,n)
105     # define STRCAT strcat
106     # define STRNCAT strncat
107     # define STRTOK(STR,PAT,VAR) strtok_r(STR,PAT,&VAR)
108     # define STRTOKVAR(VAR) char *VAR
109     # define GETCWD getcwd
110     # define GETENV(VAR) getenv(VAR)
111 ben.allan 704 #else
112     # define STRCPY strcpy
113     # define STRNCPY(dest,src,n) strncpy(dest,src,n)
114     # define STRCAT strcat
115     # define STRNCAT strncat
116     # define STRTOK(STR,PAT,VAR) strtok(STR,PAT)
117     # define STRTOKVAR(VAR) ((void)0)
118     # define GETCWD getcwd
119     # define GETENV(VAR) getenv(VAR)
120     #endif
121    
122 johnpye 908 /* PATH_MAX is in ospath.h */
123 ben.allan 704 #define DRIVEMAX 3
124     #define LISTMAX 256
125    
126     #ifdef __WIN32__ /* && !defined(__MINGW32__) */
127     # define WINPATHS
128     #endif
129    
130     struct FilePath{
131 johnpye 908 char path[PATH_MAX]; /** the string version of the represented POSIX path */
132 ben.allan 704
133 johnpye 965 #ifdef WINPATHS
134 johnpye 908 char drive[DRIVEMAX]; /** the drive the path resides on (field is absent in POSIX systems) */
135 ben.allan 704 #endif
136     };
137    
138     #include <string.h>
139    
140     #if !defined(MALLOC) && !defined(FREE)
141     # define MALLOC malloc
142     # define FREE free
143     #endif
144    
145     #define E(MSG) fprintf(stderr,"%s:%d: (%s) ERROR: %s\n",__FILE__,__LINE__,__FUNCTION__,MSG)
146    
147     #ifdef DO_FIXSLASHES
148 johnpye 542 void ospath_fixslash(char *path);
149 ben.allan 704 #endif
150    
151     struct FilePath *ospath_getcwd();
152    
153     void ospath_copy(struct FilePath *dest, struct FilePath *src);
154    
155    
156     #ifdef WINPATHS
157     /**
158     This function splits out the drive letter in the path string, thus completing
159     the correct construction of a FilePath object under Win32.
160     */
161     void ospath_extractdriveletter(struct FilePath *);
162     #endif
163    
164     #ifdef WINPATHS
165     # define PATH_SEPARATOR_STR "\\"
166     # define PATH_SEPARATOR_CHAR '\\'
167     # define PATH_LISTSEP_CHAR ';'
168 johnpye 542 # define PATH_LISTSEP_STR ";"
169 ben.allan 704 # define PATH_WRONGSLASH_CHAR '/'
170     # define PATH_WRONGSLASH_STR "/"
171     #else
172     # define PATH_SEPARATOR_STR "/"
173     # define PATH_SEPARATOR_CHAR '/'
174     # define PATH_LISTSEP_CHAR ':'
175     # define PATH_LISTSEP_STR ":"
176     # define PATH_WRONGSLASH_CHAR '\\'
177     # define PATH_WRONGSLASH_STR "\\"
178     #endif
179    
180     /**
181     Create a new path structure from a string
182     */
183     struct FilePath *ospath_new(const char *path){
184     struct FilePath *fp;
185     fp = ospath_new_noclean(path);
186    
187     #ifdef DO_FIXSLASHES
188     ospath_fixslash(fp->path);
189     #endif
190    
191     ospath_cleanup(fp);
192    
193 johnpye 908 #if 0
194     D(fp);
195     #endif
196 ben.allan 704
197     return fp;
198     }
199    
200    
201    
202 johnpye 908 /** Create but with no 'cleanup', and no fixing of / vs \. */
203 ben.allan 704 struct FilePath *ospath_new_noclean(const char *path){
204     struct FilePath *fp = (struct FilePath *)MALLOC(sizeof(struct FilePath));
205 johnpye 998 P(fp);
206     X(path);
207 ben.allan 704 STRNCPY(fp->path,path,PATH_MAX);
208     assert(strcmp(fp->path,path)==0);
209     #ifdef WINPATHS
210 johnpye 908 #if 0
211     X(fp->path);
212     #endif
213 ben.allan 704 ospath_extractdriveletter(fp);
214     #endif
215    
216     return fp;
217     }
218    
219     struct FilePath *ospath_new_expand_env(const char *path, GetEnvFn *getenvptr){
220     struct FilePath *fp;
221    
222     char *pathnew = env_subst(path,getenvptr);
223     fp = ospath_new(pathnew);
224     FREE(pathnew);
225    
226     return fp;
227     }
228    
229 johnpye 741 struct FilePath *ospath_new_copy(struct FilePath *fp){
230     struct FilePath *fp1 = (struct FilePath *)MALLOC(sizeof(struct FilePath));
231     ospath_copy(fp1,fp);
232     return fp1;
233     }
234 ben.allan 704
235     /**
236     This function will serve to allow #include-style file paths
237     to be specified with platform-independent forward slashes then
238     translated into the local filesystem format for subsequent use.
239    
240     This method should be identical to ospath_new on posix, right?
241    
242     @NOTE: on windows, we also want:
243     C:dir/file --> c:$PWD\dir\file
244     e:/hello --> e:\hello
245     here/i/am --> here\i\am
246    
247     @NOTE:
248     A path-search function should create full file paths by
249     appending relative file to each component of the search path
250     then performing a callback on each one to determine if the
251     match is OK or not.
252     */
253     struct FilePath *ospath_new_from_posix(const char *posixpath){
254     struct FilePath *fp;
255     fp = ospath_new_noclean(posixpath);
256    
257     #ifdef DO_FIXSLASHES
258     ospath_fixslash(fp->path);
259     #endif
260    
261 johnpye 908 #if 0
262     X(fp->path);
263     #endif
264 ben.allan 704
265     ospath_cleanup(fp);
266    
267     return fp;
268     }
269    
270     void ospath_free(struct FilePath *fp){
271 johnpye 662 if(fp!=NULL){
272 johnpye 998 P(fp);
273 johnpye 662 FREE(fp);
274     }
275 johnpye 664 fp=NULL;
276 ben.allan 704 }
277 johnpye 542
278 ben.allan 704 void ospath_free_str(char *str){
279     FREE(str);
280 johnpye 542 }
281 ben.allan 704
282    
283     #ifdef DO_FIXSLASHES
284     void ospath_fixslash(char *path){
285    
286     char *p;
287     char temp[PATH_MAX];
288     int startslash;
289     int endslash;
290     STRTOKVAR(nexttok);
291    
292     STRNCPY(temp,path,PATH_MAX);
293    
294 johnpye 908 #if 0
295     X(path);
296     #endif
297 ben.allan 704
298     startslash = (strlen(temp) > 0 && temp[0] == PATH_WRONGSLASH_CHAR);
299     endslash = (strlen(temp) > 1 && temp[strlen(temp) - 1] == PATH_WRONGSLASH_CHAR);
300    
301 johnpye 908 #if 0
302     V(startslash);
303     V(endslash);
304 ben.allan 704
305 johnpye 908 #endif
306     /* reset fp->path as required. */
307 ben.allan 704 STRNCPY(path, (startslash ? PATH_SEPARATOR_STR : ""), PATH_MAX);
308    
309 johnpye 908 #if 0
310     M("STARTING STRTOK");
311     #endif
312 ben.allan 704 for(p = STRTOK(temp, PATH_WRONGSLASH_STR,nexttok);
313     p!=NULL;
314     p = STRTOK(NULL,PATH_WRONGSLASH_STR,nexttok)
315     ){
316 johnpye 908 /* add a separator if we've already got some stuff */
317 ben.allan 704 if(
318     strlen(path) > 0
319     && path[strlen(path) - 1] != PATH_SEPARATOR_CHAR
320     ){
321     STRCAT(path,PATH_SEPARATOR_STR);
322     }
323    
324     STRCAT(path,p);
325     }
326 johnpye 908 #if 0
327     M("FINISHED STRTOK");
328     #endif
329 ben.allan 704
330 johnpye 908 /* put / on end as required, according to what the starting path had */
331 ben.allan 704 if(endslash && (strlen(path) > 0 ? (path[strlen(path) - 1] != PATH_SEPARATOR_CHAR) : 1))
332     {
333 johnpye 908 #if 0
334     M("adding endslash!");
335     #endif
336 ben.allan 704
337     STRCAT(path, PATH_SEPARATOR_STR);
338     }
339    
340 johnpye 908 #if 0
341     X(path);
342     #endif
343 ben.allan 704 }
344     #endif
345    
346     struct FilePath *ospath_getcwd(void){
347 johnpye 998 struct FilePath *fp;
348 ben.allan 704 char *cwd;
349    
350 johnpye 908 /* get current working directory */
351 ben.allan 704 cwd = (char *)GETCWD(NULL, 0);
352    
353 johnpye 908 /* create new path with resolved working directory */
354 ben.allan 704 fp = ospath_new_noclean(cwd != NULL ? cwd : ".");
355    
356 jpye 2334 ASC_FREE(cwd);
357 ben.allan 704 D(fp);
358    
359     return fp;
360     }
361    
362     /**
363     Use getenv() function to retrieve HOME path, or if not set, use
364     the password database and try to retrieve it that way (???)
365     */
366     struct FilePath *ospath_gethomepath(void){
367    
368     const char *pfx = (const char *)getenv("HOME");
369     struct FilePath *fp;
370    
371 johnpye 542 #ifndef __WIN32__
372 ben.allan 704 # ifdef TRY_GETPWUID
373     struct passwd *pw;
374    
375     if(pfx==NULL){
376     pw = (struct passwd*)getpwuid(getuid());
377    
378     if(pw){
379     pfx = pw->pw_dir;
380     }
381 johnpye 542 }
382 ben.allan 704 # endif
383     #endif
384    
385 johnpye 908 /* create path object from HOME, but don't compress it
386     (because that would lead to an infinite loop) */
387 ben.allan 704 fp = ospath_new_noclean(pfx ? pfx : "");
388    
389     #ifdef DO_FIXSLASHES
390     ospath_fixslash(fp->path);
391     #endif
392    
393     return fp;
394     }
395    
396 johnpye 542 #ifdef WINPATHS
397 ben.allan 704 void ospath_extractdriveletter(struct FilePath *fp)
398     {
399     char *p;
400 johnpye 908 #if 0
401     M("SOURCE");
402     X(fp->path);
403     fprintf(stderr,"CHAR 1 = %c\n",fp->path[1]);
404     #endif
405 ben.allan 704
406 johnpye 908 /* extract the drive the path resides on... */
407 ben.allan 704 if(strlen(fp->path) >= 2 && fp->path[1] == ':')
408     {
409     STRNCPY(fp->drive,fp->path,2);
410     fp->drive[2]='\0';
411     for(p=fp->path+2; *p!='\0'; ++p){
412     *(p-2)=*p;
413     }
414     *(p-2)='\0';
415     }else{
416     STRNCPY(fp->drive,"",DRIVEMAX);
417     }
418 johnpye 908 #if 0
419     M("RESULT");
420     X(fp->path);
421     X(fp->drive);
422     #endif
423 ben.allan 704 }
424     #endif
425    
426     void ospath_cleanup(struct FilePath *fp){
427     char path[PATH_MAX];
428     char *p;
429     struct FilePath *home;
430     struct FilePath *working;
431     struct FilePath *parent;
432 johnpye 908 int startslash, endslash;
433 ben.allan 704 STRTOKVAR(nexttok);
434    
435 johnpye 908 /* compress the path, and resolve ~ */
436     startslash = (strlen(fp->path) > 0 && fp->path[0] == PATH_SEPARATOR_CHAR);
437     endslash = (strlen(fp->path) > 1 && fp->path[strlen(fp->path) - 1] == PATH_SEPARATOR_CHAR);
438 ben.allan 704
439 johnpye 908 #if 0
440     fprintf(stderr,"FS ON START = %d\n",startslash);
441     fprintf(stderr,"FS ON END = %d\n",endslash);
442     fprintf(stderr,"FIRST CHAR = %c\n",fp->path[0]);
443     #endif
444 ben.allan 704
445     home = ospath_gethomepath();
446    
447 johnpye 908 /* create a copy of fp->path. */
448 ben.allan 704 STRCPY(path, fp->path);
449    
450 johnpye 908 /* reset fp->path as required. */
451 ben.allan 704 STRCPY(fp->path, (startslash ? PATH_SEPARATOR_STR : ""));
452    
453     D(fp);
454     X(path);
455    
456 johnpye 908 /* split path into it tokens, using STRTOK which is NOT reentrant
457     so be careful! */
458 ben.allan 704
459 johnpye 908 /*M("STARTING STRTOK"); */
460 ben.allan 704 for(p = STRTOK(path, PATH_SEPARATOR_STR,nexttok);
461     p!=NULL;
462     p = STRTOK(NULL,PATH_SEPARATOR_STR,nexttok)
463     ){
464 johnpye 908 #if 0
465     M("NEXT TOKEN");
466     X(p);
467     X(path+strlen(p)+1);
468     #endif
469 ben.allan 704 if(strcmp(p, "~")==0){
470    
471 johnpye 908 if(p == path){ /* check that the ~ is the first character in the path */
472 ben.allan 704 if(ospath_isvalid(home)){
473     ospath_copy(fp,home);
474     continue;
475     }else{
476     E("HOME does not resolve to valid path");
477     }
478     }else{
479     E("A tilde (~) present as a component in a file path must be at the start!");
480     }
481     }else if(strcmp(p, ".") == 0){
482    
483 johnpye 908 if(p==path){/* start of path: */
484 ben.allan 704 M("EXPANDING LEADING '.' IN PATH");
485     X(path);
486    
487     working = ospath_getcwd();
488    
489     D(working);
490     #ifdef WINPATHS
491 johnpye 542 X(working->drive);
492 ben.allan 704 #endif
493     X(p);
494     X(path);
495    
496     ospath_copy(fp,working);
497    
498    
499     D(fp);
500     X(p);
501 johnpye 908 X(path+strlen(p)+1);
502 johnpye 998
503 johnpye 908 ospath_free(working);
504 ben.allan 704 continue;
505 johnpye 908 }else{/* later in the path: just skip it */
506 ben.allan 704 M("SKIPPING '.' IN PATH");
507     continue;
508     }
509    
510     }else if(strcmp(p, "..") == 0){
511     M("GOING TO PARENT");
512     parent = ospath_getparent(fp);
513     if(ospath_isvalid(parent)){
514     ospath_copy(fp,parent);
515     }
516 johnpye 908 ospath_free(parent);
517 ben.allan 704 continue;
518     }
519    
520 johnpye 908 /* add a separator if we've already got some stuff */
521 ben.allan 704 if(
522     strlen(fp->path) > 0
523     && fp->path[strlen(fp->path) - 1] != PATH_SEPARATOR_CHAR
524     ){
525     STRCAT(fp->path,PATH_SEPARATOR_STR);
526     }
527    
528 johnpye 908 /* add the present path component */
529 ben.allan 704 STRCAT(fp->path, p);
530     }
531 johnpye 908 #if 0
532     M("FINISHED STRTOK");
533     #endif
534 ben.allan 704
535 johnpye 715 ospath_free(home);
536    
537 ben.allan 704 // put / on end as required, according to what the starting path had
538     if(endslash && (strlen(fp->path) > 0 ? (fp->path[strlen(fp->path) - 1] != PATH_SEPARATOR_CHAR) : 1))
539     {
540     STRCAT(fp->path, PATH_SEPARATOR_STR);
541     }
542     }
543    
544    
545 johnpye 542 int ospath_isvalid(struct FilePath *fp){
546 johnpye 908 /*if(fp==NULL) return 0; */
547 ben.allan 704 return strlen(fp->path) > 0 ? 1 : 0;
548     }
549 johnpye 542
550 ben.allan 704
551 johnpye 864 char *ospath_str(const struct FilePath *fp){
552 ben.allan 704 char *s;
553     #ifdef WINPATHS
554     s = (char *)MALLOC(sizeof(char)*(strlen(fp->drive)+strlen(fp->path) +1) );
555     STRCPY(s,fp->drive);
556     STRCAT(s,fp->path);
557     #else
558     s = MALLOC(sizeof(char)*(strlen(fp->path)+1));
559     STRCPY(s,fp->path);
560     #endif
561     return s;
562     }
563    
564 johnpye 741 void ospath_strncpy(struct FilePath *fp, char *dest, int destsize){
565 ben.allan 704 #ifdef WINPATHS
566     STRNCPY(dest,fp->drive,destsize);
567     STRNCAT(dest,fp->path,destsize-strlen(dest));
568     #else
569     STRNCPY(dest,fp->path,destsize);
570 johnpye 542 #endif
571     }
572 ben.allan 704
573     void ospath_strcat(struct FilePath *fp, char *dest, int destsize){
574 johnpye 588 int remaining = destsize - strlen(dest);
575 ben.allan 704 V(remaining);
576     #ifdef WINPATHS
577     STRNCAT(dest,fp->drive,remaining);
578     STRNCAT(dest,fp->path,remaining-strlen(dest));
579     #else
580     STRNCAT(dest,fp->path,remaining);
581 johnpye 588 #endif
582 ben.allan 704 D(fp);
583     }
584 johnpye 585
585 ben.allan 704 void ospath_fwrite(struct FilePath *fp, FILE *dest){
586     #ifdef WINPATHS
587     fprintf(dest,"%s%s",fp->drive,fp->path);
588     #else
589     fprintf(dest,"%s",fp->path);
590     #endif
591     }
592    
593     unsigned ospath_length(struct FilePath *fp){
594     #ifdef WINPATHS
595 johnpye 908 /* we've already validated this path, so it's on to just add it up
596     (unless someone has been tinkering with the internal structure here)*/
597 ben.allan 704 return (unsigned) (strlen(fp->drive) + strlen(fp->path));
598     #else
599     return (unsigned) (strlen(fp->path));
600     #endif
601     }
602    
603     struct FilePath *ospath_getparent(struct FilePath *fp)
604     {
605     int length;
606     int offset;
607     char *pos;
608 ballan 2036 ptrdiff_t len1;
609     int len2;
610 ben.allan 704 char sub[PATH_MAX];
611     struct FilePath *fp1, *fp2;
612    
613 jpye 2335 #ifdef OSPATH_DEBUG
614     fprintf(stderr,"finding parent of %s\n",fp->path);
615     #endif
616 ben.allan 704 D(fp);
617    
618 johnpye 589 if(strlen(fp->path) == 0){
619     fp1 = ospath_getcwd();
620     fp2 = ospath_getparent(fp1);
621     ospath_free(fp1);
622     return fp2;
623 ben.allan 704 }else if(ospath_isroot(fp)){
624 jpye 2335 #ifdef OSPATH_DEBUG
625     fprintf(stderr,"path is root\n");
626     #endif
627 johnpye 908 /* stay at root */
628 ben.allan 704 return ospath_new("/");
629     }
630    
631 johnpye 908 /* reverse find a / ignoring the end / if it exists.
632     /// FIXME */
633 ben.allan 704 length = strlen(fp->path);
634     offset = (
635 johnpye 908 fp->path[length - 1] == PATH_SEPARATOR_CHAR /* last char is slash?*/
636     && length > 1 /* and more than just leading slash... */
637     ) ? length - 1 : length; /* then remove last char */
638 ben.allan 704
639     for(pos = fp->path + offset - 1; *pos!=PATH_SEPARATOR_CHAR && pos>=fp->path; --pos){
640 jpye 2335 #ifdef OSPATH_DEBUG
641     CONSOLE_DEBUG("CURRENT CHAR: %c\n",*pos);
642 johnpye 908 #endif
643 ben.allan 704 }
644    
645 ballan 2036 len1 = pos - (fp->path); len2 = (int)len1;
646     V(len2);
647     /*fprintf(stderr,"POS = %d\n",len2);*/
648 ben.allan 704
649     if(*pos==PATH_SEPARATOR_CHAR){
650     #ifdef WINPATHS
651     STRCPY(sub,fp->drive);
652 johnpye 542 STRNCAT(sub,fp->path,len1);
653     #else
654     STRNCPY(sub,fp->path,len1);
655 ben.allan 704 sub[len1]='\0';
656     #endif
657     X(sub);
658     if(strcmp(sub,"")==0){
659     M("DIRECTORY IS EMPTY");
660     STRCAT(sub,PATH_SEPARATOR_STR);
661     }
662     }else{
663 johnpye 1314 /* ie pos<fp->path */
664     M("NO PARENT DIR");
665     if(fp->path[0]==PATH_SEPARATOR_CHAR){
666     E("NO PARENT DIR");
667     return ospath_new_noclean(fp->path);
668     }else{
669     M("RETURNING '.'");
670     #ifdef WINPATHS
671     /* eg 'c:bin' --> 'c:' */
672     STRCPY(sub,fp->drive);
673     return ospath_new_noclean(sub);
674     #else
675     /* eg 'bin' --> '.' */
676     return ospath_new_noclean(".");
677     #endif
678     }
679 ben.allan 704 }
680 johnpye 662
681 johnpye 998 M("Creating 'sub'");
682 ben.allan 704 fp1 = ospath_new_noclean(sub);
683 johnpye 998 M("... 'sub'");
684 ben.allan 704 D(fp1);
685     return fp1;
686     }
687    
688     struct FilePath *ospath_getparentatdepthn(struct FilePath *fp, unsigned depth)
689     {
690     int startslash;
691     char path[PATH_MAX];
692     char *temp;
693     char *p;
694     STRTOKVAR(nexttok);
695     #ifdef WINPATHS
696     char temp2[PATH_MAX];
697     #endif
698    
699     if(
700     !ospath_isvalid(fp)
701     || depth >= ospath_depth(fp)
702     ){
703     return fp;
704     }
705    
706 johnpye 908 /* create FilePath object to parent object at depth N relative to this
707     path object.*/
708 ben.allan 704 startslash = (strlen(fp->path) > 0 && fp->path[0] == PATH_SEPARATOR_CHAR);
709    
710 johnpye 908 /* create a copy of fp->path.*/
711 ben.allan 704 STRCPY(path, fp->path);
712    
713 johnpye 908 /* reset fp->path as required.*/
714 ben.allan 704 temp = startslash ? PATH_SEPARATOR_STR : "";
715    
716 johnpye 908 /* split path into it tokens.
717     M("STARTING STRTOK");*/
718 ben.allan 704 p = STRTOK(path, PATH_SEPARATOR_STR, nexttok);
719    
720     while(p && depth > 0)
721     {
722     if(strlen(temp) > 0 && temp[strlen(temp) - 1] != PATH_SEPARATOR_CHAR)
723     {
724     strcat(temp,PATH_SEPARATOR_STR);
725     }
726    
727     STRCAT(temp,p);
728     --depth;
729    
730     p = STRTOK(NULL, PATH_SEPARATOR_STR, nexttok);
731     }
732 johnpye 908 #if 0
733     M("FINISHED STRTOK");
734     #endif
735 ben.allan 704
736 johnpye 908 /* put / on end as required*/
737 ben.allan 704 if(strlen(temp) > 0 ? (temp[strlen(temp) - 1] != PATH_SEPARATOR_CHAR) : 1)
738     {
739     strcat(temp,PATH_SEPARATOR_STR);
740     }
741    
742     #ifdef WINPATHS
743     STRCPY(temp2,fp->drive);
744     STRCAT(temp2,temp);
745     return ospath_new_noclean(temp2);
746     #else
747     return ospath_new_noclean(temp);
748     #endif
749     }
750    
751     char *ospath_getbasefilename(struct FilePath *fp){
752     char *temp;
753     unsigned length, offset;
754     char *pos;
755    
756 johnpye 662 if(fp==NULL)return NULL;
757 johnpye 542
758 ben.allan 704 if(strlen(fp->path) == 0){
759 johnpye 908 /* return empty name.*/
760 ben.allan 704 return "";
761     }
762    
763 johnpye 542 if(fp->path[strlen(fp->path)-1]==PATH_SEPARATOR_CHAR){
764     return NULL;
765     }
766    
767 johnpye 908 /* reverse find '/' but DON'T ignore a trailing slash*/
768     /* (this is changed from the original implementation)*/
769 ben.allan 704 length = strlen(fp->path);
770     offset = length;
771 johnpye 543
772 ben.allan 704 pos = strrchr(fp->path, PATH_SEPARATOR_CHAR); /* OFFSET! */
773    
774 johnpye 908 /* extract filename given position of find / and return it.*/
775 ben.allan 704 if(pos != NULL){
776     unsigned length1 = length - ((pos - fp->path));
777     temp = (char *)MALLOC(sizeof(char)*(length1+1));
778    
779     V(length1);
780 johnpye 662 STRNCPY(temp, pos + 1, length1);
781 ben.allan 704 *(temp + length1)='\0';
782     return temp;
783     }else{
784     temp = (char *)MALLOC(sizeof(char)*(length+1));
785 johnpye 662 STRNCPY(temp, fp->path, length);
786 ben.allan 704 *(temp+length)='\0';
787     return temp;
788     }
789     }
790    
791     char *ospath_getfilestem(struct FilePath *fp){
792     char *temp;
793     char *pos;
794    
795     if(!ospath_isvalid(fp)){
796     return NULL;
797     }
798    
799 johnpye 542 temp = ospath_getbasefilename(fp);
800     if(temp==NULL){
801 johnpye 908 /* it's a directory*/
802 johnpye 542 return NULL;
803     }
804    
805 ben.allan 704 pos = strrchr(temp,'.');
806    
807 johnpye 542 if(pos==NULL || pos==temp){
808 johnpye 908 /* no extension, or a filename starting with '.'
809     -- return the whole filename*/
810 johnpye 542 return temp;
811     }
812    
813 johnpye 908 /* remove extension.*/
814 johnpye 542 *pos = '\0';
815    
816 ben.allan 704 return temp;
817     }
818    
819     char *ospath_getfileext(struct FilePath *fp){
820     char *temp, *temp2, *pos;
821     int len1;
822    
823     if(!ospath_isvalid(fp)){
824     return NULL;
825     }
826    
827 johnpye 542 temp = ospath_getbasefilename(fp);
828     if(temp==NULL){
829 johnpye 908 /* it's a directory*/
830 johnpye 542 return NULL;
831 ben.allan 704 }
832    
833 johnpye 908 /* make sure there is no / on the end.
834     FIXME: is this good policy, removing a trailing slash?*/
835 ben.allan 704 if(temp[strlen(temp) - 1] == PATH_SEPARATOR_CHAR){
836     temp[strlen(temp)-1] = '\0';
837     }
838    
839     pos = strrchr(temp,'.');
840    
841     if(pos != NULL && pos!=temp){
842 johnpye 908 /* extract extension.*/
843 ben.allan 704 len1 = temp + strlen(temp) - pos + 1;
844     temp2 = (char *)MALLOC(sizeof(char)*len1);
845     STRNCPY(temp2, pos, len1);
846     }else{
847 johnpye 908 /* no extension*/
848 ben.allan 704 temp2 = NULL;
849     }
850     FREE(temp);
851     return temp2;
852 johnpye 542 }
853    
854 ben.allan 704 int ospath_isroot(struct FilePath *fp)
855     {
856 jpye 2335 if(!ospath_isvalid(fp)){
857     #ifdef OSPATH_DEBUG
858     fprintf(stderr,"path is invalid\n");
859     #endif
860 ben.allan 704 return 0;
861     }
862    
863 jpye 2335 return strcmp(fp->path, PATH_SEPARATOR_STR) ? 0 : 1;
864 ben.allan 704 }
865    
866     unsigned ospath_depth(struct FilePath *fp){
867     unsigned length;
868     unsigned depth;
869     unsigned i;
870    
871     length = strlen(fp->path);
872     depth = 0;
873    
874     for(i = 0; i < length; i++){
875     if(fp->path[i] == PATH_SEPARATOR_CHAR){
876     ++depth;
877     }
878     }
879    
880     if(
881     depth > 0
882     && length > 0
883     && fp->path[length - 1] == PATH_SEPARATOR_CHAR
884     ){
885 johnpye 908 /* PATH_SEPARATOR_CHAR on the end, reduce count by 1*/
886 ben.allan 704 --depth;
887     }
888    
889     return depth;
890     }
891    
892     struct FilePath *ospath_root(struct FilePath *fp){
893     #ifdef WINPATHS
894 johnpye 908 #if 0
895     M("WIN ROOT");
896     #endif
897 ben.allan 704 char *temp;
898     struct FilePath *r;
899    
900     if(strlen(fp->drive)){
901     temp = (char *)MALLOC(sizeof(char)*strlen(fp->drive)+1);
902     STRCPY(temp,fp->drive);
903     STRCAT(temp,PATH_SEPARATOR_STR);
904     X(temp);
905     r = ospath_new(temp);
906     FREE(temp);
907     }else{
908     r = ospath_new(fp->path);
909     }
910     return r;
911     #else
912 johnpye 908 (void)fp;
913     #if 0
914     M("JUST RETURNING PATH SEP");
915     #endif
916 ben.allan 704 return ospath_new(PATH_SEPARATOR_STR);
917     #endif
918     }
919    
920 johnpye 542 struct FilePath *ospath_getdir(struct FilePath *fp){
921     char *pos;
922     char s[PATH_MAX];
923 johnpye 864 #ifdef WINPATHS
924 johnpye 866 int e;
925 johnpye 864 #endif
926 johnpye 542
927     pos = strrchr(fp->path,PATH_SEPARATOR_CHAR);
928     if(pos==NULL){
929 johnpye 721 return ospath_new_noclean("");
930 johnpye 542 }
931     #ifdef WINPATHS
932     strncpy(s,fp->drive,PATH_MAX);
933 johnpye 864 e = strlen(s);
934 johnpye 542 strncat(s,fp->path,pos - fp->path);
935 johnpye 864 s[e+pos-fp->path]='\0';
936 johnpye 542 #else
937     strncpy(s,fp->path,pos - fp->path);
938 johnpye 864 s[pos-fp->path]='\0';
939 johnpye 931 /* CONSOLE_DEBUG("DIRECTORY: '%s'",s); */
940 johnpye 542 #endif
941     return ospath_new(s);
942     }
943    
944 johnpye 1063 ASC_DLLSPEC struct FilePath *ospath_getabs(struct FilePath *fp){
945 johnpye 721 struct FilePath *fp1, *fp2;
946 johnpye 741 if(fp->path[0]==PATH_SEPARATOR_CHAR){
947     fp1 = ospath_new_copy(fp);
948 johnpye 721 }else{
949     fp2 = ospath_new(".");
950     fp1 = ospath_concat(fp2,fp);
951     ospath_free(fp2);
952     }
953     return fp1;
954     }
955    
956 ben.allan 704 int ospath_cmp(struct FilePath *fp1, struct FilePath *fp2){
957     char temp[2][PATH_MAX];
958     #ifdef WINPATHS
959     char *p;
960     struct FilePath *fp;
961     #endif
962    
963     if(!ospath_isvalid(fp1)){
964     if(!ospath_isvalid(fp2)){
965     return 0;
966     }else{
967     return -1;
968     }
969     }else if(!ospath_isvalid(fp2)){
970     return 1;
971     }
972    
973 johnpye 908 #if 0
974     / now, both are valid...
975     M("BOTH ARE VALID");
976 ben.allan 704
977 johnpye 908 /Check that paths both have drives, if applic.
978     #endif
979 ben.allan 704 #ifdef WINPATHS
980     if(strcmp(fp1->drive,"")==0){
981     M("PATH IS MISSING DRIVE LETTER");
982     D(fp1);
983     fp = ospath_getcwd();
984     assert(strlen(fp->drive)!=0);
985     X(fp->drive);
986     STRCPY(temp[0],fp->drive);
987     ospath_free(fp);
988     }else{
989     STRCPY(temp[0],fp1->drive);
990     }
991    
992     if(strcmp(fp2->drive,"")==0){
993     M("PATH IS MISSING DRIVE LETTER");
994     D(fp2);
995     fp = ospath_getcwd();
996     assert(strlen(fp->drive)!=0);
997     X(fp->drive);
998     STRCPY(temp[1],fp->drive);
999     ospath_free(fp);
1000     }else{
1001     STRCPY(temp[1],fp2->drive);
1002     }
1003    
1004     STRCAT(temp[0],fp1->path);
1005     STRCAT(temp[1],fp2->path);
1006     #else
1007     STRCPY(temp[0], fp1->path);
1008     STRCPY(temp[1], fp2->path);
1009     #endif
1010    
1011     #ifdef WINPATHS
1012     X(temp[0]);
1013     for(p=temp[0];*p!='\0';++p){
1014     *p=tolower(*p);
1015 johnpye 908 #if 0
1016     C(*p);
1017     #endif
1018 ben.allan 704 }
1019     X(temp[1]);
1020     for(p=temp[1];*p!='\0';++p){
1021     *p=tolower(*p);
1022 johnpye 908 #if 0
1023     C(*p);
1024     #endif
1025 ben.allan 704 }
1026     X(temp[0]);
1027     X(temp[1]);
1028     #endif
1029    
1030 johnpye 908 /* we will count two paths that different only in a trailing slash to be the *same*
1031     so we add trailing slashes to both now: */
1032 ben.allan 704 if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR){
1033     STRCAT(temp[0],PATH_SEPARATOR_STR);
1034     }
1035    
1036     if(temp[1][strlen(temp[1]) - 1] != PATH_SEPARATOR_CHAR){
1037     STRCAT(temp[1],PATH_SEPARATOR_STR);
1038     }
1039    
1040 johnpye 908 #if 0
1041     X(temp[0]);
1042     X(temp[1]);
1043     #endif
1044 ben.allan 704
1045     return strcmp(temp[0],temp[1]);
1046     }
1047    
1048     struct FilePath *ospath_concat(struct FilePath *fp1, struct FilePath *fp2){
1049    
1050     struct FilePath *fp;
1051     char temp[2][PATH_MAX];
1052     char temp2[PATH_MAX];
1053     struct FilePath *r;
1054    
1055     fp = (struct FilePath *)MALLOC(sizeof(struct FilePath));
1056    
1057     if(!ospath_isvalid(fp1)){
1058     if(ospath_isvalid(fp2)){
1059     ospath_copy(fp,fp2);
1060     }else{
1061 johnpye 908 /* both invalid*/
1062 ben.allan 704 ospath_copy(fp,fp1);
1063     }
1064     return fp;
1065     }
1066    
1067     if(!ospath_isvalid(fp2)){
1068     ospath_copy(fp,fp1);
1069     return fp;
1070     }
1071    
1072 johnpye 908 /* not just a copy of one or the other...*/
1073 ben.allan 704 ospath_free(fp);
1074    
1075 johnpye 908 /* now, both paths are valid...*/
1076 ben.allan 704
1077     #ifdef WINPATHS
1078     STRNCPY(temp[0],fp1->drive,PATH_MAX);
1079     STRNCAT(temp[0],fp1->path,PATH_MAX-strlen(temp[0]));
1080     #else
1081     STRNCPY(temp[0], fp1->path,PATH_MAX);
1082     #endif
1083    
1084     STRNCPY(temp[1], fp2->path,PATH_MAX);
1085    
1086 johnpye 908 /* make sure temp has a / on the end. */
1087 ben.allan 704 if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR)
1088     {
1089     STRNCAT(temp[0],PATH_SEPARATOR_STR,PATH_MAX-strlen(temp[0]));
1090     }
1091    
1092 johnpye 542 #ifdef DO_FIXSLASHES
1093 ben.allan 704 ospath_fixslash(temp[0]);
1094     ospath_fixslash(temp[1]);
1095 johnpye 542 #endif
1096 ben.allan 704
1097 johnpye 908 #if 0
1098     V(strlen(temp[0]));
1099     X(temp[0]);
1100     V(strlen(temp[1]));
1101     X(temp[1]);
1102     #endif
1103 ben.allan 704
1104 johnpye 908 /* make sure rhs path has NOT got a / at the start. */
1105 ben.allan 704 if(temp[1][0] == PATH_SEPARATOR_CHAR){
1106     return NULL;
1107     }
1108    
1109 johnpye 908 /* create a new path object with the two path strings appended together.*/
1110 ben.allan 704 STRNCPY(temp2,temp[0],PATH_MAX);
1111     STRNCAT(temp2,temp[1],PATH_MAX-strlen(temp2));
1112 johnpye 908 #if 0
1113     V(strlen(temp2));
1114     X(temp2);
1115     #endif
1116 ben.allan 704 r = ospath_new_noclean(temp2);
1117     D(r);
1118    
1119     /* ospath_cleanup(r);*/
1120     return r;
1121     }
1122    
1123     void ospath_append(struct FilePath *fp, struct FilePath *fp1){
1124     char *p;
1125     char temp[2][PATH_MAX];
1126     struct FilePath fp2;
1127    
1128     ospath_copy(&fp2,fp1);
1129 johnpye 542 #ifdef DO_FIXSLASHES
1130 ben.allan 704 ospath_fixslash(fp2.path);
1131     #endif
1132    
1133     if(!ospath_isvalid(&fp2)){
1134     M("fp1 invalid");
1135     return;
1136     }
1137    
1138     if(!ospath_isvalid(fp) && ospath_isvalid(&fp2)){
1139 johnpye 908 /* set this object to be the same as the rhs */
1140 ben.allan 704 M("fp invalid");
1141     ospath_copy(fp,&fp2);
1142     #ifdef DO_FIXSLASHES
1143 johnpye 542 ospath_fixslash(fp->path);
1144 ben.allan 704 #endif
1145     return;
1146     }
1147    
1148     X(fp->path);
1149     X(fp2.path);
1150    
1151 johnpye 908 /* both paths are valid...*/
1152     #if 0
1153     temp[0] = CALLOC(1+strlen(fp->path), sizeof(char));
1154     #endif
1155 ben.allan 704 STRNCPY(temp[0], fp->path, PATH_MAX);
1156 johnpye 908 #if 0
1157     temp[1] = CALLOC(strlen(fp2.path), sizeof(char));
1158     #endif
1159 ben.allan 704 STRNCPY(temp[1], fp2.path, PATH_MAX);
1160    
1161     X(temp[0]);
1162     X(temp[1]);
1163    
1164 johnpye 908 /* make sure temp has a / on the end. */
1165 ben.allan 704 if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR)
1166     {
1167     STRCAT(temp[0],PATH_SEPARATOR_STR);
1168     }
1169    
1170 johnpye 908 /* make sure rhs path has NOT got a / at the start. */
1171 ben.allan 704 if(temp[1][0] == PATH_SEPARATOR_CHAR){
1172     for(p=temp[1]+1; *p != '\0'; ++p){
1173     *(p-1)=*p;
1174     }
1175     *(p-1)='\0';
1176     }
1177    
1178     X(temp[0]);
1179     X(temp[1]);
1180    
1181 johnpye 908 /*create new path string.*/
1182 ben.allan 704 STRNCPY(fp->path,temp[0], PATH_MAX);
1183     STRNCAT(fp->path,temp[1], PATH_MAX-strlen(fp->path));
1184    
1185     X(fp->path);
1186    
1187 johnpye 908 #if 0
1188     FREE(temp[0]);
1189     M("Freed temp[0]");
1190     FREE(temp[1]);
1191     M("Freed temp[1]");
1192     #endif
1193 ben.allan 704
1194     D(fp);
1195     ospath_cleanup(fp);
1196 johnpye 542 }
1197    
1198 ben.allan 704 void ospath_copy(struct FilePath *dest, struct FilePath *src){
1199     STRCPY(dest->path,src->path);
1200     #ifdef WINPATHS
1201     STRCPY(dest->drive,src->drive);
1202     #endif
1203     }
1204    
1205     void ospath_debug(struct FilePath *fp){
1206     #ifdef WINPATHS
1207     fprintf(stderr,"{\"%s\",\"%s\"}\n",fp->drive,fp->path);
1208     #else
1209     fprintf(stderr,"{\"%s\"}\n",fp->path);
1210     #endif
1211     }
1212    
1213 johnpye 542 FILE *ospath_fopen(struct FilePath *fp, const char *mode){
1214     char s[PATH_MAX];
1215 johnpye 635 FILE *f;
1216    
1217 johnpye 542 if(!ospath_isvalid(fp)){
1218     E("Invalid path");
1219     return NULL;
1220     }
1221 johnpye 741 ospath_strncpy(fp,s,PATH_MAX);
1222 johnpye 635 f = fopen(s,mode);
1223 ben.allan 704 return f;
1224 johnpye 542 }
1225 johnpye 662
1226 johnpye 741 int ospath_stat(struct FilePath *fp,ospath_stat_t *buf){
1227 johnpye 662 char s[PATH_MAX];
1228    
1229     if(!ospath_isvalid(fp)){
1230     E("Invalid path");
1231     return -1;
1232     }
1233 johnpye 741 ospath_strncpy(fp,s,PATH_MAX);
1234 johnpye 742 return STAT(s,buf);
1235 johnpye 741 }
1236 ben.allan 704
1237 johnpye 908 /*------------------------
1238     SEARCH PATH FUNCTIONS
1239     */
1240 ben.allan 704
1241     struct FilePath **ospath_searchpath_new(const char *path){
1242     char *p;
1243     char *list[LISTMAX];
1244     unsigned n=0;
1245     char *c;
1246     unsigned i;
1247     struct FilePath **pp;
1248 johnpye 908 char path1[PATH_MAX];
1249    
1250 johnpye 542 STRTOKVAR(nexttok);
1251    
1252     strncpy(path1,path,PATH_MAX);
1253    
1254     X(path1);
1255     X(PATH_LISTSEP_STR);
1256    
1257     V(strlen(path1));
1258     V(strlen(PATH_LISTSEP_STR));
1259    
1260     /*
1261     c = strstr(path,PATH_LISTSEP_CHAR);
1262     if(c==NULL){
1263     E("NO TOKEN FOUND");
1264     }
1265 ben.allan 704 */
1266 johnpye 542
1267     p=STRTOK(path1,PATH_LISTSEP_STR,nexttok);
1268 ben.allan 704 X(p);
1269     for(; p!= NULL; p=STRTOK(NULL,PATH_LISTSEP_STR,nexttok)){
1270     c = (char *)MALLOC(sizeof(char)*(strlen(p)+1));
1271     X(p);
1272     STRCPY(c,p);
1273     if(n>=LISTMAX){
1274     E("IGNORING SOME PATH COMPONENTS");
1275     break;
1276     }
1277     list[n++]=c;
1278     }
1279    
1280 johnpye 866
1281 johnpye 542 for(i=0;i<n;++i){
1282 ben.allan 704 X(list[i]);
1283     }
1284     V(n);
1285    
1286 johnpye 866
1287 ben.allan 704 pp = (struct FilePath **)MALLOC(sizeof(struct FilePath*)*(n+1));
1288     for(i=0; i<n; ++i){
1289 johnpye 908 #if 0
1290     V(i);
1291     X(list[i]);
1292     #endif
1293 ben.allan 704 pp[i] = ospath_new_noclean(list[i]);
1294 johnpye 908 #if 0
1295     D(pp[i]);
1296     #endif
1297 johnpye 998 FREE(list[i]);
1298 ben.allan 704 }
1299     pp[n] = NULL;
1300    
1301     for(i=0;i<n;++i){
1302 johnpye 542 #ifdef DO_FIXSLASHES
1303     ospath_fixslash(pp[i]->path);
1304 ben.allan 704 #endif
1305     D(pp[i]);
1306     }
1307    
1308     return pp;
1309 johnpye 542 }
1310    
1311     void ospath_searchpath_free(struct FilePath **searchpath){
1312     struct FilePath **p;
1313     for(p=searchpath; *p!=NULL; ++p){
1314     ospath_free(*p);
1315     }
1316     FREE(searchpath);
1317 ben.allan 704 }
1318 johnpye 662
1319     int ospath_searchpath_length(struct FilePath **searchpath){
1320     int i=0;
1321     struct FilePath **p;
1322     for(p=searchpath; *p!=NULL; ++p){
1323     ++i;
1324     }
1325     return i;
1326     }
1327 ben.allan 704
1328     struct FilePath *ospath_searchpath_iterate(
1329     struct FilePath **searchpath
1330     , FilePathTestFn *testfn
1331     , void *searchdata
1332     ){
1333     struct FilePath **p;
1334    
1335 johnpye 542 p = searchpath;
1336    
1337     M("SEARCHING IN...");
1338     for(p=searchpath; *p!=NULL; ++p){
1339     D(*p);
1340 ben.allan 704 }
1341    
1342     for(p=searchpath; *p!=NULL; ++p){
1343 johnpye 542 D(*p);
1344 johnpye 662 assert(*p!=NULL);
1345 ben.allan 704 if((*testfn)(*p,searchdata)){
1346     return *p;
1347     }
1348     }
1349     return NULL;
1350     }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22