/dev/dmd2/src/dmd/tk/filespec.c

https://github.com/soywiz/pspemu · C · 424 lines · 352 code · 47 blank · 25 comment · 172 complexity · d6572c488c4a2e30f106f0e88633e16a MD5 · raw file

  1. /*_ filespec.c Mon Jul 3 1989 Modified by: Walter Bright */
  2. /* Copyright (C) 1986-1987 by Northwest Software */
  3. /* All Rights Reserved */
  4. /* Written by Walter Bright */
  5. /* Package with which to manipulate filespecs */
  6. #include <stdio.h>
  7. #include "filespec.h"
  8. #ifndef MEM_H
  9. #include "mem.h"
  10. #endif
  11. #ifndef VAX11C
  12. #include <string.h>
  13. #endif
  14. #if BSDUNIX
  15. #include <pwd.h>
  16. #endif
  17. #if MSDOS || __OS2__ || __NT__ || _WIN32
  18. #include <direct.h>
  19. #include <ctype.h>
  20. #endif
  21. #if M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #endif
  25. #ifndef assert
  26. #include <assert.h>
  27. #endif
  28. /* Macro to determine if char is a path or drive delimiter */
  29. #if MSDOS || __OS2__ || __NT__ || _WIN32
  30. #define ispathdelim(c) ((c) == '\\' || (c) == ':' || (c) == '/')
  31. #else
  32. #ifdef VMS
  33. #define ispathdelim(c) ((c)==':' || (c)=='[' || (c)==']' )
  34. #else
  35. #ifdef MPW
  36. #define ispathdelim(c) ((c) == ':')
  37. #else
  38. #define ispathdelim(c) ((c) == '/')
  39. #endif /* MPW */
  40. #endif /* VMS */
  41. #endif
  42. /**********************/
  43. char * filespecaddpath(const char *path,const char *filename)
  44. { register char *filespec;
  45. register unsigned pathlen;
  46. if (!path || (pathlen = strlen(path)) == 0)
  47. filespec = mem_strdup(filename);
  48. else
  49. {
  50. filespec = (char *) mem_malloc(pathlen + 1 + strlen(filename) + 1);
  51. if (filespec)
  52. { strcpy(filespec,path);
  53. #if MSDOS || __OS2__ || __NT__ || _WIN32
  54. if (!ispathdelim(filespec[pathlen - 1]))
  55. strcat(filespec,"\\");
  56. #else
  57. #if VMS
  58. #else
  59. #if MPW
  60. if (!ispathdelim(filespec[pathlen - 1]))
  61. strcat(filespec,":");
  62. #else
  63. if (!ispathdelim(filespec[pathlen - 1]))
  64. strcat(filespec,"/");
  65. #endif /* MPW */
  66. #endif /* VMS */
  67. #endif
  68. strcat(filespec,filename);
  69. }
  70. }
  71. return filespec;
  72. }
  73. #ifndef MPW
  74. /**********************/
  75. char * filespecrootpath(char *filespec)
  76. {
  77. #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  78. #define DIRCHAR '/'
  79. #endif
  80. #if MSDOS || __OS2__ || __NT__ || _WIN32
  81. #define DIRCHAR '\\'
  82. #endif
  83. #ifdef MPW
  84. #define DIRCHAR ':'
  85. #endif
  86. char *cwd, *cwd_t;
  87. char *p, *p2;
  88. if (!filespec)
  89. return filespec;
  90. #if MSDOS || __OS2__ || __NT__ || _WIN32
  91. /* if already absolute (with \ or drive:) ... */
  92. if (*filespec == DIRCHAR || (isalpha((unsigned char)*filespec) && *(filespec+1) == ':'))
  93. return filespec; /* ... return input string */
  94. #else
  95. if (*filespec == DIRCHAR) /* already absolute ... */
  96. return filespec; /* ... return input string */
  97. #endif
  98. /* get current working directory path */
  99. #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  100. cwd_t = (char *)getcwd(NULL, 256);
  101. #endif
  102. #if MSDOS || __OS2__ || __NT__ || _WIN32
  103. char cwd_d[132];
  104. if (getcwd(cwd_d, sizeof(cwd_d)))
  105. cwd_t = cwd_d;
  106. else
  107. cwd_t = NULL;
  108. #endif
  109. if (cwd_t == NULL)
  110. {
  111. mem_free(filespec);
  112. return NULL; /* error - path too long (more than 256 chars !)*/
  113. }
  114. cwd = mem_strdup(cwd_t); /* convert cwd to mem package */
  115. #if MSDOS
  116. assert(strlen(cwd) > 0);
  117. if (cwd[strlen(cwd) - 1] == DIRCHAR)
  118. cwd[strlen(cwd) - 1] = '\0';
  119. #endif
  120. #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  121. free(cwd_t);
  122. #endif
  123. p = filespec;
  124. while (p != NULL)
  125. {
  126. p2 = (char *)strchr(p, DIRCHAR);
  127. if (p2 != NULL)
  128. {
  129. *p2 = '\0';
  130. if (strcmp(p, "..") == 0) /* move up cwd */
  131. /* remove last directory from cwd */
  132. *((char *)strrchr(cwd, DIRCHAR)) = '\0';
  133. else if (strcmp(p, ".") != 0) /* not current directory */
  134. {
  135. cwd_t = cwd;
  136. cwd = (char *)mem_calloc(strlen(cwd_t) + 1 + strlen(p) + 1);
  137. #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  138. sprintf(cwd, "%s/%s", cwd_t, p); /* add relative directory */
  139. #endif
  140. #if MSDOS || __OS2__ || __NT__ || _WIN32
  141. sprintf(cwd, "%s\\%s", cwd_t, p); /* add relative directory */
  142. #endif
  143. mem_free(cwd_t);
  144. }
  145. /* else if ".", then ignore - it means current directory */
  146. *p2 = DIRCHAR;
  147. p2++;
  148. }
  149. else if (strcmp(p,"..") == 0) /* move up cwd */
  150. {
  151. /* remove last directory from cwd */
  152. *((char *)strrchr(cwd, DIRCHAR)) = '\0';
  153. }
  154. else if (strcmp(p,".") != 0) /* no more subdirectories ... */
  155. { /* ... save remaining string */
  156. cwd_t = cwd;
  157. cwd = (char *)mem_calloc(strlen(cwd_t) + 1 + strlen(p) + 1);
  158. #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  159. sprintf(cwd, "%s/%s", cwd_t, p); /* add relative directory */
  160. #endif
  161. #if MSDOS || __OS2__ || __NT__ || _WIN32
  162. sprintf(cwd, "%s\\%s", cwd_t, p); /* add relative directory */
  163. #endif
  164. mem_free(cwd_t);
  165. }
  166. p = p2;
  167. }
  168. mem_free(filespec);
  169. return cwd;
  170. #ifdef VMS
  171. assert(0);
  172. #endif
  173. }
  174. #endif
  175. /**********************/
  176. char * filespecdotext(const char *filespec)
  177. { register const char *p;
  178. register int len;
  179. if ((p = filespec) != NULL)
  180. { p += (len = strlen(p));
  181. while (1)
  182. { if (*p == '.')
  183. break;
  184. if (p <= filespec || ispathdelim(*p))
  185. { p = filespec + len;
  186. break;
  187. }
  188. p--;
  189. }
  190. }
  191. return (char *)p;
  192. }
  193. /**********************/
  194. char * filespecname(const char *filespec)
  195. { register const char *p;
  196. /* Start at end of string and back up till we find the beginning */
  197. /* of the filename or a path. */
  198. for (p = filespec + strlen(filespec);
  199. p != filespec && !ispathdelim(*(p - 1));
  200. p--
  201. )
  202. ;
  203. return (char *)p;
  204. }
  205. /***********************/
  206. char * filespecgetroot(const char *name)
  207. { char *root,*p,c;
  208. p = filespecdotext(name);
  209. c = *p;
  210. *p = 0;
  211. root = mem_strdup(name);
  212. *p = c;
  213. return root;
  214. }
  215. /*****************************/
  216. char * filespecforceext(const char *filespec,const char *ext)
  217. { register char *p;
  218. register const char *pext;
  219. if (*ext == '.')
  220. ext++;
  221. if ((p = (char *)filespec) != NULL)
  222. { pext = filespecdotext(filespec);
  223. if (ext)
  224. { int n = pext - filespec;
  225. p = (char *) mem_malloc(n + 1 + strlen(ext) + 1);
  226. if (p)
  227. { memcpy(p,filespec,n);
  228. p[n] = '.';
  229. strcpy(&p[n + 1],ext);
  230. }
  231. }
  232. else
  233. p = mem_strdup(filespec);
  234. }
  235. return p;
  236. }
  237. /*****************************/
  238. char * filespecdefaultext(const char *filespec,const char *ext)
  239. { register char *p;
  240. register const char *pext;
  241. pext = filespecdotext(filespec);
  242. if (*pext == '.') /* if already got an extension */
  243. {
  244. p = mem_strdup(filespec);
  245. }
  246. else
  247. { int n = pext - filespec;
  248. p = (char *) mem_malloc(n + 1 + strlen(ext) + 1);
  249. if (p)
  250. {
  251. memcpy(p,filespec,n);
  252. p[n] = '.';
  253. strcpy(&p[n + 1],ext);
  254. }
  255. }
  256. return p;
  257. }
  258. /************************************/
  259. #if !(MSDOS || __OS2__ || __NT__ || _WIN32)
  260. char *filespectilde(char *filespec)
  261. {
  262. #if BSDUNIX
  263. struct passwd *passwdPtr;
  264. register char *f;
  265. if (filespec && *filespec == '~')
  266. {
  267. passwdPtr = NULL;
  268. if (filespec[1] == '/' || filespec[1] == 0) /* if ~/... or ~ */
  269. { f = filespec + 1;
  270. passwdPtr = getpwuid(getuid());
  271. }
  272. else /* else ~name */
  273. {
  274. char c;
  275. f = strpbrk(filespec," /");
  276. if (!f)
  277. f = filespec + strlen(filespec); /* point at trailing 0 */
  278. c = *f;
  279. *f = 0;
  280. passwdPtr = getpwnam(filespec + 1);
  281. *f = c;
  282. }
  283. if (passwdPtr)
  284. { char *p;
  285. p = (char *) mem_malloc(strlen(passwdPtr->pw_dir) + strlen(f) + 1);
  286. if (p)
  287. {
  288. strcpy(p,passwdPtr->pw_dir);
  289. strcat(p,f);
  290. mem_free(filespec);
  291. filespec = p;
  292. }
  293. }
  294. }
  295. #endif
  296. #if MSDOS || __OS2__ || __NT__ || _WIN32
  297. #endif
  298. #if VMS
  299. assert(0);
  300. #endif
  301. return filespec;
  302. }
  303. /************************************/
  304. char *filespecmultitilde(char *string)
  305. {
  306. register char *p, *p2, *p3, *p4;
  307. string = filespectilde(string); /* expand if first character is a '~' */
  308. if (string)
  309. {
  310. for (p = string; *p != '\0'; p++)
  311. {
  312. if (*p == '~')
  313. {
  314. *p = '\0'; /* terminate sub string */
  315. p2 = mem_strdup(string); /* get new sub string from old string */
  316. *p = '~'; /* reset ~ character */
  317. for (p3 = p + 1; *p3 != ' ' && *p3 != '\0'; p3++)
  318. ; /* scan to next name, or end of the string */
  319. p4 = NULL;
  320. if (*p3 == ' ')
  321. {
  322. p4 = mem_strdup(p3); /* save reminder of the string */
  323. *p3 = '\0';
  324. }
  325. p = mem_strdup(p); /* get tilde string */
  326. mem_free(string);
  327. p = filespectilde(p);
  328. /* reconstruct the string from pieces */
  329. if (p4)
  330. {
  331. string = (char *)
  332. mem_calloc(strlen(p2) + strlen(p) + strlen(p4) + 1);
  333. sprintf(string, "%s%s%s", p2, p, p4);
  334. }
  335. else
  336. {
  337. string = (char *)
  338. mem_calloc(strlen(p2) + strlen(p) + 1);
  339. sprintf(string, "%s%s", p2, p);
  340. }
  341. mem_free(p);
  342. p = string + strlen(p2) + 2;
  343. mem_free(p2);
  344. if (p4)
  345. mem_free(p4);
  346. }
  347. }
  348. }
  349. return string;
  350. }
  351. #endif
  352. #ifndef MPW
  353. /************************************/
  354. char * filespecbackup(const char *filespec)
  355. {
  356. #if MSDOS || __OS2__ || __NT__ || _WIN32
  357. return filespecforceext(filespec,"BAK");
  358. #endif
  359. #if BSDUNIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  360. char *p,*f;
  361. /* Prepend .B to file name, if it isn't already there */
  362. if (!filespec)
  363. return (char *)filespec;
  364. p = filespecname(filespec);
  365. if (p[0] == '.' && p[1] == 'B')
  366. return mem_strdup(filespec);
  367. f = (char *) mem_malloc(strlen(filespec) + 2 + 1);
  368. if (f)
  369. { strcpy(f,filespec);
  370. strcpy(&f[p - filespec],".B");
  371. strcat(f,p);
  372. }
  373. return f;
  374. #endif
  375. }
  376. #endif