path.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 2017 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * path.c - host operating system specific pathname manipulation functions
  35. *
  36. * This file is inherently nonportable ... please help adjusting it to
  37. * any new platforms that may be necessary.
  38. */
  39. #include "compiler.h"
  40. #include "nasmlib.h"
  41. #include "error.h"
  42. #if defined(__MSDOS__) || defined(__DOS__) || \
  43. defined(__WINDOWS__) || defined(_Windows) || \
  44. defined(__OS2__) || defined(_WIN16) || defined(WIN32) || defined(_WIN32)
  45. /* MS-DOS/Windows and like operating systems */
  46. # define separators "/\\:"
  47. # define cleandirend "/\\"
  48. # define catsep '\\'
  49. # define leaveonclean 2 /* Leave \\ at the start alone */
  50. # define curdir "."
  51. #elif defined(unix) || defined(__unix) || defined(__unix__) || \
  52. defined(__UNIX__) || defined(__Unix__) || \
  53. defined(__MACH__) || defined(__BEOS__)
  54. /* Unix and Unix-like operating systems and others using
  55. * the equivalent syntax (slashes as only separators, no concept of volume)
  56. *
  57. * This must come after the __MSDOS__ section, since it seems that at
  58. * least DJGPP defines __unix__ despite not being a Unix environment at all.
  59. */
  60. # define separators "/"
  61. # define cleandirend "/"
  62. # define catsep '/'
  63. # define leaveonclean 1
  64. # define curdir "."
  65. #elif defined(Macintosh) || defined(macintosh)
  66. /* MacOS classic */
  67. # define separators ":"
  68. # define curdir ":"
  69. # define catsep ':'
  70. # define cleandirend ":"
  71. # define leaveonclean 0
  72. # define leave_leading 1
  73. #elif defined(__VMS)
  74. /* VMS *
  75. *
  76. * VMS filenames may have ;version at the end. Assume we should count that
  77. * as part of the filename anyway.
  78. */
  79. # define separators ":]"
  80. # define curdir "[]"
  81. #else
  82. /* No idea what to do here, do nothing. Feel free to add new ones. */
  83. # define curdir ""
  84. #endif
  85. /*
  86. * This is an inline, because most compilers can greatly simplify this
  87. * for a fixed string, like we have here.
  88. */
  89. static inline bool ismatch(const char *charset, char ch)
  90. {
  91. const char *p;
  92. for (p = charset; *p; p++) {
  93. if (ch == *p)
  94. return true;
  95. }
  96. return false;
  97. }
  98. static const char *first_filename_char(const char *path)
  99. {
  100. #ifdef separators
  101. const char *p = path + strlen(path);
  102. while (p > path) {
  103. if (ismatch(separators, p[-1]))
  104. return p;
  105. p--;
  106. }
  107. return p;
  108. #else
  109. return path;
  110. #endif
  111. }
  112. /* Return the filename portion of a PATH as a new string */
  113. char *nasm_basename(const char *path)
  114. {
  115. return nasm_strdup(first_filename_char(path));
  116. }
  117. /* Return the directory name portion of a PATH as a new string */
  118. char *nasm_dirname(const char *path)
  119. {
  120. const char *p = first_filename_char(path);
  121. const char *p0 = p;
  122. (void)p0; /* Don't warn if unused */
  123. if (p == path)
  124. return nasm_strdup(curdir);
  125. #ifdef cleandirend
  126. while (p > path+leaveonclean) {
  127. if (ismatch(cleandirend, p[-1]))
  128. break;
  129. p--;
  130. }
  131. #endif
  132. #ifdef leave_leading
  133. /* If the directory contained ONLY separators, leave as-is */
  134. if (p == path+leaveonclean)
  135. p = p0;
  136. #endif
  137. return nasm_strndup(path, p-path);
  138. }
  139. /*
  140. * Concatenate a directory path and a filename. Note that this function
  141. * currently does NOT handle the case where file itself contains
  142. * directory components (except on Unix platforms, because it is trivial.)
  143. */
  144. char *nasm_catfile(const char *dir, const char *file)
  145. {
  146. #ifndef catsep
  147. return nasm_strcat(dir, file);
  148. #else
  149. size_t dl = strlen(dir);
  150. size_t fl = strlen(file);
  151. char *p, *pp;
  152. bool dosep = true;
  153. if (!dl || ismatch(separators, dir[dl-1])) {
  154. /* No separator necessary */
  155. dosep = false;
  156. }
  157. p = pp = nasm_malloc(dl + fl + dosep + 1);
  158. memcpy(pp, dir, dl);
  159. pp += dl;
  160. if (dosep)
  161. *pp++ = catsep;
  162. memcpy(pp, file, fl+1);
  163. return p;
  164. #endif
  165. }