FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_path.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <errno.h>
10 #include "hecmw_config.h"
11 #include "hecmw_path.h"
12 #include "hecmw_util.h"
13 
14 #ifdef __MINGW32__
15 #define PATH_SEPARATOR '/'
16 #elif __MINGW64__
17 #define PATH_SEPARATOR '/'
18 #elif __CYGWIN__
19 #define PATH_SEPARATOR '/'
20 #elif __WIN32__
21 #define PATH_SEPARATOR '\\'
22 #else
23 #define PATH_SEPARATOR '/'
24 #endif
25 
26 #ifdef __WIN32__
27 #define isslash(c) ((c) == '/' || (c) == '\\')
28 #elif __CYGWIN__
29 #define isslash(c) ((c) == '/' || (c) == '\\')
30 #else
31 #define isslash(c) ((c) == '/')
32 #endif
33 
35 
36 static int has_drive(const char *path) {
37  const char *p = path;
38 
39  if (path == NULL) return 0;
40  if (!*p || !isalpha(*p)) return 0;
41  p++;
42  return (*p == ':');
43 }
44 
45 int HECMW_is_absolute_path(const char *path) {
46  if (path == NULL) return 0;
47 
48 #ifdef __WIN32__
49  if (*path && isslash(*path)) return 1;
50  return has_drive(path);
51 #elif __CYGWIN__
52  if (*path && isslash(*path)) return 1;
53  return has_drive(path);
54 #else
55  return (*path && isslash(*path));
56 #endif
57 }
58 
59 static char *dir_name(const char *path) {
60  const char *p;
61  static char dname[HECMW_FILENAME_LEN + 1];
62 
63  if (path == NULL || strlen(path) == 0) {
64  snprintf(dname, sizeof(dname), ".");
65  return dname;
66  }
67 
68  p = path + strlen(path) - 1;
69  while (p > path && isslash(*p)) {
70  p--;
71  }
72 
73  while (p > path && !isslash(*p)) {
74  p--;
75  }
76 
77  if (p == path) {
78  snprintf(dname, sizeof(dname), "%c", isslash(*p) ? PATH_SEPARATOR : '.');
79  return dname;
80  } else {
81  do {
82  p--;
83  } while (p > path && isslash(*p));
84  }
85 
86  if (p - path + 1 > HECMW_FILENAME_LEN) {
87  errno = ENAMETOOLONG;
88  return NULL;
89  }
90  snprintf(dname, sizeof(dname), "%.*s", (int)(p - path + 1), path);
91 
92  return dname;
93 }
94 
95 static char *base_name(const char *path) {
96  const char *sp, *ep;
97  static char bname[HECMW_FILENAME_LEN + 1];
98 
99  if (path == NULL || strlen(path) == 0) {
100  snprintf(bname, sizeof(bname), ".");
101  return bname;
102  }
103 
104  ep = path + strlen(path) - 1;
105  while (ep > path && isslash(*ep)) {
106  ep--;
107  }
108 
109  if (ep == path && isslash(*ep)) {
110  snprintf(bname, sizeof(bname), "%c", PATH_SEPARATOR);
111  return bname;
112  }
113 
114  sp = ep;
115  while (sp > path && !isslash(*(sp - 1))) {
116  sp--;
117  }
118 
119  if (ep - sp + 1 > HECMW_FILENAME_LEN) {
120  errno = ENAMETOOLONG;
121  return NULL;
122  }
123  snprintf(bname, sizeof(bname), "%.*s", (int)(ep - sp + 1), sp);
124 
125  return bname;
126 }
127 
128 static char *get_bdname(const char *path, int type) {
129  const char *p, *q;
130  static char bname[HECMW_FILENAME_LEN + 16];
131  char drive[10] = "";
132 
133  if (has_drive(path)) {
134  p = path + 2;
135  snprintf(drive, sizeof(drive), "%.2s", path);
136  } else {
137  p = path;
138  }
139  if (type == 'B') { /* basename */
140  q = base_name(p);
141  } else { /* dirname */
142  q = dir_name(p);
143  }
144  if (q == NULL) return NULL;
145  if (strlen(drive) > 0 && isslash(*q)) {
146  if (strlen(drive) + strlen(q) > HECMW_FILENAME_LEN) {
147  errno = ENAMETOOLONG;
148  return NULL;
149  }
150  snprintf(bname, sizeof(bname), "%s%s", drive, q);
151  } else {
152  snprintf(bname, sizeof(bname), "%s", q);
153  }
154  return bname;
155 }
156 
157 char *HECMW_basename(const char *path) {
158  char *bname = get_bdname(path, 'B');
159  if (bname == NULL) {
160  HECMW_set_error(errno, "");
161  }
162  return bname;
163 }
164 
165 char *HECMW_dirname(const char *path) {
166  char *dname = get_bdname(path, 'D');
167  if (dname == NULL) {
168  HECMW_set_error(errno, "");
169  }
170  return dname;
171 }
#define HECMW_FILENAME_LEN
Definition: hecmw_config.h:74
int HECMW_set_error(int errorno, const char *fmt,...)
Definition: hecmw_error.c:33
#define NULL
char * HECMW_basename(const char *path)
Definition: hecmw_path.c:157
#define isslash(c)
Definition: hecmw_path.c:31
#define PATH_SEPARATOR
Definition: hecmw_path.c:23
char * HECMW_dirname(const char *path)
Definition: hecmw_path.c:165
int HECMW_get_path_separator(void)
Definition: hecmw_path.c:34
int HECMW_is_absolute_path(const char *path)
Definition: hecmw_path.c:45