sysmac.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /* sysmac.c Copyright (C) 1989-2002 Codemist Ltd */
  2. /*
  3. * Macintosh system-specific stuff
  4. */
  5. /*
  6. * This code may be used and modified, and redistributed in binary
  7. * or source form, subject to the "CCL Public License", which should
  8. * accompany it. This license is a variant on the BSD license, and thus
  9. * permits use of code derived from this in either open and commercial
  10. * projects: but it does require that updates to this code be made
  11. * available back to the originators of the package.
  12. * Before merging other code in with this or linking this code
  13. * with other packages or libraries please check that the license terms
  14. * of the other material are compatible with those of this.
  15. */
  16. /* Signature: 4bed9bc9 08-Apr-2002 */
  17. #include "machine.h"
  18. #include <stdarg.h>
  19. #include <stddef.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include "tags.h"
  23. #include "externs.h"
  24. #include <sysequ.h>
  25. #include <unix.h>
  26. #include <files.h>
  27. #include <unix.h>
  28. #include <retrace.h>
  29. #include <timer.h>
  30. #undef nil /* #define'd by Think C headers but not wanted (by me) */
  31. static void get_home_directory(char *b, int length);
  32. static void get_users_home_directory(char *b, int length);
  33. #include "filename.c"
  34. /*
  35. * This is a dummy definition of get_truename, here so that everything
  36. * will link. Both the calling convention used here and the exact
  37. * meaning and implementation may be under gentle review!
  38. */
  39. char *get_truename(char *filename, char *old, size_t n)
  40. {
  41. char *w;
  42. process_file_name(filename, old, n);
  43. if (*filename == 0)
  44. { aerror("truename");
  45. return NULL;
  46. }
  47. w = (char *)(*malloc_hool)(1+strlen(filename));
  48. if (w == NULL) return w;
  49. strcpy(w, filename);
  50. return w;
  51. }
  52. char *my_getenv(char *s)
  53. {
  54. return getenv(s);
  55. }
  56. int my_system(char *s)
  57. {
  58. return 0; /* Not available - sorry! */
  59. }
  60. static void get_home_directory(char *b, int length)
  61. {
  62. char *w = my_getenv("home");
  63. if (w != NULL) strcpy(b, w);
  64. else
  65. strcpy(b, ":"); /* Not satisfactory */
  66. }
  67. static void get_users_home_directory(char *b, int length)
  68. {
  69. char *w, h[LONGEST_LEGAL_FILENAME];
  70. sprintf(h, "home$%s", b);
  71. w = my_getenv(h);
  72. if (w != NULL) strcpy(b, w);
  73. else
  74. strcpy(b, ":"); /* Not satisfactory */
  75. }
  76. int batchp()
  77. {
  78. return !isatty(fileno(stdin));
  79. }
  80. /*
  81. * The next procedure is responsible for establishing information about
  82. * where the main checkpoint image should be recovered from, and where
  83. * and fasl files should come from.
  84. */
  85. char *find_image_directory(int argc, char *argv[])
  86. {
  87. char image[LONGEST_LEGAL_FILENAME];
  88. char pgmname[LONGEST_LEGAL_FILENAME];
  89. char *w;
  90. /*
  91. * For the Macintosh I use the data fork of the application image as
  92. * a place to store useful stuff.
  93. */
  94. WDPBRec pb1;
  95. CInfoPBRec pb2;
  96. int i, j, r, p = LONGEST_LEGAL_FILENAME;
  97. long id;
  98. pgmname[--p] = 0;
  99. sprintf(image, "%#s", CurApName); /* name of current application */
  100. strcpy(image, program_name);
  101. i = strlen(image);
  102. p -= i;
  103. memcpy(&pgmname[p], image, i); /* copy to the end of a buffer */
  104. pb1.ioNamePtr = (unsigned char *)image;
  105. PBHGetVolSync(&pb1); /* find current working dir & volume */
  106. id = pb1.ioWDDirID; /* working directory identifier */
  107. while (id != 0)
  108. { pb2.dirInfo.ioFDirIndex = -1; /* use directory ID, not file name/index */
  109. pb2.dirInfo.ioVRefNum = pb1.ioVRefNum; /* look in this volume */
  110. pb2.dirInfo.ioDrDirID = id; /* get info about this directory */
  111. pb2.dirInfo.ioNamePtr = (unsigned char *)image;
  112. r = PBGetCatInfoSync(&pb2); /* Read catalogue - find name & parent */
  113. if (r != 0) break; /* failed - must be at top of tree */
  114. id = pb2.dirInfo.ioDrParID; /* go on up to parent directory */
  115. i = image[0] & 0xff; /* length of name of this directory */
  116. pgmname[--p] = ':';
  117. p -= i;
  118. if (p < 10)
  119. { fprintf(stderr, "\nPlease re-install this package nearer the top of\n");
  120. fprintf(stderr, "your directory hierarchy. It will not work this far down\n");
  121. abort();
  122. }
  123. memcpy(&pgmname[p], &image[1], i); /* stick names together with ':'s */
  124. }
  125. strcpy(image, &pgmname[p]); /* Put complete name in convenient place */
  126. /*
  127. * I copy from local vectors into malloc'd space to hand my
  128. * answer back.
  129. */
  130. w = (char *)(*malloc_hook)(1+strlen(image));
  131. /*
  132. * The error exit here seem unsatisfactory...
  133. */
  134. if (w == NULL)
  135. { fprintf(stderr, "\n+++ Panic - run out of space\n");
  136. exit(EXIT_FAILURE);
  137. }
  138. strcpy(w, image);
  139. return w;
  140. }
  141. int truncate_file(FILE *f, long int where)
  142. {
  143. if (fflush(f) != 0) return 1;
  144. return SetEOF(fileno(f), where); /* Returns zero if successs */
  145. }
  146. #ifdef TICK_STREAM
  147. void accept_tick(void)
  148. {
  149. /*
  150. * This is where I can put things that need to be done regularly.
  151. * This will need to involve prodding the window manager etc etc.
  152. * At present I do NOTHING...
  153. */
  154. return;
  155. }
  156. #ifdef USE_VBL
  157. static VBLTask VBL_control_block;
  158. static pascal void deal_with_tick(void)
  159. {
  160. /*
  161. * This way of recovering register a5 was OK before the multi-finder,
  162. * but is UNSATISFACTORY now. It is proper to use the time manager
  163. * instead of VBL, but only recent versions of the time manager are any good
  164. * so it is a bit of a mess.
  165. */
  166. asm { move.l a5, -(sp)
  167. movea.l CurrentA5, a5 }
  168. VBL_control_block.vblCount = 5;
  169. if (tick_pending == 0)
  170. {
  171. if (already_in_gc) tick_on_gc_exit = YES;
  172. else
  173. { Lisp_Object nil = C_nil;
  174. CSLbool xxx = NO;
  175. if (exception_pending()) flip_exception(), xxx = YES;
  176. tick_pending = YES;
  177. saveheaplimit = heaplimit;
  178. heaplimit = fringe;
  179. savevheaplimit = vheaplimit;
  180. vheaplimit = vfringe;
  181. savecodelimit = codelimit;
  182. codelimit = codefringe;
  183. savestacklimit = stacklimit;
  184. stacklimit = stackbase;
  185. if (xxx) flip_exception();
  186. }
  187. }
  188. asm { movea.l (sp)+, a5 }
  189. return;
  190. }
  191. void remove_ticker(void)
  192. {
  193. VRemove((QElemPtr)&VBL_control_block);
  194. }
  195. void add_ticker(void)
  196. {
  197. VBL_control_block.qType = vType;
  198. VBL_control_block.vblAddr = deal_with_tick;
  199. VBL_control_block.vblCount = 1;
  200. VBL_control_block.vblPhase = 0;
  201. VInstall((QElemPtr)&VBL_control_block);
  202. }
  203. #else /* USE_VBL */
  204. typedef struct xTMTask
  205. {
  206. struct TMTask a;
  207. long int a5save;
  208. } xTMTask;
  209. static pascal void do_tick(void)
  210. {
  211. QElemPtr w;
  212. long int savea5;
  213. asm { move.l a5, savea5
  214. move.l offsetof(xTMTask, a5save)(a1), a5
  215. move.l a1, w }
  216. if (tick_pending == 0)
  217. {
  218. if (already_in_gc) tick_on_gc_exit = YES;
  219. else
  220. { Lisp_Object nil = C_nil;
  221. CSLbool xxx = NO;
  222. if (exception_pending()) flip_exception(), xxx = YES;
  223. tick_pending = YES;
  224. saveheaplimit = heaplimit;
  225. heaplimit = fringe;
  226. savevheaplimit = vheaplimit;
  227. vheaplimit = vfringe;
  228. savecodelimit = codelimit;
  229. codelimit = codefringe;
  230. savestacklimit = stacklimit;
  231. stacklimit = stackbase;
  232. if (xxx) flip_exception();
  233. }
  234. }
  235. PrimeTime(w, 1000);
  236. asm { move.l savea5, a5 }
  237. return;
  238. }
  239. static xTMTask ticker;
  240. void remove_ticker(void)
  241. {
  242. RmvTime((QElemPtr)&ticker);
  243. }
  244. void add_ticker()
  245. {
  246. ticker.a.tmAddr = do_tick;
  247. ticker.a.tmCount = 0;
  248. ticker.a.tmWakeUp = 0;
  249. ticker.a.tmReserved = 0;
  250. asm { move.l a5,ticker.a5save }
  251. InsTime((QElemPtr) &ticker);
  252. PrimeTime((QElemPtr) &ticker, 1000);
  253. }
  254. #endif /* USE_VBL */
  255. #endif /* TICK_STREAM */
  256. /* end of sysmac.c */