home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / forut062.zip / ForUtil-0.62 / lib / SplitPath.c < prev    next >
C/C++ Source or Header  |  1996-08-28  |  8KB  |  292 lines

  1. #ifndef lint
  2. static char rcsId[]="$Source: /usr/local/rcs/ForUtil/lib/RCS/SplitPath.c,v $";
  3. #endif
  4. /*****
  5. * SplitPath.c : splits a filename in a fully qualified path and name
  6. *    component.
  7. *
  8. * This file Version    $Revision: 1.7 $
  9. *
  10. * Creation date:    Mon Feb  5 02:44:15 GMT+0100 1996
  11. * Last modification:     $Date: 1996/08/27 19:19:10 $
  12. * By:            $Author: koen $
  13. * Current State:    $State: Exp $
  14. *
  15. * Author:        Mark Edel with modifications by koen
  16. *****/
  17. /*****
  18. * ChangeLog 
  19. * $Log: SplitPath.c,v $
  20. * Revision 1.7  1996/08/27 19:19:10  koen
  21. * Added the get_filename_part routine
  22. *
  23. * Revision 1.6  1996/08/07 21:17:27  koen
  24. * Corrected a bug in normalizePathname for MSDOS.
  25. *
  26. * Revision 1.5  1996/08/02 14:52:42  koen
  27. * Replaced forLibP.h with forutil.h
  28. *
  29. * Revision 1.4  1996/07/30 02:02:27  koen
  30. * Added the get_filename_part routine.
  31. *
  32. * Revision 1.3  1996/07/16 09:17:53  koen
  33. * corrected copyright
  34. *
  35. * Revision 1.2  1996/05/06 00:36:25  koen
  36. * Adapted for MSDOS: now using generic slashes. Specific code for getting the 
  37. * correct path name under msdos.
  38. *
  39. * Revision 1.1  1996/02/05 01:45:29  koen
  40. * Initial revision
  41. *
  42. *****/ 
  43. /* needed to prevent multiple variable decls under MSDOS in sysdeps.h */
  44. #define LIBRARY_OBJECT
  45.  
  46. /* include this before anything else */
  47. #ifdef HAVE_CONFIG_H
  48. #include "autoconf.h"
  49. #endif
  50.  
  51. #include <stdio.h>
  52. #include <string.h> 
  53. #include <stdlib.h> 
  54. #include <limits.h> 
  55. #include <ctype.h>
  56.  
  57. #include "forutil.h"
  58.  
  59. /*****************Private functions prototypes*************************/
  60.  
  61. static int normalizePathname(char *pathname);
  62. static int compressPathname(char *pathname);
  63. static char *nextSlash(char *ptr);
  64. static char *prevSlash(char *ptr);
  65. static int compareThruSlash(char *string1, char *string2);
  66. static void copyThruSlash(char **toString, char **fromString);
  67.  
  68. /*
  69. * return only the filename part of a file specification
  70. */
  71. void
  72. get_filename_part(char *fullname, char *filename)
  73. {
  74.     int fullLen = strlen(fullname);
  75.     int i, pathLen, fileLen;
  76.     /* find the last slash */
  77.     for (i=fullLen-1; i>=0; i--) {
  78.         if (fullname[i] == SLASH)
  79.         break;
  80.     }
  81.     /* move chars before / (or ] or :) into pathname,& after into filename */
  82.     pathLen = i + 1;
  83.     fileLen = fullLen - pathLen;
  84.     strncpy(filename, &fullname[pathLen], fileLen);
  85.     filename[fileLen] = 0;
  86.     return;
  87. }
  88.  
  89. /* 
  90. * Decompose a Unix file name into a file name and a path
  91. * This function originally comes from Nedit. 
  92. * Used with kind permission of Mark Edel (Author of Nedit).  
  93. */ 
  94.  
  95. int ParseFilename(char *fullname, char *filename, char *pathname)
  96. {
  97.     int fullLen = strlen(fullname);
  98.     int i, pathLen, fileLen;
  99.     /* find the last slash */
  100.     for (i=fullLen-1; i>=0; i--) {
  101.         if (fullname[i] == SLASH)
  102.         break;
  103.     }
  104.     /* move chars before / (or ] or :) into pathname,& after into filename */
  105.     pathLen = i + 1;
  106.     fileLen = fullLen - pathLen;
  107.     strncpy(pathname, fullname, pathLen);
  108.     pathname[pathLen] = 0;
  109.     strncpy(filename, &fullname[pathLen], fileLen);
  110.     filename[fileLen] = 0;
  111.     return(normalizePathname(pathname));
  112. }
  113.  
  114. static int normalizePathname(char *pathname)
  115. {
  116.     static char oldPathname[MAXPATHLEN], *wd;
  117.  
  118.     /* if this is a relative pathname, prepend current directory */
  119. #ifndef __MSDOS__
  120.     if (pathname[0] != SLASH)
  121.     {     /* make a copy of pathname to work from */
  122.         strcpy(oldPathname, pathname);
  123.         /* get the working directory */
  124.         wd = getcwd(NULL, MAXPATHLEN);
  125.         /* prepend it to the path */
  126.         strcpy(pathname, wd);
  127.         strcat(pathname, CHAR_SLASH);
  128.         strcat(pathname, oldPathname);
  129.     }
  130.     /* compress out .. and . */
  131.     return compressPathname(pathname);
  132. #else
  133.     /* relative directories in msdos can start with a . or a drive spec. */
  134.     if (pathname[0] == '.' ||
  135.         (isascii(pathname[0]) && pathname[1] == ':' && pathname[2] != '\\'))
  136.     {
  137.         /* make a copy of pathname to work from */
  138.         strcpy(oldPathname, pathname);
  139.         /*
  140.         * OK, fuzzy msdos, if the second char is a :, the first two chars
  141.         * specify another drive. To get the current wd on that drive,
  142.         * chdir to that drive, and get the working directory on that drive,
  143.         * else just get the current directory.
  144.         */
  145.         if(pathname[1] == ':')
  146.         {
  147.             char *curr_dir, *wd2_dir;
  148.             int curr_disk, new_disk;
  149.             /* let wd point right past the [drive:] stuff */
  150.             wd = pathname + 2;
  151.             strcpy(oldPathname, wd);
  152.             wd = NULL;
  153.             /* get current drive & directory */
  154.             curr_dir = getcwd(NULL, MAXPATHLEN);
  155.             curr_disk = getdisk();
  156.             new_disk = toupper(pathname[0]) - 65;
  157.             /* change disk */
  158.             setdisk(new_disk);
  159.             /* get current directory on this drive */
  160.             wd2_dir = getcwd(NULL, MAXPATHLEN);
  161.             /*
  162.             *  set & get current directory. This ensures that a path spec.
  163.             * a la d:..\..\foo will be resolved in a fully qualified path.
  164.             */
  165.             chdir(pathname);
  166.             wd = getcwd(NULL, MAXPATHLEN);
  167.             /* change back to original dir on this drive */
  168.             chdir(wd2_dir);
  169.             /* change back to original disk & path */
  170.             setdisk(curr_disk);
  171.             chdir(curr_dir);
  172.             /* remove the trailing slash */
  173.             if(wd[strlen(wd)-1] == SLASH)
  174.                 wd[strlen(wd)-1] = '\0';
  175.             /* free the chars getcwd returns */
  176.             free(curr_dir);
  177.             free(wd2_dir);
  178.         }
  179.         else
  180.             wd = getcwd(NULL, MAXPATHLEN);
  181.         /* prepend it to the path */
  182.         strcpy(pathname, wd);
  183.         strcat(pathname, CHAR_SLASH);
  184.         strcat(pathname, oldPathname);
  185.     }
  186.     /* compress out .. and . */
  187.     return compressPathname(pathname);
  188. #endif
  189. }
  190.  
  191.  
  192. static int compressPathname(char *pathname)
  193. {
  194.     char *inPtr, *outPtr;
  195.  
  196.     /* compress out . and .. */
  197.     inPtr = &pathname[1];        /* start after initial / */
  198.     outPtr = &pathname[1];
  199.     while (1) {
  200.     /* if the next component is "../", remove previous component */
  201.     if (compareThruSlash(inPtr, ".."CHAR_SLASH)) {
  202.         /* error if already at beginning of string */
  203.         if (outPtr == &pathname[1])
  204.             return 0;
  205.         /* back up outPtr to remove last path name component */
  206.         outPtr = prevSlash(outPtr);
  207.         inPtr = nextSlash(inPtr);
  208.     } else if (compareThruSlash(inPtr, "."CHAR_SLASH)) {
  209.         /* don't copy the component if it's the redundant "./" */
  210.         inPtr = nextSlash(inPtr);
  211.     } else {
  212.         /* copy the component to outPtr */
  213.         copyThruSlash(&outPtr, &inPtr);
  214.     }
  215.     if (inPtr == NULL) {
  216.         return 1;
  217.     }
  218.     }
  219. }
  220.  
  221. static char *nextSlash(char *ptr)
  222. {
  223.     for(; *ptr!=SLASH; ptr++) {
  224.         if (*ptr == '\0')
  225.         return NULL;
  226.     }
  227.     return ptr + 1;
  228. }
  229.  
  230. static char *prevSlash(char *ptr)
  231. {
  232.     for(ptr -= 2; *ptr!=SLASH; ptr--);
  233.     return ptr + 1;
  234. }
  235.  
  236. static int compareThruSlash(char *string1, char *string2)
  237. {
  238.     while (1) {
  239.         if (*string1 != *string2)
  240.         return 0;
  241.     if (*string1 =='\0' || *string1==SLASH)
  242.         return 1;
  243.     string1++;
  244.     string2++;
  245.     }
  246. }
  247.  
  248. static void copyThruSlash(char **toString, char **fromString)
  249. {
  250.     char *to = *toString;
  251.     char *from = *fromString;
  252.     
  253.     while (1) {
  254.         *to = *from;
  255.         if (*from =='\0') {
  256.             *fromString = NULL;
  257.             return;
  258.         }
  259.     if (*from==SLASH) {
  260.         *toString = to + 1;
  261.         *fromString = from + 1;
  262.         return;
  263.     }
  264.     from++;
  265.     to++;
  266.     }
  267. }
  268.  
  269. #ifdef TEST
  270. int main(int argc, char **argv)
  271. {
  272.     static char path[256], file[14];
  273.  
  274.     fprintf(stderr, "Testing d:\\usr\\bcc\\include\\stdio.h\n");
  275.     ParseFilename("d:\\usr\\bcc\\include\\stdio.h", file,path);
  276.     fprintf(stderr, "path: %s\nfile: %s\n", path, file);
  277.  
  278.     fprintf(stderr, "Testing ..\\autoconf.h\n");
  279.     ParseFilename("..\\autoconf.h", file,path);
  280.     fprintf(stderr, "path: %s\nfile: %s\n", path, file);
  281.  
  282.     fprintf(stderr, "Testing d:..\\foo.txt\n");
  283.     ParseFilename("d:..\\foo.txt", file,path);
  284.     fprintf(stderr, "path: %s\nfile: %s\n", path, file);
  285.  
  286.     fprintf(stderr, "Testing d:..\\..\\foo.txt\n");
  287.     ParseFilename("d:..\\..\\foo.txt", file,path);
  288.     fprintf(stderr, "path: %s\nfile: %s\n", path, file);
  289.     return(0);
  290. }
  291. #endif
  292.