/Build/source/texk/ttf2pk2/emtexdir.c

https://bitbucket.org/preining/tex-live · C · 405 lines · 347 code · 53 blank · 5 comment · 152 complexity · fa613b41f628082a74c2cf9ccd54e013 MD5 · raw file

  1. /* emtexdir.c -- written by Eberhard Mattes, donated to the public domain */
  2. #if defined (__EMX__)
  3. #include <emx/syscalls.h>
  4. #else
  5. #include "emdir.h"
  6. #endif
  7. #if defined(DJGPP) || defined(GO32)
  8. #include <unistd.h>
  9. #endif
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <fcntl.h>
  13. #include <io.h>
  14. #include "emtexdir.h"
  15. #define FALSE 0
  16. #define TRUE 1
  17. void (*emtex_dir_find_callback)(const char *name, int ok) = NULL;
  18. static int setup_add (struct emtex_dir *dst, const char *path)
  19. {
  20. char *p;
  21. if (dst->used >= dst->alloc)
  22. {
  23. dst->alloc += 8;
  24. dst->list = realloc (dst->list, dst->alloc * sizeof (*dst->list));
  25. if (dst->list == NULL)
  26. return (FALSE);
  27. }
  28. p = strdup (path);
  29. if (p == NULL)
  30. return (FALSE);
  31. dst->list[dst->used++] = p;
  32. return (TRUE);
  33. }
  34. static int setup_subdir (struct emtex_dir *dst, char *path, size_t add,
  35. unsigned flags, int recurse)
  36. {
  37. int ok, i, end, len;
  38. #if defined (__EMX__)
  39. struct _find find;
  40. #else
  41. struct ll_findbuffer find;
  42. #endif
  43. i = dst->used;
  44. strcpy (path + add, "*.*");
  45. #if defined (__EMX__)
  46. ok = __findfirst (path, 0x10, &find) == 0;
  47. #else
  48. ok = ll_findfirst (path, 0x10, &find);
  49. #endif
  50. while (ok)
  51. {
  52. if ((find.attr & 0x10)
  53. && !(strcmp (find.name, ".") == 0 || strcmp (find.name, "..") == 0))
  54. {
  55. len = strlen (find.name);
  56. memcpy (path + add, find.name, len);
  57. path[add+len] = '\\';
  58. path[add+len+1] = 0;
  59. if (!setup_add (dst, path))
  60. return (FALSE);
  61. }
  62. #if defined (__EMX__)
  63. ok = __findnext (&find) == 0;
  64. #else
  65. ok = ll_findnext (&find);
  66. #endif
  67. }
  68. if (recurse)
  69. {
  70. end = dst->used;
  71. while (i < end)
  72. {
  73. strcpy (path, dst->list[i]);
  74. if (!setup_subdir (dst, path, strlen (path), flags, TRUE))
  75. return (FALSE);
  76. ++i;
  77. }
  78. }
  79. return (TRUE);
  80. }
  81. static int setup_dir (struct emtex_dir *dst, char *path,
  82. const char *base_dir, size_t base_dir_len,
  83. const char *sub_dir,
  84. unsigned flags)
  85. {
  86. size_t i, len;
  87. memcpy (path, base_dir, base_dir_len);
  88. i = base_dir_len;
  89. if ((flags & EDS_BANG) && sub_dir == NULL)
  90. {
  91. flags &= ~(EDS_ONESUBDIR|EDS_ALLSUBDIR);
  92. if (i >= 2 && path[i-1] == '!' && path[i-2] == '!')
  93. {
  94. flags |= EDS_ALLSUBDIR;
  95. i -= 2;
  96. }
  97. else if (i >= 1 && path[i-1] == '!')
  98. {
  99. flags |= EDS_ONESUBDIR;
  100. --i;
  101. }
  102. }
  103. if (sub_dir != NULL && *sub_dir != 0)
  104. {
  105. if (i != 0 && path[i-1] != ':' && path[i-1] != '/' && path[i-1] != '\\')
  106. path[i++] = '\\';
  107. len = strlen (sub_dir);
  108. memcpy (path+i, sub_dir, len);
  109. i += len;
  110. }
  111. if (path[i-1] != ':' && path[i-1] != '/' && path[i-1] != '\\')
  112. path[i++] = '\\';
  113. path[i] = 0;
  114. if (!setup_add (dst, path))
  115. return (FALSE);
  116. if (flags & EDS_ALLSUBDIR)
  117. return (setup_subdir (dst, path, i, flags, TRUE));
  118. else if (flags & EDS_ONESUBDIR)
  119. return (setup_subdir (dst, path, i, flags, FALSE));
  120. else
  121. return (TRUE);
  122. }
  123. int setup_list (struct emtex_dir *dst, char *path,
  124. const char *list, unsigned flags)
  125. {
  126. const char *end;
  127. size_t i;
  128. for (;;)
  129. {
  130. while (*list == ' ' || *list == '\t')
  131. ++list;
  132. if (*list == 0)
  133. return (TRUE);
  134. end = list;
  135. while (*end != 0 && *end != ';')
  136. ++end;
  137. i = end - list;
  138. while (i > 0 && (list[i-1] == ' ' || list[i-1] == '\t'))
  139. --i;
  140. if (i != 0 && !setup_dir (dst, path, list, i, NULL, flags))
  141. return (FALSE);
  142. if (*end == 0)
  143. return (TRUE);
  144. list = end + 1;
  145. }
  146. }
  147. int emtex_dir_setup (struct emtex_dir *ed, const char *env, const char *dir,
  148. unsigned flags)
  149. {
  150. const char *val;
  151. char path[260];
  152. ed->alloc = 0;
  153. ed->used = 0;
  154. ed->list = NULL;
  155. if (env != NULL && (val = getenv (env)) != NULL)
  156. return (setup_list (ed, path, val, flags));
  157. else if ((val = getenv ("EMTEXDIR")) != NULL)
  158. return (setup_dir (ed, path, val, strlen (val), dir, flags));
  159. else
  160. return (setup_dir (ed, path, "\\emtex", 6, dir, flags));
  161. }
  162. static void pretty (char *path, unsigned flags)
  163. {
  164. char *p;
  165. if (flags & EDF_FSLASH)
  166. for (p = path; *p != 0; ++p)
  167. if (*p == '\\')
  168. *p = '/';
  169. }
  170. #define ADDCHAR(C) \
  171. if (dst_size < 1) return (EDT_TOOLONG); \
  172. *dst++ = (C); --dst_size
  173. int emtex_dir_trunc (char *dst, size_t dst_size, const char *src,
  174. unsigned flags, int method)
  175. {
  176. int len, truncated, dot;
  177. if (src[0] != 0 && src[1] == ':')
  178. {
  179. ADDCHAR (src[0]);
  180. ADDCHAR (src[1]);
  181. src += 2;
  182. }
  183. truncated = FALSE; dot = FALSE; len = 0;
  184. for (;;)
  185. {
  186. switch (*src)
  187. {
  188. case 0:
  189. ADDCHAR (0);
  190. return (truncated ? EDT_CHANGED : EDT_UNCHANGED);
  191. case ':':
  192. return (EDT_INVALID);
  193. case '/':
  194. case '\\':
  195. ADDCHAR (*src);
  196. len = 0; dot = FALSE;
  197. break;
  198. case '.':
  199. if (dot)
  200. return (EDT_INVALID);
  201. ADDCHAR (*src);
  202. /* ".." is allowed -- don't return EDT_INVALID for the next
  203. dot. */
  204. if (!(len == 0 && src[1] == '.'
  205. && (src[2] == 0 || src[2] == '/' || src[2] == '\\')))
  206. {
  207. len = 0; dot = TRUE;
  208. }
  209. break;
  210. default:
  211. if (dot && len == 3)
  212. truncated = TRUE;
  213. else if (!dot && len == 8)
  214. {
  215. truncated = TRUE;
  216. if (method == 0)
  217. {
  218. dst[-3] = dst[-2];
  219. dst[-2] = dst[-1];
  220. dst[-1] = *src;
  221. }
  222. }
  223. else
  224. {
  225. ADDCHAR (*src);
  226. ++len;
  227. }
  228. break;
  229. }
  230. ++src;
  231. }
  232. }
  233. static int find2 (const char *name, unsigned flags)
  234. {
  235. int ok;
  236. ok = (access (name, 4) == 0);
  237. if (flags & EDF_TRACE)
  238. emtex_dir_find_callback (name, ok);
  239. return (ok);
  240. }
  241. static int find1 (char *path, size_t path_size, const char *dir,
  242. const char *fname, unsigned flags)
  243. {
  244. char buf[260];
  245. int method, rc;
  246. size_t len, tmp;
  247. len = 0;
  248. if (dir != NULL)
  249. {
  250. tmp = strlen (dir);
  251. if (tmp >= sizeof (buf))
  252. return (FALSE);
  253. memcpy (buf, dir, tmp);
  254. len = tmp;
  255. }
  256. tmp = strlen (fname);
  257. if (len + tmp >= sizeof (buf))
  258. return (FALSE);
  259. memcpy (buf + len, fname, tmp + 1);
  260. len += tmp;
  261. #if 0 /* wkim */
  262. /* disabled for Win95's long file name support */
  263. /* -- Wonkoo Kim (wkim+@pitt.edu), May 18, 1997 */
  264. if (_osmode == DOS_MODE)
  265. {
  266. rc = emtex_dir_trunc (path, path_size, buf, flags, EDT_5_PLUS_3);
  267. if ((rc == EDT_UNCHANGED || rc == EDT_CHANGED) && find2 (path, flags))
  268. {
  269. pretty (path, flags);
  270. return (TRUE);
  271. }
  272. rc = emtex_dir_trunc (path, path_size, buf, flags, EDT_8);
  273. if (rc == EDT_CHANGED && find2 (path, flags))
  274. {
  275. pretty (path, flags);
  276. return (TRUE);
  277. }
  278. return (FALSE);
  279. }
  280. else
  281. #endif /* wkim */
  282. {
  283. if (len < path_size && find2 (buf, flags))
  284. {
  285. memcpy (path, buf, len + 1);
  286. pretty (path, flags);
  287. return (TRUE);
  288. }
  289. for (method = 0; method < 2; ++method)
  290. {
  291. rc = emtex_dir_trunc (path, path_size, buf, flags, method);
  292. if (rc == EDT_CHANGED && find2 (path, flags))
  293. {
  294. pretty (path, flags);
  295. return (TRUE);
  296. }
  297. }
  298. return (FALSE);
  299. }
  300. }
  301. int emtex_dir_find (char *path, size_t path_size,
  302. const struct emtex_dir *ed,
  303. const char *fname, unsigned flags)
  304. {
  305. int i, absp;
  306. const char *p;
  307. absp = FALSE;
  308. for (p = fname; *p != 0; ++p)
  309. if (*p == ':' || *p == '/' || *p == '\\')
  310. {
  311. absp = TRUE;
  312. break;
  313. }
  314. if (absp)
  315. return (find1 (path, path_size, NULL, fname, flags));
  316. if ((flags & EDF_CWD) && find1 (path, path_size, NULL, fname, flags))
  317. return (TRUE);
  318. for (i = 0; i < ed->used; ++i)
  319. if (find1 (path, path_size, ed->list[i], fname, flags))
  320. return (TRUE);
  321. return (FALSE);
  322. }
  323. #if defined (TEST)
  324. #include <stdio.h>
  325. int main (int argc, char *argv[])
  326. {
  327. struct emtex_dir ed;
  328. int i;
  329. unsigned flags1, flags2;
  330. char path[260];
  331. if (argc != 6)
  332. {
  333. puts ("Usage: emtexdir <flags> <flags> <env> <dir> <fname>");
  334. return (1);
  335. }
  336. flags1 = (unsigned)strtol (argv[1], NULL, 0);
  337. flags2 = (unsigned)strtol (argv[2], NULL, 0);
  338. if (!emtex_dir_setup (&ed, argv[3], argv[4], flags1))
  339. {
  340. fputs ("emtex_dir_setup failed\n", stderr);
  341. return (2);
  342. }
  343. printf ("Directories:\n");
  344. for (i = 0; i < ed.used; ++i)
  345. printf (" %s\n", ed.list[i]);
  346. if (!emtex_dir_find (path, sizeof (path), &ed, argv[5], flags2))
  347. puts ("File not found");
  348. else
  349. printf ("Path: %s\n", path);
  350. return (0);
  351. }
  352. #endif