misc.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. *
  3. * Authors: Mike Sperber
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h> /* for getenv(), etc. (POSIX?/ANSI) */
  7. #include <string.h> /* for strncpy(), etc. (POSIX/ANSI) */
  8. #include <errno.h>
  9. #include <windows.h>
  10. /*
  11. Expanding Windows filenames
  12. Windows Sucks. Unix Sucks. C Sucks.
  13. Richard Kelsey Wed Jan 17 21:40:26 EST 1990 (for the Unix version)
  14. Later rewritten by others who wish to remain anonymous.
  15. Expands ~/ in string `name', leaving the result in `buffer'.
  16. `buffer_len' is the length of `buffer'.
  17. */
  18. char *s48_expand_file_name (char *name, char *buffer, int buffer_len)
  19. {
  20. char *drive = NULL, *path = NULL, *dir = NULL;
  21. int dir_len;
  22. int name_len = strlen(name);
  23. if ((name_len >= 2) && (name[0] == '~') && ((name[1] == '\\' || (name[1] == '/'))))
  24. {
  25. drive = getenv("HOMEDRIVE");
  26. /* HOMEPATH is usually \.
  27. * I have no idea if it will have trailing \ for a subdirectory.
  28. */
  29. path = getenv("HOMEPATH");
  30. name += 1;
  31. name_len -= 2;
  32. }
  33. else if ((name_len >= 3) && (name[0] == '%'))
  34. {
  35. char *pos = strchr(name + 2, '%');
  36. if (pos)
  37. {
  38. *pos = '\0';
  39. dir = getenv(name+1);
  40. name = pos + 1;
  41. name_len -= (pos - name) + 1;
  42. }
  43. }
  44. if ((drive && path) || dir)
  45. {
  46. if (drive && path)
  47. dir_len = strlen(drive) + strlen(path);
  48. else
  49. dir_len = strlen(dir);
  50. if ((name_len + dir_len + 1) > buffer_len)
  51. {
  52. fprintf(stderr, "\ns48_expand_file_name: supplied buffer is too small\n");
  53. return(NULL);
  54. };
  55. if (drive && path)
  56. {
  57. int drive_length = strlen(drive);
  58. strcpy(buffer, drive);
  59. strcpy(buffer + drive_length, path);
  60. strcpy(buffer + dir_len, name);
  61. }
  62. else
  63. {
  64. strcpy(buffer, dir);
  65. strcpy(buffer + dir_len, name);
  66. }
  67. }
  68. else
  69. {
  70. if ((name_len + 1) > buffer_len)
  71. {
  72. fprintf(stderr, "\ns48_expand_file_name: supplied buffer is too small\n");
  73. return NULL;
  74. };
  75. strcpy(buffer, name);
  76. }
  77. return(buffer);
  78. }
  79. /* test routine */
  80. /*
  81. main(argc, argv)
  82. int argc;
  83. char *argv[];
  84. {
  85. char buffer[512];
  86. s48_expand_file_name(argv[1], buffer, 512);
  87. printf("%s\n", buffer);
  88. return(0);
  89. }
  90. /* */
  91. /* Driver loop for tail-recursive calls */
  92. long s48_return_value;
  93. long
  94. s48_run_machine(long (*proc) (void))
  95. {
  96. while (proc != 0)
  97. proc = (long (*) (void)) (*proc)();
  98. return s48_return_value;
  99. }
  100. /* Infinities and NaNs */
  101. /* Visual C++ barfs when trying to evaluate 1.0/0.0 statically. */
  102. static double double_zero = 0.0;
  103. double
  104. ps_pos_infinity(void)
  105. {
  106. return 1.0 / double_zero;
  107. }
  108. double
  109. ps_neg_infinity(void)
  110. {
  111. return -1.0 / double_zero;
  112. }
  113. double
  114. ps_not_a_number(void)
  115. {
  116. return (-1.0 / double_zero) + (1.0 / double_zero);
  117. }
  118. unsigned char *
  119. ps_error_string(long the_errno)
  120. {
  121. DWORD id = (DWORD) the_errno;
  122. #define ERROR_BUFFER_SIZE 512
  123. static WCHAR buf[ERROR_BUFFER_SIZE + 1];
  124. static char utf8[(ERROR_BUFFER_SIZE * 4) + 1];
  125. for (;;)
  126. {
  127. if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
  128. NULL, /* lpSource */
  129. id,
  130. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  131. buf, ERROR_BUFFER_SIZE,
  132. NULL)) /* arguments ... */
  133. {
  134. int count
  135. = WideCharToMultiByte(CP_UTF8,
  136. 0, /* dwFlags */
  137. buf,
  138. -1,
  139. utf8,
  140. ERROR_BUFFER_SIZE * 4 + 1,
  141. NULL, /* lpDefaultChar */
  142. NULL /* lpUsedDefaultChar */
  143. );
  144. /* get rid of annoying trailing line end */
  145. if ((count > 3) && (utf8[count-3] == 0x0d) && (utf8[count-2] == 0x0a))
  146. utf8[count-3] = '\0';
  147. return utf8;
  148. }
  149. else
  150. /* risky, but we assume some amount of sanity on the side of
  151. the Windows implementors---haha */
  152. id = GetLastError();
  153. }
  154. #undef ERROR_BUFFER_SIZE
  155. }
  156. /* Getting the length of a file. */
  157. long
  158. s48_get_file_size(unsigned char *name)
  159. {
  160. HANDLE handle = CreateFile(name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  161. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  162. if (handle == INVALID_HANDLE_VALUE)
  163. return -1;
  164. {
  165. DWORD dwSize = GetFileSize(handle, NULL);
  166. CloseHandle(handle);
  167. if (dwSize == 0xFFFFFFFF)
  168. return -1;
  169. else
  170. return (long) dwSize;
  171. }
  172. }