r36front.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. /* r36front.c Copyright (C) 1997-2001 Codemist Ltd */
  2. /*
  3. * This is a Windows front-end for Reduce. It expects a server to
  4. * be running somewhere else and contactable using a socket-based
  5. * link.
  6. */
  7. /* Signature: 4a1fdfb3 20-Mar-2001 */
  8. #include <stdarg.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include "machine.h"
  12. #include "tags.h"
  13. #include "externs.h"
  14. #include "arith.h"
  15. #include "read.h"
  16. #include "stream.h"
  17. #include "entries.h"
  18. #include "version.h"
  19. #include "cslerror.h"
  20. #ifdef TIMEOUT
  21. #include "timeout.h"
  22. #endif
  23. #ifdef OLD_THINK_C
  24. #include <console.h>
  25. #include <memory.h>
  26. #undef nil /* Yuk - this is defined by <types.h> which <memory.h> loads */
  27. #endif
  28. #ifdef __WATCOMC__
  29. #include <float.h>
  30. #endif
  31. #ifdef SOCKETS
  32. #include "sockhdr.h"
  33. #ifndef ms_windows
  34. #include <sys/wait.h>
  35. #endif
  36. SOCKET socket_server;
  37. int sockets_ready;
  38. static int char_to_socket(int c);
  39. #endif
  40. #ifdef WINDOW_SYSTEM
  41. bool use_wimp;
  42. #endif
  43. Lisp_Object C_nil=0xbad00000;
  44. Lisp_Object Lstop(Lisp_Object env, Lisp_Object a)
  45. {
  46. my_exit(0);
  47. return 0;
  48. }
  49. int init_flags = INIT_VERBOSE;
  50. jmp_buf my_exit_buffer;
  51. void my_exit(int n)
  52. {
  53. #ifdef BUFFERED_STDOUT
  54. ensure_screen();
  55. #endif
  56. #ifdef SOCKETS
  57. if (sockets_ready) WSACleanup();
  58. #endif
  59. #ifdef CWIN
  60. if (n == 0) n = 0x80000000;
  61. longjmp(my_exit_buffer, n);
  62. #else
  63. #if defined(WINDOWS_NT) && defined(NAG)
  64. { extern void sys_abort(int);
  65. sys_abort(n);
  66. }
  67. #else
  68. exit(n);
  69. #endif
  70. #endif
  71. }
  72. static int return_code = 0;
  73. bool segvtrap = YES;
  74. bool batch_flag = NO;
  75. bool ignore_restart_fn = NO;
  76. int tty_count;
  77. character_reader *procedural_input;
  78. character_writer *procedural_output;
  79. void cslstart(int argc, char *argv[], character_writer *wout)
  80. {
  81. #ifdef WINDOW_SYSTEM
  82. /*
  83. * On some systems (Archimedes/RISCOS) the same executable
  84. * may run either under a window manager or using a command line.
  85. * I select which to use based on a command line option, which
  86. * I scan for VERY early since until I know what I am doing
  87. * I can not report errors etc etc
  88. */
  89. use_wimp = YES; /* Other than on RISCOS always enable window system */
  90. #ifdef CWIN
  91. cwin_pause_at_end = 1;
  92. #endif
  93. start_up_window_manager(use_wimp);
  94. #endif
  95. #ifdef SOCKETS
  96. sockets_ready = 0;
  97. socket_server = 0;
  98. #endif
  99. procedural_input = NULL;
  100. procedural_output = wout;
  101. base_time = read_clock();
  102. consolidated_time[0] = gc_time = 0.0;
  103. clock_stack = &consolidated_time[0];
  104. push_clock();
  105. if (init_flags & INIT_VERBOSE)
  106. {
  107. #ifndef WINDOW_SYSTEM
  108. /*
  109. * If I do NOT have a window system I will print a newline here so that I
  110. * can be very certain that my banner appears at the start of a line.
  111. * With a window system I should have a brand-new fresh window for output
  112. * and the newline would intrude as an initial blank line.
  113. */
  114. term_printf("\n");
  115. #endif
  116. term_printf("Codemist Standard Lisp %s for %s: %s\n",
  117. VERSION, IMPNAME, __DATE__);
  118. }
  119. #ifdef WINDOW_SYSTEM
  120. ensure_screen();
  121. /* If the user hits the close button here I may be in trouble */
  122. #endif
  123. gc_time += pop_clock();
  124. ensure_screen();
  125. procedural_output = NULL;
  126. #ifdef CWIN
  127. /*
  128. * OK, if I get this far I will suppose that any messages that report utter
  129. * disasters will have reached the user, so I can allow CWIN to terminate
  130. * rather more promptly.
  131. */
  132. cwin_pause_at_end = 0;
  133. #endif
  134. }
  135. #ifdef SOCKETS
  136. #define SOCKET_BUFFER_SIZE 1024
  137. static char socket_in[SOCKET_BUFFER_SIZE], socket_out[SOCKET_BUFFER_SIZE];
  138. static int socket_in_p = 0, socket_in_n = 0, socket_out_p = 0;
  139. static int char_from_socket(void)
  140. {
  141. int c;
  142. clock_t c0;
  143. time_t t0;
  144. if (socket_server == 0) return EOF;
  145. if (socket_in_n == 0)
  146. { for (;;)
  147. { socket_in_n = recv(socket_server, socket_in, SOCKET_BUFFER_SIZE, 0);
  148. c0 = clock();
  149. t0 = time(NULL);
  150. if (socket_in_n <= 0)
  151. #ifndef EWOULDBLOCK
  152. # define EWOULDBLOCK WSAEWOULDBLOCK
  153. #endif
  154. { if (errno == EWOULDBLOCK)
  155. { sleep(1); /* Delay 1 second before re-polling */
  156. continue;
  157. }
  158. closesocket(socket_server);
  159. socket_server = 0;
  160. return EOF;
  161. }
  162. else break;
  163. }
  164. socket_in_p = 0;
  165. }
  166. c = socket_in[socket_in_p++];
  167. socket_in_n--;
  168. return c & 0xff;
  169. }
  170. static int char_to_socket(int c)
  171. {
  172. if (socket_server == 0) return 1;
  173. socket_out[socket_out_p++] = c;
  174. if (c == '\n' || socket_out_p == SOCKET_BUFFER_SIZE)
  175. { if (send(socket_server, socket_out, socket_out_p, 0) < 0)
  176. { closesocket(socket_server);
  177. socket_server = 0;
  178. return 1;
  179. }
  180. socket_out_p = 0;
  181. }
  182. return 0;
  183. }
  184. #endif
  185. void cslaction()
  186. {
  187. char buffer[512];
  188. ensure_screen();
  189. /* procedural_input = char_from_socket;
  190. procedural_output = char_to_socket; */
  191. tty_count = 0;
  192. term_printf("Input:");
  193. ensure_screen();
  194. wimpget(buffer);
  195. term_printf("\nIt was <%s>\n", buffer);
  196. term_printf("Input:");
  197. ensure_screen();
  198. wimpget(buffer);
  199. term_printf("\nIt was <%s>\n", buffer);
  200. term_printf("Input:");
  201. ensure_screen();
  202. wimpget(buffer);
  203. term_printf("\nIt was <%s>\n", buffer);
  204. ensure_screen();
  205. procedural_input = NULL;
  206. procedural_output = NULL;
  207. }
  208. int cslfinish(character_writer *w)
  209. {
  210. procedural_output = w;
  211. /*
  212. * clock_t is an arithmetic type but I do not know what sort - so I
  213. * widen to double to do arithmetic on it.
  214. */
  215. if (init_flags & INIT_VERBOSE)
  216. { long int t = (long int)(100.0 * (consolidated_time[0] +
  217. (double)(read_clock() - base_time)/
  218. (double)CLOCKS_PER_SEC));
  219. long int gct = (long int)(100.0 * gc_time);
  220. term_printf("\n\nEnd of Lisp run after %ld.%.2ld+%ld.%.2ld seconds\n",
  221. t/100, t%100, gct/100, gct%100);
  222. }
  223. if (spool_file != NULL)
  224. {
  225. #ifdef COMMON
  226. fprintf(spool_file, "\nFinished dribbling to %s.\n", spool_file_name);
  227. #else
  228. fprintf(spool_file, "\n+++ Transcript closed at end of run +++\n");
  229. #endif
  230. #ifndef _DEBUG
  231. fclose(spool_file);
  232. spool_file = NULL;
  233. #endif
  234. }
  235. ensure_screen();
  236. procedural_output = NULL;
  237. return return_code;
  238. }
  239. static int submain(int argc, char *argv[])
  240. {
  241. cslstart(argc, argv, NULL);
  242. cslaction();
  243. my_exit(cslfinish(NULL));
  244. return 0;
  245. }
  246. #if !defined(WINDOWS_NT) || defined(CWIN) || !defined(NAG)
  247. #ifdef CWIN
  248. #define ENTRYPOINT cwin_main
  249. #else
  250. #define ENTRYPOINT main
  251. #endif
  252. int ENTRYPOINT(int argc, char *argv[])
  253. {
  254. int res;
  255. #ifdef CWIN
  256. #ifdef NAG
  257. strcpy(about_box_title, "About AXIOM for Windows");
  258. strcpy(about_box_description, "CWIN interface");
  259. strcpy(about_box_rights_1,"Copyright NAG Ltd.");
  260. strcpy(about_box_rights_2,"1991-6");
  261. #else
  262. strcpy(about_box_title, "About CSL");
  263. strcpy(about_box_description, "Codemist Standard Lisp");
  264. #endif
  265. #endif
  266. #ifdef __cplusplus
  267. try { res = submain(argc, argv); }
  268. catch(int r) { res = r; }
  269. #else
  270. res = setjmp(my_exit_buffer);
  271. if (res == 0) res = submain(argc, argv);
  272. if (res == 0x80000000) res = 0;
  273. #endif
  274. return res;
  275. }
  276. #endif /* NAG */
  277. FILE *spool_file = NULL;
  278. char spool_file_name[32];
  279. int32 terminal_column = 0;
  280. int32 terminal_line_length = (int32)0x80000000;
  281. #ifdef CWIN
  282. #define default_terminal_line_length cwin_linelength
  283. #else
  284. #define default_terminal_line_length 80
  285. #endif
  286. #define VPRINTF_CHUNK 256
  287. #ifdef BUFFERED_STDOUT
  288. static int print_buffn = 0;
  289. #define PRINT_BUFSIZE 8000
  290. static char print_buffer[PRINT_BUFSIZE+VPRINTF_CHUNK];
  291. clock_t last_flush = 0;
  292. void ensure_screen()
  293. {
  294. /*
  295. * Some of what is going on here is that I arrange to discount time spent
  296. * actually writing characters to the screen.
  297. */
  298. if (spool_file != NULL) fflush(spool_file); /* Maybe useful? */
  299. if (print_buffn != 0)
  300. { push_clock();
  301. /*
  302. * Time spend writing to the screen is explicitly discounted from measurements
  303. * of time spent in CSL...
  304. */
  305. #ifdef WINDOW_SYSTEM
  306. {
  307. #ifdef CWIN
  308. print_buffer[print_buffn] = 0;
  309. cwin_puts(print_buffer);
  310. #else
  311. int i;
  312. for (i=0; i<print_buffn; i++)
  313. putc_stdout(print_buffer[i]);
  314. #endif
  315. flush_screen();
  316. }
  317. #else
  318. fwrite(print_buffer, 1, print_buffn, stdout);
  319. fflush(stdout); fflush(stderr);
  320. #endif
  321. print_buffn = 0;
  322. pop_clock();
  323. last_flush = base_time;
  324. }
  325. else last_flush = read_clock();
  326. }
  327. #endif
  328. void MS_CDECL term_printf(char *fmt, ...)
  329. {
  330. va_list a;
  331. char print_temp[VPRINTF_CHUNK], *p;
  332. int n;
  333. va_start(a, fmt);
  334. n = vsprintf(print_temp, fmt, a);
  335. p = print_temp;
  336. while (n-- > 0) char_to_terminal(*p++, 0);
  337. va_end(a);
  338. }
  339. int char_to_terminal(int c, Lisp_Object dummy)
  340. {
  341. CSL_IGNORE(dummy);
  342. if (c == '\n' || c == '\f') terminal_column = 0;
  343. else terminal_column++;
  344. if (spool_file != NULL)
  345. { putc(c, spool_file);
  346. }
  347. if (procedural_output != NULL) return (*procedural_output)(c);
  348. #ifdef BUFFERED_STDOUT
  349. print_buffer[print_buffn++] = c;
  350. if (print_buffn > PRINT_BUFSIZE) ensure_screen();
  351. #else
  352. /*
  353. * Note that if I have a windowed system then BUFFERED_STDOUT will always
  354. * be set, so the case here is JUST for when I have direct output to the
  355. * ordinary stdout file, with no Lisp-level buffering.
  356. */
  357. putchar(c);
  358. #endif
  359. return 0; /* indicate success */
  360. }
  361. #ifdef SOCKETS
  362. /*
  363. * If a Winsock function fails it leaves an error code that
  364. * WSAGetLastError() can retrieve. This function converts the numeric
  365. * codes to some printable text. Still cryptic, but maybe better than
  366. * the raw numbers!
  367. */
  368. static char error_name[32];
  369. char *WSAErrName(int i)
  370. {
  371. switch (i)
  372. {
  373. default: sprintf(error_name, "Socket error %d", i);
  374. return error_name;
  375. #ifdef ms_windows
  376. case WSAEINTR: return "WSAEINTR";
  377. case WSAEBADF: return "WSAEBADF";
  378. case WSAEACCES: return "WSAEACCES";
  379. #ifdef WSAEDISCON
  380. case WSAEDISCON: return "WSAEDISCON";
  381. #endif
  382. case WSAEFAULT: return "WSAEFAULT";
  383. case WSAEINVAL: return "WSAEINVAL";
  384. case WSAEMFILE: return "WSAEMFILE";
  385. case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
  386. case WSAEINPROGRESS: return "WSAEINPROGRESS";
  387. case WSAEALREADY: return "WSAEALREADY";
  388. case WSAENOTSOCK: return "WSAENOTSOCK";
  389. case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
  390. case WSAEMSGSIZE: return "WSAEMSGSIZE";
  391. case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
  392. case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
  393. case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
  394. case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
  395. case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
  396. case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
  397. case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
  398. case WSAEADDRINUSE: return "WSAEADDRINUSE";
  399. case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
  400. case WSAENETDOWN: return "WSAENETDOWN";
  401. case WSAENETUNREACH: return "WSAENETUNREACH";
  402. case WSAENETRESET: return "WSAENETRESET";
  403. case WSAECONNABORTED: return "WSAECONNABORTED";
  404. case WSAECONNRESET: return "WSAECONNRESET";
  405. case WSAENOBUFS: return "WSAENOBUFS";
  406. case WSAEISCONN: return "WSAEISCONN";
  407. case WSAENOTCONN: return "WSAENOTCONN";
  408. case WSAESHUTDOWN: return "WSAESHUTDOWN";
  409. case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
  410. case WSAETIMEDOUT: return "WSAETIMEDOUT";
  411. case WSAECONNREFUSED: return "WSAECONNREFUSED";
  412. case WSAELOOP: return "WSAELOOP";
  413. case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
  414. case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
  415. case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
  416. case WSASYSNOTREADY: return "WSASYSNOTREADY";
  417. case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
  418. case WSANOTINITIALISED: return "WSANOTINITIALISED";
  419. case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
  420. case WSATRY_AGAIN: return "WSATRY_AGAIN";
  421. case WSANO_RECOVERY: return "WSANO_RECOVERY";
  422. case WSANO_DATA: return "WSANO_DATA";
  423. #else
  424. /*
  425. * When I run under Unix I display both the Unix and Windows form of the
  426. * error code. I guess that shows you which of those platforms is the one
  427. * I am doing initial development on!
  428. */
  429. case EINTR: return "WSAEINTR/EINTR";
  430. case EBADF: return "WSAEBADF/EBADF";
  431. case EACCES: return "WSAEACCES/EACCES";
  432. case EFAULT: return "WSAEFAULT/EFAULT";
  433. case EINVAL: return "WSAEINVAL/EINVAL";
  434. case EMFILE: return "WSAEMFILE/EMFILE";
  435. case EWOULDBLOCK: return "WSAEWOULDBLOCK/EWOULDBLOCK";
  436. case EINPROGRESS: return "WSAEINPROGRESS/EINPROGRESS";
  437. case EALREADY: return "WSAEALREADY/EALREADY";
  438. case ENOTSOCK: return "WSAENOTSOCK/ENOTSOCK";
  439. case EDESTADDRREQ: return "WSAEDESTADDRREQ/EDESTADDRREQ";
  440. case EMSGSIZE: return "WSAEMSGSIZE/EMSGSIZE";
  441. case EPROTOTYPE: return "WSAEPROTOTYPE/EPROTOTYPE";
  442. case ENOPROTOOPT: return "WSAENOPROTOOPT/ENOPROTOOPT";
  443. case EPROTONOSUPPORT: return "WSAEPROTONOSUPPORT/EPROTONOSUPPORT";
  444. case ESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT/ESOCKTNOSUPPORT";
  445. case EOPNOTSUPP: return "WSAEOPNOTSUPP/EOPNOTSUPP";
  446. case EPFNOSUPPORT: return "WSAEPFNOSUPPORT/EPFNOSUPPORT";
  447. case EAFNOSUPPORT: return "WSAEAFNOSUPPORT/EAFNOSUPPORT";
  448. case EADDRINUSE: return "WSAEADDRINUSE/EADDRINUSE";
  449. case EADDRNOTAVAIL: return "WSAEADDRNOTAVAIL/EADDRNOTAVAIL";
  450. case ENETDOWN: return "WSAENETDOWN/ENETDOWN";
  451. case ENETUNREACH: return "WSAENETUNREACH/ENETUNREACH";
  452. case ENETRESET: return "WSAENETRESET/ENETRESET";
  453. case ECONNABORTED: return "WSAECONNABORTED/ECONNABORTED";
  454. case ECONNRESET: return "WSAECONNRESET/ECONNRESET";
  455. case ENOBUFS: return "WSAENOBUFS/ENOBUFS";
  456. case EISCONN: return "WSAEISCONN/EISCONN";
  457. case ENOTCONN: return "WSAENOTCONN/ENOTCONN";
  458. case ESHUTDOWN: return "WSAESHUTDOWN/ESHUTDOWN";
  459. case ETOOMANYREFS: return "WSAETOOMANYREFS/ETOOMANYREFS";
  460. case ETIMEDOUT: return "WSAETIMEDOUT/ETIMEDOUT";
  461. case ECONNREFUSED: return "WSAECONNREFUSED/ECONNREFUSED";
  462. case ELOOP: return "WSAELOOP/ELOOP";
  463. case ENAMETOOLONG: return "WSAENAMETOOLONG/ENAMETOOLONG";
  464. case EHOSTDOWN: return "WSAEHOSTDOWN/EHOSTDOWN";
  465. case EHOSTUNREACH: return "WSAEHOSTUNREACH/EHOSTUNREACH";
  466. case HOST_NOT_FOUND: return "WSAHOST_NOT_FOUND/HOST_NOT_FOUND";
  467. case TRY_AGAIN: return "WSATRY_AGAIN/TRY_AGAIN";
  468. case NO_RECOVERY: return "WSANO_RECOVERY/NO_RECOVERY";
  469. #ifdef never
  470. /*
  471. * Duplicated EINTR, at least on Linux.
  472. */
  473. case NO_DATA: return "WSANO_DATA/NO_DATA";
  474. #endif
  475. #endif
  476. }
  477. }
  478. int ensure_sockets_ready()
  479. {
  480. if (!sockets_ready)
  481. {
  482. #ifdef ms_windows
  483. /*
  484. * Under Windows the socket stuff is not automatically active, so some
  485. * system calls have to be made at the start of a run. I demand a
  486. * Winsock 1.1, and fail if that is not available.
  487. */
  488. WSADATA wsadata;
  489. int i = WSAStartup(MAKEWORD(1,1), &wsadata);
  490. if (i) return i; /* Failed to start winsock for some reason */;
  491. if (LOBYTE(wsadata.wVersion) != 1 ||
  492. HIBYTE(wsadata.wVersion) != 1)
  493. { WSACleanup();
  494. return 1; /* Version 1.1 of winsock needed */
  495. }
  496. #endif
  497. sockets_ready = 1;
  498. }
  499. return 0;
  500. }
  501. #endif
  502. clock_t base_time;
  503. double *clock_stack, consolidated_time[10], gc_time;
  504. void push_clock()
  505. {
  506. clock_t t0 = read_clock();
  507. double delta = (double)(t0 - base_time)/(double)CLOCKS_PER_SEC;
  508. base_time = t0;
  509. *clock_stack += delta;
  510. *++clock_stack = 0.0;
  511. }
  512. double pop_clock()
  513. {
  514. clock_t t0 = read_clock();
  515. double delta = (double)(t0 - base_time)/(double)CLOCKS_PER_SEC;
  516. base_time = t0;
  517. return delta + *clock_stack--;
  518. }
  519. #include <errno.h>
  520. #include <io.h>
  521. #include <dos.h>
  522. #include <direct.h>
  523. #include <sys\stat.h>
  524. #ifdef _MSC_VER
  525. #define strdup(x) _strdup(x)
  526. #endif
  527. void flush_screen()
  528. {
  529. cwin_ensure_screen();
  530. }
  531. void start_up_window_manager(int use_wimp)
  532. {
  533. use_wimp = use_wimp;
  534. }
  535. int wimpget(char *buf)
  536. {
  537. int c, n=0;
  538. Lisp_Object nil;
  539. ensure_screen();
  540. nil = C_nil;
  541. if (exception_pending()) return 0;
  542. while (n < 255)
  543. { c = cwin_getchar();
  544. nil = C_nil;
  545. if (exception_pending() || c == EOF) return 0;
  546. c = c & 0xff;
  547. buf[n++] = c;
  548. if (c == '\n') break;
  549. };
  550. return n;
  551. }
  552. /*
  553. * Slightly optional jollies re GC statistics...
  554. */
  555. static char time_string[32], space_string[32];
  556. void report_time(int32 t, int32 gct)
  557. {
  558. sprintf(time_string, "%ld.%.2ld+%ld.%.2ld secs ",
  559. t/100L, t%100L, gct/100L, gct%100L);
  560. cwin_report_left(time_string);
  561. }
  562. void report_space(int n, double percent)
  563. {
  564. sprintf(space_string, "[GC %d]:%.2f%%", n, percent);
  565. cwin_report_right(space_string);
  566. }
  567. static char *eu_prices[] =
  568. {
  569. "<HTML>",
  570. "<HEAD>",
  571. " <TITLE>European Union REDUCE Price List from Codemist Ltd</TITLE>",
  572. "</HEAD>",
  573. "<H1>",
  574. " European Union REDUCE Price List from Codemist Ltd",
  575. "</H1>",
  576. "<P>",
  577. "This price list is valid for customers within the European Union. Others",
  578. "should use the Worldwide price list. Note",
  579. "that all payment should be in Sterling by cheque drawn on a London Bank or",
  580. "by credit card (VISA or MasterCard). The prices quoted here are valid until",
  581. "<U>30 August 1997</U>.",
  582. "<UL>",
  583. " <LI>",
  584. " The <B>Professional Reduce</B> price for all systems is <B>340 pounds sterling",
  585. " + VAT</B> at the rate in force at the time of delivery. At present this is",
  586. " 17.5% making a complete price of <B>399.50 pounds</B>. The price includes",
  587. " all sources, instruction sheets, a printed manual and postage and packing.",
  588. " <LI>",
  589. " The <B>Personal Reduce</B>, only available for PC clones, Acorn Archimedes,",
  590. " Atari ST and Macintosh, is <B>72.29 pounds sterling + VAT</B> which is <B>84.95",
  591. " pounds</B>. This system is pre-built, and delivered with documentation in",
  592. " machine readable form, instruction sheets, and the price includes postage",
  593. " and packing. It does <I>not</I> include a printed manual.",
  594. " <LI>",
  595. " The <B>Codemist REDUCE Manual</B>, a 450 page single volume manual, incorporating",
  596. " the Reduce manual, and the manuals for modules and libraries costs <B>15",
  597. " pounds</B> if ordered at the same time as a system, or <B>20 pounds</B> if",
  598. " ordered separately. There is no VAT on books in the UK. Please note that",
  599. " one copy of the manual is included in the Professional REDUCE package.",
  600. " <LI>",
  601. " <B>Reduce Site licences</B> are available for 2 or more systems for use at",
  602. " the same site, defined as a single postal address. The prices in the European",
  603. " Union are",
  604. " <UL>",
  605. " <LI>",
  606. " <B>510 pounds + VAT</B> for 2 systems",
  607. " <LI>",
  608. " <B>612 pounds + VAT</B> for 3 systems",
  609. " <LI>",
  610. " <B>640 pounds + VAT</B> for 4 systems",
  611. " <LI>",
  612. " <B>1020 pounds + VAT</B> for 5-8 systems",
  613. " <LI>",
  614. " <B>1340 pounds + VAT</B> for 9-15 systems",
  615. " <LI>",
  616. " <B>1700 pounds + VAT</B> for unlimited systems",
  617. " </UL>",
  618. " <LI>",
  619. " Note that the current applicable VAT rate is 17.5%.",
  620. "</UL>",
  621. "<P>",
  622. "Customers who are VAT registered in an EU country other than the United Kingdom",
  623. "may be able to account for VAT it their own country instead. In this case",
  624. "the VAT registration number <I>must</I> be quoted at the time of order. ",
  625. " <HR>",
  626. "<P>",
  627. "jpff@maths.bath.ac.uk"
  628. };
  629. static char *world_prices[] =
  630. {
  631. "Worldwide REDUCE Price List from Codemist Ltd",
  632. "",
  633. "This price list is valid in all countries except those of the European Union,",
  634. "for which the EU price list applies. Note that",
  635. "all payment should be in Sterling by cheque drawn on a London Bank or by",
  636. "credit card (VISA or MasterCard). The prices quoted here are valid until",
  637. "30 August 1997.",
  638. "<UL>",
  639. " <LI>",
  640. " The <B>Professional Reduce</B> price for all systems is <B>350 pounds",
  641. " sterling</B>. The price includes all sources of both REDUCE and CSL, instruction",
  642. " sheets, a printed manual and postage and packing.",
  643. " <LI>",
  644. " The <B>Personal Reduce</B>, only available for PC clones, Acorn Archimedes,",
  645. " Atari ST and Macintosh, is <B>80 pounds sterling</B>. This system is pre-built,",
  646. " and delivered with documentation in machine readable form, instruction sheets,",
  647. " and the price includes postage and packing. It does <I>not</I> include a",
  648. " printed manual.",
  649. " <LI>",
  650. " The <B>Codemist REDUCE Manual</B>, a 450 page single volume manual, incorporating",
  651. " the Reduce manual, and the manuals for modules and libraries costs <B>15",
  652. " pounds</B> if ordered at the same time as a system, or <B>20 pounds</B> if",
  653. " ordered separately. Please note that one copy of the manual is included in",
  654. " the Professional REDUCE package.",
  655. " <LI>",
  656. " <B>Reduce Site licences</B> are available for 2 or more systems for use at",
  657. " the same site, defined as a single postal address. The prices outside the",
  658. " European Union are",
  659. " <UL>",
  660. " <LI>",
  661. " <B>520 pounds</B> for 2 systems",
  662. " <LI>",
  663. " <B>622 pounds</B> for 3 systems",
  664. " <LI>",
  665. " <B>650 pounds</B> for 4 systems",
  666. " <LI>",
  667. " <B>1030 pounds</B> for 5-8 systems",
  668. " <LI>",
  669. " <B>1350 pounds</B> for 9-15 systems",
  670. " <LI>",
  671. " <B>1710 pounds</B> for unlimited systems",
  672. " </UL>",
  673. "",
  674. " jpff@maths.bath.ac.uk"
  675. };
  676. static char *order_form[] =
  677. {
  678. "REDUCE Order Form",
  679. "",
  680. "",
  681. "Send _____ REDUCE 3.6 system(s) for",
  682. " Archimedes, Macintosh(68K), Macintosh (Power), PC (DOS),",
  683. " PC(Windows), SUN, SGI, IBM/AIX, Generic",
  684. " (please delete as required)",
  685. "",
  686. " Professional/Personal/Personal+Manual(*) (please delete as required)",
  687. "",
  688. " [For SUN, SGI, AIX or Generic] Preferred medium?",
  689. " DAT/DDS, QIC Tape, FTP, 3.5\" floppy, other........",
  690. "to",
  691. "",
  692. " Name _______________________________________________________ ",
  693. " ",
  694. " Organization _______________________________________________",
  695. "",
  696. " Street _____________________________________________________",
  697. "",
  698. " City _______________________________________________________",
  699. "",
  700. " Country ____________________________________________________",
  701. "",
  702. " Phone ____________________ Fax ____________________",
  703. "",
  704. " email ____________________",
  705. "",
  706. " Payment: Cheque included (in Pounds",
  707. " Sterling drawn on London Bank) ____",
  708. "",
  709. " VISA or MasterCard Credit Card(**) ____",
  710. "",
  711. " Card number __________________",
  712. " Expiry Date __________________",
  713. "",
  714. " Invoice required at above Organisation ____",
  715. "",
  716. "(*) The Personal REDUCE is only available for Archimedes, Macintosh or",
  717. " any of the PC-clones.",
  718. "(**) Please note that if payment is made by credit card, the address",
  719. " for delivery must be the same as the registered address of the card",
  720. " holder. This is required as part of the credit card anti-fraud",
  721. " policy.",
  722. "",
  723. "I acknowledge the copyrights held in the software by Codemist Ltd",
  724. "(CSL) and Dr. A.C. Hearn (The RAND Corporation) and that further",
  725. "distribution is not allowed. The royalty fee covers the installation",
  726. "and use of REDUCE on one computer at one location. The software is",
  727. "delivered on an as-is basis without any warranty.",
  728. "",
  729. "",
  730. "Date _______________________ Signature __________________________",
  731. "",
  732. "",
  733. "Send this order to: ",
  734. " Codemist Ltd",
  735. " \"Alta\", Horsecombe Vale",
  736. " Combe Down",
  737. " BATH",
  738. " BA2 5QR",
  739. " United Kingdom",
  740. "",
  741. " FAX/Tel: +44-1225-837430",
  742. "",
  743. "Contact Codemist at the address above or by e-mail to jpff@maths.bath.ac.uk",
  744. "for information on site licences.",
  745. "",
  746. " jpff@maths.bath.ac.uk"
  747. };
  748. /* End of r36front.c */