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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2036 - (show annotations) (download) (as text)
Mon May 18 15:03:16 2009 UTC (15 years ago) by ballan
File MIME type: text/x-csrc
File size: 27073 byte(s)
issues resolved:
295
390
301
cmslv.c: unused var cleanup.
lsode/SConscript: fortran flags bugs-- may not work with 0.9x scons.
works with 1.2+. when adding -w, or any special flags, be sure to add
them and not replace the original flag.
system/var.c: 64bit clarity.
system/discrete.c: 64bit clarity.
system/analyze*: g_reuse declared in wrong place. 64bit clarity
system/diffvars: missing prototype function, 64bit clarity.
compiler/numlist.*: changed from int to glint.
compiler/simlist.c: missing includes needed for 64bit clarity.
compiler/instance_io.c: missing includes needed for 64bit clarity.
compiler/initialize.[ch]: const clarifications.
compiler/packages.c: const clarifications.
compiler/module.c: const clarifications.
compiler/statio.c: unused var cleanup.
compiler/procframe; const clarification. memory deallocation bugs.
compiler/notequery.c: repaired multiple casting and 64bit issues.
compiler/importhandler.c: const and free issues fixed.
compiler/type_desc.c: ridiculous if constructs clarified.
compiler/createinst.c: casting stupidity repaired.
linear/ranki2.c: missing includes needed for 64bitness.
solver/solver.c: const issues clarified.
utilities/ascConfig.h: added GLint typedefs for dealing with gllist
64bit portability.
utilities/ascPanic.c: removed extraneous const.
general/ospath.c: safer,quieter handling for string pointer difference.
integrator/integrator.c: const issues clarified.
packages/sensitivity.c: missing includes needed fo 64bit sanity.
tcltk/interface/Integrators.c: 64 bitness.
tcltk/interface/SimsProc.c: const errors.
tcltk/interface/Driver.c: fixed env var handling wrt ascend-config (295)
models/test/z*a4c: fixed meters -> m conversion; someone never ran the
test suite after teasing the default units to ambiguous abbreviations.
SConstruct: added sizeof checks; output might be better put in a ascend
system-wide header.


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

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