PageRenderTime 97ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 1ms

/racket/src/racket/src/error.c

http://github.com/plt/racket
C | 4799 lines | 3963 code | 691 blank | 145 comment | 755 complexity | 6e62fdbbfda041ed054b7145fcf94e8b MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, BSD-3-Clause, CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. #include "schpriv.h"
  2. #include "schrktio.h"
  3. #include <ctype.h>
  4. #ifdef DOS_FILE_SYSTEM
  5. # include <windows.h>
  6. #endif
  7. #ifdef NO_ERRNO_GLOBAL
  8. # define errno -1
  9. #else
  10. # include <errno.h>
  11. #endif
  12. #define mzVA_ARG(x, y) HIDE_FROM_XFORM(va_arg(x, y))
  13. #define TMP_CMARK_VALUE scheme_parameterization_key
  14. #ifndef INIT_SYSLOG_LEVEL
  15. # define INIT_SYSLOG_LEVEL 0
  16. #endif
  17. /* globals */
  18. SHARED_OK scheme_console_printf_t scheme_console_printf;
  19. scheme_console_printf_t scheme_get_console_printf() { return scheme_console_printf; }
  20. void scheme_set_console_printf(scheme_console_printf_t p) { scheme_console_printf = p; }
  21. SHARED_OK Scheme_Exit_Proc scheme_exit;
  22. void scheme_set_exit(Scheme_Exit_Proc p) { scheme_exit = p; }
  23. HOOK_SHARED_OK void (*scheme_console_output)(char *str, intptr_t len);
  24. void scheme_set_console_output(scheme_console_output_t p) { scheme_console_output = p; }
  25. SHARED_OK static Scheme_Object *init_syslog_level = scheme_make_integer(INIT_SYSLOG_LEVEL);
  26. SHARED_OK static Scheme_Object *init_stderr_level = scheme_make_integer(SCHEME_LOG_ERROR);
  27. SHARED_OK static Scheme_Object *init_stdout_level = scheme_make_integer(0);
  28. THREAD_LOCAL_DECL(static Scheme_Logger *scheme_main_logger);
  29. THREAD_LOCAL_DECL(static Scheme_Logger *scheme_gc_logger);
  30. THREAD_LOCAL_DECL(static Scheme_Logger *scheme_future_logger);
  31. THREAD_LOCAL_DECL(static Scheme_Logger *scheme_place_logger);
  32. /* readonly globals */
  33. ROSYM static Scheme_Object *none_symbol;
  34. ROSYM static Scheme_Object *fatal_symbol;
  35. ROSYM static Scheme_Object *error_symbol;
  36. ROSYM static Scheme_Object *warning_symbol;
  37. ROSYM static Scheme_Object *info_symbol;
  38. ROSYM static Scheme_Object *debug_symbol;
  39. ROSYM static Scheme_Object *posix_symbol;
  40. ROSYM static Scheme_Object *windows_symbol;
  41. ROSYM static Scheme_Object *gai_symbol;
  42. ROSYM static Scheme_Object *arity_property;
  43. ROSYM static Scheme_Object *def_err_val_proc;
  44. ROSYM static Scheme_Object *def_error_esc_proc;
  45. ROSYM static Scheme_Object *default_display_handler;
  46. ROSYM static Scheme_Object *emergency_display_handler;
  47. ROSYM static Scheme_Object *def_exe_yield_proc;
  48. READ_ONLY Scheme_Object *scheme_def_exit_proc;
  49. READ_ONLY Scheme_Object *scheme_raise_arity_error_proc;
  50. #ifdef MEMORY_COUNTING_ON
  51. intptr_t scheme_misc_count;
  52. #endif
  53. #ifdef MZ_USE_MZRT
  54. static mzrt_mutex *glib_log_queue_lock;
  55. typedef struct glib_log_queue_entry {
  56. const char *log_domain;
  57. int log_level;
  58. const char *message;
  59. struct glib_log_queue_entry *next;
  60. } glib_log_queue_entry;
  61. static glib_log_queue_entry *glib_log_queue;
  62. static void *glib_log_signal_handle;
  63. #endif
  64. /* locals */
  65. static Scheme_Object *error(int argc, Scheme_Object *argv[]);
  66. static Scheme_Object *raise_user_error(int argc, Scheme_Object *argv[]);
  67. static Scheme_Object *raise_type_error(int argc, Scheme_Object *argv[]);
  68. static Scheme_Object *raise_argument_error(int argc, Scheme_Object *argv[]);
  69. static Scheme_Object *raise_result_error(int argc, Scheme_Object *argv[]);
  70. static Scheme_Object *raise_mismatch_error(int argc, Scheme_Object *argv[]);
  71. static Scheme_Object *raise_arguments_error(int argc, Scheme_Object *argv[]);
  72. static Scheme_Object *raise_range_error(int argc, Scheme_Object *argv[]);
  73. static Scheme_Object *raise_arity_error(int argc, Scheme_Object *argv[]);
  74. static Scheme_Object *raise_arity_mask_error(int argc, Scheme_Object *argv[]);
  75. static Scheme_Object *raise_result_arity_error(int argc, Scheme_Object *argv[]);
  76. static Scheme_Object *error_escape_handler(int, Scheme_Object *[]);
  77. static Scheme_Object *error_display_handler(int, Scheme_Object *[]);
  78. static Scheme_Object *error_value_string_handler(int, Scheme_Object *[]);
  79. static Scheme_Object *exit_handler(int, Scheme_Object *[]);
  80. static Scheme_Object *exe_yield_handler(int, Scheme_Object *[]);
  81. static Scheme_Object *error_print_width(int, Scheme_Object *[]);
  82. static Scheme_Object *error_print_context_length(int, Scheme_Object *[]);
  83. static Scheme_Object *error_print_srcloc(int, Scheme_Object *[]);
  84. static MZ_NORETURN void def_error_escape_proc(int, Scheme_Object *[]);
  85. static Scheme_Object *def_error_display_proc(int, Scheme_Object *[]);
  86. static Scheme_Object *emergency_error_display_proc(int, Scheme_Object *[]);
  87. static Scheme_Object *def_error_value_string_proc(int, Scheme_Object *[]);
  88. static Scheme_Object *def_exit_handler_proc(int, Scheme_Object *[]);
  89. static Scheme_Object *default_yield_handler(int, Scheme_Object *[]);
  90. static Scheme_Object *srcloc_to_string(int argc, Scheme_Object **argv);
  91. static Scheme_Object *unquoted_printing_string(int argc, Scheme_Object **argv);
  92. static Scheme_Object *unquoted_printing_string_p(int argc, Scheme_Object **argv);
  93. static Scheme_Object *unquoted_printing_string_value(int argc, Scheme_Object **argv);
  94. static Scheme_Object *log_message(int argc, Scheme_Object *argv[]);
  95. static Scheme_Object *log_level_p(int argc, Scheme_Object *argv[]);
  96. static Scheme_Object *log_max_level(int argc, Scheme_Object *argv[]);
  97. static Scheme_Object *log_all_levels(int argc, Scheme_Object *argv[]);
  98. static Scheme_Object *log_level_evt(int argc, Scheme_Object *argv[]);
  99. static Scheme_Object *make_logger(int argc, Scheme_Object *argv[]);
  100. static Scheme_Object *logger_p(int argc, Scheme_Object *argv[]);
  101. static Scheme_Object *current_logger(int argc, Scheme_Object *argv[]);
  102. static Scheme_Object *logger_name(int argc, Scheme_Object *argv[]);
  103. static Scheme_Object *make_log_reader(int argc, Scheme_Object *argv[]);
  104. static Scheme_Object *log_reader_p(int argc, Scheme_Object *argv[]);
  105. static int log_reader_get(Scheme_Object *ch, Scheme_Schedule_Info *sinfo);
  106. static MZ_NORETURN void do_raise(Scheme_Object *arg, int need_debug, int barrier);
  107. static MZ_NORETURN void nested_exn_handler(void *old_exn, int argc, Scheme_Object *argv[]);
  108. static void update_want_level(Scheme_Logger *logger, Scheme_Object *name);
  109. static Scheme_Object *check_arity_property_value_ok(int argc, Scheme_Object *argv[]);
  110. static char *make_provided_list(Scheme_Object *o, int count, intptr_t *lenout);
  111. static char *init_buf(intptr_t *len, intptr_t *blen);
  112. void scheme_set_logging2(int syslog_level, int stderr_level, int stdout_level)
  113. {
  114. if (syslog_level > -1)
  115. init_syslog_level = scheme_make_integer(syslog_level);
  116. if (stderr_level > -1)
  117. init_stderr_level = scheme_make_integer(stderr_level);
  118. if (stdout_level > -1)
  119. init_stdout_level = scheme_make_integer(stdout_level);
  120. }
  121. void scheme_set_logging(int syslog_level, int stderr_level)
  122. {
  123. scheme_set_logging2(syslog_level, stderr_level, -1);
  124. }
  125. void scheme_set_logging2_spec(Scheme_Object *syslog_level, Scheme_Object *stderr_level, Scheme_Object *stdout_level)
  126. {
  127. /* A spec is (list* <int> <byte-string> .... <int>) */
  128. if (syslog_level) {
  129. REGISTER_SO(init_syslog_level);
  130. init_syslog_level = syslog_level;
  131. }
  132. if (stderr_level) {
  133. REGISTER_SO(init_stderr_level);
  134. init_stderr_level = stderr_level;
  135. }
  136. if (stdout_level) {
  137. REGISTER_SO(init_stdout_level);
  138. init_stdout_level = stdout_level;
  139. }
  140. }
  141. void scheme_set_logging_spec(Scheme_Object *syslog_level, Scheme_Object *stderr_level)
  142. {
  143. scheme_set_logging2_spec(syslog_level, stderr_level, NULL);
  144. }
  145. void scheme_init_logging_once(void)
  146. {
  147. /* Convert specs to use symbols */
  148. int j;
  149. Scheme_Object *l, *s;
  150. for (j = 0; j < 3; j++) {
  151. switch (j) {
  152. case 0: l = init_syslog_level; break;
  153. case 1: l = init_stderr_level; break;
  154. default: l = init_stdout_level; break;
  155. }
  156. if (l) {
  157. while (!SCHEME_INTP(l)) {
  158. l = SCHEME_CDR(l);
  159. s = scheme_intern_exact_symbol(SCHEME_BYTE_STR_VAL(SCHEME_CAR(l)),
  160. SCHEME_BYTE_STRLEN_VAL(SCHEME_CAR(l)));
  161. SCHEME_CAR(l) = s;
  162. l = SCHEME_CDR(l);
  163. }
  164. }
  165. }
  166. }
  167. typedef struct {
  168. int args;
  169. Scheme_Object *type;
  170. Scheme_Object **names;
  171. int count;
  172. Scheme_Object *exptime;
  173. int super_pos;
  174. } exn_rec;
  175. #define _MZEXN_TABLE
  176. #include "schexn.h"
  177. #undef _MZEXN_TABLE
  178. static void default_printf(char *msg, ...)
  179. {
  180. GC_CAN_IGNORE va_list args;
  181. HIDE_FROM_XFORM(va_start(args, msg));
  182. vfprintf(stderr, msg, args);
  183. HIDE_FROM_XFORM(va_end(args));
  184. fflush(stderr);
  185. }
  186. static void default_output(char *s, intptr_t len)
  187. {
  188. fwrite(s, len, 1, stderr);
  189. fflush(stderr);
  190. }
  191. intptr_t scheme_errno() {
  192. #ifdef WINDOWS_FILE_HANDLES
  193. return GetLastError();
  194. #else
  195. return errno;
  196. #endif
  197. }
  198. Scheme_Config *scheme_init_error_escape_proc(Scheme_Config *config)
  199. {
  200. if (!def_error_esc_proc) {
  201. REGISTER_SO(def_error_esc_proc);
  202. def_error_esc_proc =
  203. scheme_make_prim_w_arity((Scheme_Prim *)def_error_escape_proc,
  204. "default-error-escape-handler",
  205. 0, 0);
  206. }
  207. if (config)
  208. return scheme_extend_config(config, MZCONFIG_ERROR_ESCAPE_HANDLER, def_error_esc_proc);
  209. else {
  210. scheme_set_root_param(MZCONFIG_ERROR_ESCAPE_HANDLER, def_error_esc_proc);
  211. return NULL;
  212. }
  213. }
  214. /*
  215. Recognized by scheme_[v]sprintf:
  216. %c = unicode char
  217. %d = int
  218. %gd = long int
  219. %gx = long int
  220. %ld = intptr_t
  221. %Id = intptr_t (for MSVC)
  222. %I64d = intptr_t (for MingGW)
  223. %lx = intptr_t
  224. %Ix = intptr_t (for MSVC)
  225. %I64x = intptr_t (for MingGW)
  226. %o = int, octal
  227. %f = double
  228. %% = percent
  229. %s = string
  230. %5 = mzchar string
  231. %S = Scheme symbol
  232. %t = string with inptr_t size
  233. %u = mzchar string with intptr_t size
  234. %T = Scheme string
  235. %q = truncated-to-256 string
  236. %Q = truncated-to-256 Scheme string
  237. %V = scheme_value
  238. %@ = list of scheme_value to write splice
  239. %D = scheme value to display
  240. %W = scheme value to write
  241. %_ = skip pointer
  242. %- = skip int
  243. %L = line number as intptr_t, -1 means no line
  244. %R = get error number and string from rktio
  245. %e = error number for strerror()
  246. %E = error number for platform-specific error string
  247. %Z = potential platform-specific error number; additional char*
  248. is either NULL or a specific error message
  249. %N = boolean then error number like %E (if boolean is 0)
  250. or error number for scheme_hostname_error()
  251. %m = boolean then error number like %e, which
  252. is used only if the boolean is 1
  253. %M = boolean then error number like %E, which
  254. is used only if the boolean is 1
  255. */
  256. static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list args, char **_s,
  257. Scheme_Object **_errno_val, int *_unsupported)
  258. /* NULL for s means allocate the buffer here (and return in (_s), but this function
  259. doesn't allocate before extracting arguments from the stack. */
  260. {
  261. intptr_t i, j;
  262. char buf[100];
  263. /* Since we might malloc, move all pointers into a local array for
  264. the sake of precise GC. We have to do numbers, too, for
  265. consistency. */
  266. int pp = 0, ip = 0, dp = 0;
  267. void *ptrs[25];
  268. intptr_t ints[25];
  269. double dbls[25];
  270. for (j = 0; msg[j]; j++) {
  271. if (msg[j] == '%') {
  272. int type;
  273. j++;
  274. type = msg[j];
  275. switch (type) {
  276. case 'c':
  277. ints[ip++] = mzVA_ARG(args, int);
  278. break;
  279. case 'd':
  280. case 'o':
  281. case '-':
  282. ints[ip++] = mzVA_ARG(args, int);
  283. break;
  284. case 'g':
  285. ints[ip++] = mzVA_ARG(args, long);
  286. break;
  287. case 'l':
  288. case 'I':
  289. ints[ip++] = mzVA_ARG(args, intptr_t);
  290. break;
  291. case 'f':
  292. dbls[dp++] = mzVA_ARG(args, double);
  293. break;
  294. case 'L':
  295. ints[ip++] = mzVA_ARG(args, intptr_t);
  296. break;
  297. case 'e':
  298. case 'E':
  299. ints[ip++] = mzVA_ARG(args, int);
  300. break;
  301. case 'N':
  302. case 'm':
  303. case 'M':
  304. ints[ip++] = mzVA_ARG(args, int);
  305. ints[ip++] = mzVA_ARG(args, int);
  306. break;
  307. case 'Z':
  308. ints[ip++] = mzVA_ARG(args, int);
  309. ptrs[pp++] = mzVA_ARG(args, char*);
  310. break;
  311. case 'S':
  312. case 'V':
  313. case '@':
  314. case 'D':
  315. case 'W':
  316. case 'T':
  317. case 'Q':
  318. case '_':
  319. ptrs[pp++] = mzVA_ARG(args, Scheme_Object*);
  320. break;
  321. default:
  322. ptrs[pp++] = mzVA_ARG(args, char*);
  323. if ((type == 't') || (type == 'u')) {
  324. ints[ip++] = mzVA_ARG(args, intptr_t);
  325. }
  326. }
  327. }
  328. }
  329. pp = 0;
  330. ip = 0;
  331. dp = 0;
  332. if (!s) {
  333. s = init_buf(NULL, &maxlen);
  334. *_s = s;
  335. }
  336. --maxlen;
  337. i = j = 0;
  338. while ((i < maxlen) && msg[j]) {
  339. if (msg[j] == '%') {
  340. int type;
  341. j++;
  342. type = msg[j++];
  343. if (type == '%')
  344. s[i++] = '%';
  345. else {
  346. const char *t;
  347. intptr_t tlen;
  348. int dots = 0;
  349. switch (type) {
  350. case 'c':
  351. {
  352. int c;
  353. c = ints[ip++];
  354. if (c < 128) {
  355. buf[0] = c;
  356. tlen = 1;
  357. } else {
  358. mzchar mc;
  359. mc = c;
  360. tlen = scheme_utf8_encode_all(&mc, 1, (unsigned char *)buf);
  361. }
  362. t = buf;
  363. }
  364. break;
  365. case 'd':
  366. {
  367. int d;
  368. d = ints[ip++];
  369. sprintf(buf, "%d", d);
  370. t = buf;
  371. tlen = strlen(t);
  372. }
  373. break;
  374. case '-':
  375. {
  376. ip++;
  377. t = "";
  378. tlen = 0;
  379. }
  380. break;
  381. case 'o':
  382. {
  383. int d;
  384. d = ints[ip++];
  385. sprintf(buf, "%o", d);
  386. t = buf;
  387. tlen = strlen(t);
  388. }
  389. break;
  390. case 'I':
  391. case 'l':
  392. case 'g':
  393. {
  394. intptr_t d;
  395. int as_hex;
  396. if ((type == 'I') && (msg[j] == '6') && (msg[j+1] == '4'))
  397. j++;
  398. as_hex = (msg[j] == 'x');
  399. j++;
  400. d = ints[ip++];
  401. if (as_hex)
  402. sprintf(buf, "%" PRIxPTR, d);
  403. else
  404. sprintf(buf, "%" PRIdPTR, d);
  405. t = buf;
  406. tlen = strlen(t);
  407. }
  408. break;
  409. case 'f':
  410. {
  411. double f;
  412. f = dbls[dp++];
  413. sprintf(buf, "%f", f);
  414. t = buf;
  415. tlen = strlen(t);
  416. }
  417. break;
  418. case 'L':
  419. {
  420. intptr_t d;
  421. d = ints[ip++];
  422. if (d >= 0) {
  423. sprintf(buf, "%" PRIdPTR ":", d);
  424. t = buf;
  425. tlen = strlen(t);
  426. } else {
  427. t = ":";
  428. tlen = 1;
  429. }
  430. }
  431. break;
  432. case 'R':
  433. {
  434. intptr_t errid;
  435. intptr_t errkind;
  436. const char *es, *errkind_str;
  437. intptr_t elen;
  438. errkind = rktio_get_last_error_kind(scheme_rktio);
  439. errid = rktio_get_last_error(scheme_rktio);
  440. switch (errkind) {
  441. case RKTIO_ERROR_KIND_WINDOWS:
  442. errkind_str = "errid";
  443. break;
  444. case RKTIO_ERROR_KIND_POSIX:
  445. errkind_str = "errno";
  446. break;
  447. case RKTIO_ERROR_KIND_GAI:
  448. errkind_str = "gai_err";
  449. break;
  450. default:
  451. errkind_str = "rktio_err";
  452. break;
  453. }
  454. es = rktio_get_error_string(scheme_rktio, errkind, errid);
  455. sprintf(buf, "; %s=%" PRIdPTR "", errkind_str, errid);
  456. if (es) elen = strlen(es); else elen = 0;
  457. tlen = strlen(buf);
  458. t = (const char *)scheme_malloc_atomic(tlen+elen+1);
  459. memcpy((char *)t, es, elen);
  460. memcpy((char *)t+elen, buf, tlen+1);
  461. tlen += elen;
  462. if (_errno_val) {
  463. Scheme_Object *err_kind;
  464. switch (errkind) {
  465. case RKTIO_ERROR_KIND_WINDOWS:
  466. err_kind = windows_symbol;
  467. break;
  468. case RKTIO_ERROR_KIND_POSIX:
  469. err_kind = posix_symbol;
  470. break;
  471. case RKTIO_ERROR_KIND_GAI:
  472. err_kind = gai_symbol;
  473. break;
  474. default:
  475. err_kind = NULL;
  476. }
  477. if (err_kind) {
  478. err_kind = scheme_make_pair(scheme_make_integer_value(errid), err_kind);
  479. *_errno_val = err_kind;
  480. }
  481. }
  482. if (_unsupported
  483. && (errid == RKTIO_ERROR_UNSUPPORTED)
  484. && (errkind == RKTIO_ERROR_KIND_RACKET))
  485. *_unsupported = 1;
  486. }
  487. break;
  488. case 'e':
  489. case 'm':
  490. case 'E':
  491. case 'M':
  492. case 'Z':
  493. case 'N':
  494. {
  495. int en, he, none = 0;
  496. char *es;
  497. const char *errkind_str = NULL;
  498. Scheme_Object *err_kind = NULL;
  499. if (type == 'm') {
  500. none = !ints[ip++];
  501. type = 'e';
  502. he = 0;
  503. } else if (type == 'M') {
  504. none = !ints[ip++];
  505. type = 'E';
  506. he = 0;
  507. } else if (type == 'N') {
  508. he = ints[ip++];
  509. type = 'E';
  510. } else
  511. he = 0;
  512. en = ints[ip++];
  513. if (type == 'Z')
  514. es = ptrs[pp++];
  515. else
  516. es = NULL;
  517. if (he) {
  518. es = (char *)scheme_hostname_error(en);
  519. err_kind = gai_symbol;
  520. errkind_str = "gai_err";
  521. }
  522. if ((en || es) && !none) {
  523. #ifdef NO_STRERROR_AVAILABLE
  524. if (!es)
  525. es = "Unknown error";
  526. err_kind = posix_symbol;
  527. #else
  528. # ifdef DOS_FILE_SYSTEM
  529. wchar_t mbuf[256];
  530. int len;
  531. if ((type != 'e') && !es) {
  532. if ((len = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM
  533. | FORMAT_MESSAGE_IGNORE_INSERTS),
  534. NULL,
  535. en, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  536. mbuf, 255, NULL))) {
  537. int i;
  538. i = scheme_utf8_encode((const unsigned int *)mbuf, 0, len, NULL, 0, 1);
  539. es = (char *)scheme_malloc_atomic(i + 1);
  540. (void)scheme_utf8_encode((const unsigned int *)mbuf, 0, len, es, 0, 1);
  541. es[i] = 0;
  542. /* Remove newlines: */
  543. for (i = strlen(es) - 1; i > 0; i--) {
  544. if (isspace(es[i]))
  545. es[i] = 0;
  546. else
  547. break;
  548. }
  549. err_kind = windows_symbol;
  550. errkind_str = "win_err";
  551. }
  552. }
  553. # endif
  554. if (!es) {
  555. es = strerror(en);
  556. err_kind = posix_symbol;
  557. errkind_str = "errno";
  558. }
  559. #endif
  560. tlen = strlen(es) + 24;
  561. t = (const char *)scheme_malloc_atomic(tlen);
  562. MZ_ASSERT(errkind_str);
  563. sprintf((char *)t, "%s; %s=%d", es, errkind_str, en);
  564. tlen = strlen(t);
  565. if (_errno_val) {
  566. err_kind = scheme_make_pair(scheme_make_integer_value(en), err_kind);
  567. *_errno_val = err_kind;
  568. }
  569. } else {
  570. if (none) {
  571. t = "";
  572. tlen = 0;
  573. } else {
  574. t = "errno=?";
  575. tlen = 7;
  576. }
  577. }
  578. }
  579. break;
  580. case 'S':
  581. {
  582. Scheme_Object *sym;
  583. sym = (Scheme_Object *)ptrs[pp++];
  584. t = scheme_symbol_name_and_size(sym, (uintptr_t *)&tlen, 0);
  585. }
  586. break;
  587. case 'V':
  588. {
  589. Scheme_Object *o;
  590. o = (Scheme_Object *)ptrs[pp++];
  591. t = scheme_make_provided_string(o, 1, &tlen);
  592. }
  593. break;
  594. case '@':
  595. {
  596. Scheme_Object *o;
  597. o = (Scheme_Object *)ptrs[pp++];
  598. t = make_provided_list(o, 1, &tlen);
  599. }
  600. break;
  601. case 'D':
  602. {
  603. Scheme_Object *o;
  604. intptr_t dlen;
  605. o = (Scheme_Object *)ptrs[pp++];
  606. t = scheme_display_to_string(o, &dlen);
  607. tlen = dlen;
  608. }
  609. break;
  610. case 'W':
  611. {
  612. Scheme_Object *o;
  613. intptr_t dlen;
  614. o = (Scheme_Object *)ptrs[pp++];
  615. t = scheme_write_to_string(o, &dlen);
  616. tlen = dlen;
  617. }
  618. break;
  619. case '_':
  620. {
  621. pp++;
  622. t = "";
  623. tlen = 0;
  624. }
  625. break;
  626. case 'T':
  627. case 'Q':
  628. {
  629. Scheme_Object *str;
  630. str = (Scheme_Object *)ptrs[pp++];
  631. if (SCHEME_CHAR_STRINGP(str))
  632. str = scheme_char_string_to_byte_string(str);
  633. t = SCHEME_BYTE_STR_VAL(str);
  634. tlen = SCHEME_BYTE_STRLEN_VAL(str);
  635. }
  636. break;
  637. case 'u':
  638. case '5':
  639. {
  640. mzchar *u;
  641. intptr_t ltlen;
  642. u = (mzchar *)ptrs[pp++];
  643. if (type == 'u') {
  644. tlen = ints[ip++];
  645. if (tlen < 0)
  646. tlen = scheme_char_strlen(u);
  647. } else {
  648. tlen = scheme_char_strlen(u);
  649. }
  650. t = scheme_utf8_encode_to_buffer_len(u, tlen, NULL, 0, &ltlen);
  651. tlen = ltlen;
  652. }
  653. break;
  654. default:
  655. {
  656. t = (char *)ptrs[pp++];
  657. if (type == 't') {
  658. tlen = ints[ip++];
  659. if (tlen < 0)
  660. tlen = strlen(t);
  661. } else {
  662. tlen = strlen(t);
  663. }
  664. }
  665. break;
  666. }
  667. if ((type == 'q') || (type == 'Q')) {
  668. if (tlen > 256) {
  669. tlen = 250;
  670. dots = 1;
  671. }
  672. }
  673. while (tlen && i < maxlen) {
  674. s[i++] = *t;
  675. t = t XFORM_OK_PLUS 1;
  676. tlen--;
  677. }
  678. if (dots) {
  679. /* FIXME: avoiding truncating in the middle of a UTF-8 encoding */
  680. if (i < maxlen - 3) {
  681. s[i++] = '.';
  682. s[i++] = '.';
  683. s[i++] = '.';
  684. }
  685. }
  686. }
  687. } else {
  688. s[i++] = msg[j++];
  689. }
  690. }
  691. s[i] = 0;
  692. return i;
  693. }
  694. intptr_t scheme_sprintf(char *s, intptr_t maxlen, const char *msg, ...)
  695. {
  696. intptr_t len;
  697. GC_CAN_IGNORE va_list args;
  698. HIDE_FROM_XFORM(va_start(args, msg));
  699. len = sch_vsprintf(s, maxlen, msg, args, NULL, NULL, NULL);
  700. HIDE_FROM_XFORM(va_end(args));
  701. return len;
  702. }
  703. int scheme_last_error_is_racket(int errid)
  704. {
  705. return ((rktio_get_last_error_kind(scheme_rktio) == RKTIO_ERROR_KIND_RACKET)
  706. && (rktio_get_last_error(scheme_rktio) == errid));
  707. }
  708. #define ESCAPING_NONCM_PRIM(name, func, a1, a2, env) \
  709. p = scheme_make_noncm_prim(func, name, a1, a2); \
  710. SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_ALWAYS_ESCAPES); \
  711. scheme_addto_prim_instance(name, p, env);
  712. void scheme_init_error(Scheme_Startup_Env *env)
  713. {
  714. Scheme_Object *p;
  715. if (!scheme_console_printf)
  716. scheme_console_printf = default_printf;
  717. if (!scheme_console_output)
  718. scheme_console_output = default_output;
  719. REGISTER_SO(scheme_raise_arity_error_proc);
  720. /* errors */
  721. ESCAPING_NONCM_PRIM("error", error, 1, -1, env);
  722. ESCAPING_NONCM_PRIM("raise-user-error", raise_user_error, 1, -1, env);
  723. ESCAPING_NONCM_PRIM("raise-type-error", raise_type_error, 3, -1, env);
  724. ESCAPING_NONCM_PRIM("raise-argument-error", raise_argument_error, 3, -1, env);
  725. ESCAPING_NONCM_PRIM("raise-result-error", raise_result_error, 3, -1, env);
  726. ESCAPING_NONCM_PRIM("raise-arguments-error", raise_arguments_error, 2, -1, env);
  727. ESCAPING_NONCM_PRIM("raise-mismatch-error", raise_mismatch_error, 3, -1, env);
  728. ESCAPING_NONCM_PRIM("raise-range-error", raise_range_error, 7, 8, env);
  729. scheme_raise_arity_error_proc = scheme_make_noncm_prim(raise_arity_error, "raise-arity-error", 2, -1);
  730. scheme_addto_prim_instance("raise-arity-error", scheme_raise_arity_error_proc, env);
  731. ESCAPING_NONCM_PRIM("raise-arity-mask-error", raise_arity_mask_error, 2, -1, env);
  732. ESCAPING_NONCM_PRIM("raise-result-arity-error", raise_result_arity_error, 3, -1, env);
  733. ADD_PARAMETER("error-display-handler", error_display_handler, MZCONFIG_ERROR_DISPLAY_HANDLER, env);
  734. ADD_PARAMETER("error-value->string-handler", error_value_string_handler, MZCONFIG_ERROR_PRINT_VALUE_HANDLER, env);
  735. ADD_PARAMETER("error-escape-handler", error_escape_handler, MZCONFIG_ERROR_ESCAPE_HANDLER, env);
  736. ADD_PARAMETER("exit-handler", exit_handler, MZCONFIG_EXIT_HANDLER, env);
  737. ADD_PARAMETER("executable-yield-handler", exe_yield_handler, MZCONFIG_EXE_YIELD_HANDLER, env);
  738. ADD_PARAMETER("error-print-width", error_print_width, MZCONFIG_ERROR_PRINT_WIDTH, env);
  739. ADD_PARAMETER("error-print-context-length", error_print_context_length, MZCONFIG_ERROR_PRINT_CONTEXT_LENGTH, env);
  740. ADD_PARAMETER("error-print-source-location", error_print_srcloc, MZCONFIG_ERROR_PRINT_SRCLOC, env);
  741. ADD_NONCM_PRIM("exit", scheme_do_exit, 0, 1, env);
  742. /* logging */
  743. ADD_NONCM_PRIM("log-level?", log_level_p, 2, 3, env);
  744. ADD_NONCM_PRIM("log-max-level", log_max_level, 1, 2, env);
  745. ADD_NONCM_PRIM("log-all-levels", log_all_levels, 1, 1, env);
  746. ADD_NONCM_PRIM("log-level-evt", log_level_evt, 1, 1, env);
  747. ADD_NONCM_PRIM("make-logger", make_logger, 0, -1, env);
  748. ADD_NONCM_PRIM("make-log-receiver", make_log_reader, 2, -1, env);
  749. ADD_PRIM_W_ARITY("log-message", log_message, 3, 6, env);
  750. ADD_FOLDING_PRIM("logger?", logger_p, 1, 1, 1, env);
  751. ADD_FOLDING_PRIM("logger-name", logger_name, 1, 1, 1, env);
  752. ADD_FOLDING_PRIM("log-receiver?", log_reader_p, 1, 1, 1, env);
  753. ADD_PARAMETER("current-logger", current_logger, MZCONFIG_LOGGER, env);
  754. ADD_NONCM_PRIM("srcloc->string", srcloc_to_string, 1, 1, env);
  755. ADD_NONCM_PRIM("unquoted-printing-string", unquoted_printing_string, 1, 1, env);
  756. ADD_FOLDING_PRIM("unquoted-printing-string?", unquoted_printing_string_p, 1, 1, 1, env);
  757. ADD_IMMED_PRIM("unquoted-printing-string-value", unquoted_printing_string_value, 1, 1, env);
  758. REGISTER_SO(scheme_def_exit_proc);
  759. REGISTER_SO(default_display_handler);
  760. REGISTER_SO(emergency_display_handler);
  761. scheme_def_exit_proc = scheme_make_prim_w_arity(def_exit_handler_proc, "default-exit-handler", 1, 1);
  762. default_display_handler = scheme_make_prim_w_arity(def_error_display_proc, "default-error-display-handler", 2, 2);
  763. emergency_display_handler = scheme_make_prim_w_arity(emergency_error_display_proc, "emergency-error-display-handler", 2, 2);
  764. REGISTER_SO(def_err_val_proc);
  765. def_err_val_proc = scheme_make_prim_w_arity(def_error_value_string_proc, "default-error-value->string-handler", 2, 2);
  766. REGISTER_SO(none_symbol);
  767. REGISTER_SO(fatal_symbol);
  768. REGISTER_SO(error_symbol);
  769. REGISTER_SO(warning_symbol);
  770. REGISTER_SO(info_symbol);
  771. REGISTER_SO(debug_symbol);
  772. none_symbol = scheme_intern_symbol("none");
  773. fatal_symbol = scheme_intern_symbol("fatal");
  774. error_symbol = scheme_intern_symbol("error");
  775. warning_symbol = scheme_intern_symbol("warning");
  776. info_symbol = scheme_intern_symbol("info");
  777. debug_symbol = scheme_intern_symbol("debug");
  778. REGISTER_SO(posix_symbol);
  779. REGISTER_SO(windows_symbol);
  780. REGISTER_SO(gai_symbol);
  781. posix_symbol = scheme_intern_symbol("posix");
  782. windows_symbol = scheme_intern_symbol("windows");
  783. gai_symbol = scheme_intern_symbol("gai");
  784. REGISTER_SO(arity_property);
  785. {
  786. Scheme_Object *guard;
  787. guard = scheme_make_prim_w_arity(check_arity_property_value_ok, "guard-for-prop:arity-string", 2, 2);
  788. arity_property = scheme_make_struct_type_property_w_guard(scheme_intern_symbol("arity-string"), guard);
  789. }
  790. scheme_addto_prim_instance("prop:arity-string", arity_property, env);
  791. REGISTER_SO(def_exe_yield_proc);
  792. def_exe_yield_proc = scheme_make_prim_w_arity(default_yield_handler,
  793. "default-executable-yield-handler",
  794. 1, 1);
  795. }
  796. void scheme_init_logger_wait()
  797. {
  798. scheme_add_evt(scheme_log_reader_type, (Scheme_Ready_Fun)log_reader_get, NULL, NULL, 1);
  799. }
  800. void scheme_init_logger()
  801. {
  802. REGISTER_SO(scheme_main_logger);
  803. scheme_main_logger = scheme_make_logger(NULL, NULL);
  804. scheme_main_logger->syslog_level = init_syslog_level;
  805. scheme_main_logger->stderr_level = init_stderr_level;
  806. scheme_main_logger->stdout_level = init_stdout_level;
  807. REGISTER_SO(scheme_gc_logger);
  808. scheme_gc_logger = scheme_make_logger(scheme_main_logger, scheme_intern_symbol("GC"));
  809. REGISTER_SO(scheme_future_logger);
  810. scheme_future_logger = scheme_make_logger(scheme_main_logger, scheme_intern_symbol("future"));
  811. REGISTER_SO(scheme_place_logger);
  812. scheme_place_logger = scheme_make_logger(scheme_main_logger, scheme_intern_symbol("place"));
  813. }
  814. Scheme_Logger *scheme_get_main_logger() {
  815. return scheme_main_logger;
  816. }
  817. Scheme_Logger *scheme_get_gc_logger() {
  818. return scheme_gc_logger;
  819. }
  820. Scheme_Logger *scheme_get_future_logger() {
  821. return scheme_future_logger;
  822. }
  823. Scheme_Logger *scheme_get_place_logger() {
  824. return scheme_place_logger;
  825. }
  826. void scheme_init_error_config(void)
  827. {
  828. scheme_set_root_param(MZCONFIG_EXIT_HANDLER, scheme_def_exit_proc);
  829. scheme_set_root_param(MZCONFIG_ERROR_DISPLAY_HANDLER, default_display_handler);
  830. scheme_set_root_param(MZCONFIG_ERROR_PRINT_VALUE_HANDLER, def_err_val_proc);
  831. scheme_set_root_param(MZCONFIG_EXE_YIELD_HANDLER, def_exe_yield_proc);
  832. }
  833. void scheme_init_logger_config() {
  834. scheme_set_root_param(MZCONFIG_LOGGER, (Scheme_Object *)scheme_main_logger);
  835. }
  836. static MZ_NORETURN void
  837. call_error(char *buffer, int len, Scheme_Object *exn)
  838. {
  839. if (scheme_current_thread->constant_folding) {
  840. if (scheme_current_thread->constant_folding != (Optimize_Info *)scheme_false)
  841. scheme_log(scheme_optimize_info_logger(scheme_current_thread->constant_folding),
  842. SCHEME_LOG_WARNING,
  843. 0,
  844. "constant-fold attempt failed%s: %s",
  845. scheme_optimize_info_context(scheme_current_thread->constant_folding),
  846. buffer);
  847. if (SCHEME_CHAPERONE_STRUCTP(exn)
  848. && scheme_is_struct_instance(exn_table[MZEXN_BREAK].type, exn)) {
  849. /* remember to re-raise exception */
  850. scheme_current_thread->reading_delayed = exn;
  851. }
  852. scheme_longjmp(scheme_error_buf, 1);
  853. } else if (scheme_current_thread->reading_delayed) {
  854. scheme_current_thread->reading_delayed = exn;
  855. scheme_longjmp(scheme_error_buf, 1);
  856. } else {
  857. mz_jmp_buf savebuf;
  858. Scheme_Object *p[2], *display_handler, *escape_handler, *v;
  859. Scheme_Config *config, *orig_config;
  860. Scheme_Cont_Frame_Data cframe, cframe2;
  861. /* For last resort: */
  862. memcpy((void *)&savebuf, &scheme_error_buf, sizeof(mz_jmp_buf));
  863. orig_config = scheme_current_config();
  864. display_handler = scheme_get_param(orig_config, MZCONFIG_ERROR_DISPLAY_HANDLER);
  865. escape_handler = scheme_get_param(orig_config, MZCONFIG_ERROR_ESCAPE_HANDLER);
  866. v = scheme_make_byte_string_without_copying("error display handler");
  867. v = scheme_make_closed_prim_w_arity((Scheme_Closed_Prim *)nested_exn_handler,
  868. scheme_make_pair(v, exn),
  869. "nested-exception-handler",
  870. 1, 1);
  871. config = orig_config;
  872. if (SAME_OBJ(display_handler, default_display_handler))
  873. config = scheme_extend_config(config,
  874. MZCONFIG_ERROR_DISPLAY_HANDLER,
  875. emergency_display_handler);
  876. else
  877. config = scheme_extend_config(config,
  878. MZCONFIG_ERROR_DISPLAY_HANDLER,
  879. default_display_handler);
  880. scheme_push_continuation_frame(&cframe);
  881. scheme_install_config(config);
  882. scheme_set_cont_mark(scheme_exn_handler_key, v);
  883. scheme_push_break_enable(&cframe2, 0, 0);
  884. if (SCHEME_CHAPERONE_STRUCTP(exn)
  885. && (scheme_is_struct_instance(exn_table[MZEXN_BREAK_HANG_UP].type, exn))) {
  886. /* skip printout */
  887. } else {
  888. p[0] = scheme_make_immutable_sized_utf8_string(buffer, len);
  889. p[1] = exn;
  890. scheme_apply_multi(display_handler, 2, p);
  891. }
  892. if (SCHEME_CHAPERONE_STRUCTP(exn)
  893. && (scheme_is_struct_instance(exn_table[MZEXN_BREAK_HANG_UP].type, exn)
  894. || scheme_is_struct_instance(exn_table[MZEXN_BREAK_TERMINATE].type, exn))) {
  895. /* Default uncaught exception handler exits on `exn:break:hang-up'
  896. or `exn:break:terminate'. */
  897. p[0] = scheme_make_integer(1);
  898. scheme_do_exit(1, p);
  899. /* Fall through to regular escape if the exit handler doesn't exit/escape. */
  900. }
  901. v = scheme_make_byte_string_without_copying("error escape handler");
  902. v = scheme_make_closed_prim_w_arity((Scheme_Closed_Prim *)nested_exn_handler,
  903. scheme_make_pair(v, exn),
  904. "nested-exception-handler",
  905. 1, 1);
  906. config = scheme_extend_config(config,
  907. MZCONFIG_ERROR_DISPLAY_HANDLER,
  908. default_display_handler);
  909. config = scheme_extend_config(config,
  910. MZCONFIG_ERROR_ESCAPE_HANDLER,
  911. def_error_esc_proc);
  912. scheme_pop_break_enable(&cframe2, 0);
  913. scheme_pop_continuation_frame(&cframe);
  914. scheme_push_continuation_frame(&cframe);
  915. scheme_set_cont_mark(scheme_exn_handler_key, v);
  916. scheme_install_config(config);
  917. scheme_push_break_enable(&cframe2, 0, 0);
  918. /* Typically jumps out of here */
  919. scheme_apply_multi(escape_handler, 0, NULL);
  920. scheme_pop_break_enable(&cframe2, 0);
  921. scheme_pop_continuation_frame(&cframe);
  922. /* Didn't escape, so fall back to the default escaper: */
  923. def_error_escape_proc(0, NULL);
  924. }
  925. }
  926. intptr_t scheme_get_print_width(void)
  927. {
  928. intptr_t print_width;
  929. Scheme_Object *w;
  930. w = scheme_get_param(scheme_current_config(), MZCONFIG_ERROR_PRINT_WIDTH);
  931. if (SCHEME_INTP(w))
  932. print_width = SCHEME_INT_VAL(w);
  933. else if (SCHEME_BIGNUMP(w))
  934. print_width = 0x7FFFFFFF;
  935. else
  936. print_width = 10000;
  937. return print_width;
  938. }
  939. static char *init_buf(intptr_t *len, intptr_t *_size)
  940. {
  941. uintptr_t local_max_symbol_length;
  942. intptr_t print_width;
  943. intptr_t size;
  944. local_max_symbol_length = scheme_get_max_symbol_length();
  945. print_width = scheme_get_print_width();
  946. size = (3 * local_max_symbol_length + 500 + 2 * print_width);
  947. /* out parameters */
  948. if (len)
  949. *len = print_width;
  950. if (_size)
  951. *_size = size;
  952. return (char *)scheme_malloc_atomic(size);
  953. }
  954. void
  955. scheme_signal_error (const char *msg, ...)
  956. {
  957. GC_CAN_IGNORE va_list args;
  958. char *buffer;
  959. intptr_t len;
  960. HIDE_FROM_XFORM(va_start(args, msg));
  961. len = sch_vsprintf(NULL, 0, msg, args, &buffer, NULL, NULL);
  962. HIDE_FROM_XFORM(va_end(args));
  963. buffer[len] = 0;
  964. if (scheme_starting_up) {
  965. buffer[len++] = '\n';
  966. buffer[len] = 0;
  967. scheme_console_output(buffer, len);
  968. exit(0);
  969. }
  970. scheme_raise_exn(MZEXN_FAIL, "%t", buffer, len);
  971. }
  972. void scheme_warning(char *msg, ...)
  973. {
  974. GC_CAN_IGNORE va_list args;
  975. char *buffer;
  976. intptr_t len;
  977. HIDE_FROM_XFORM(va_start(args, msg));
  978. len = sch_vsprintf(NULL, 0, msg, args, &buffer, NULL, NULL);
  979. HIDE_FROM_XFORM(va_end(args));
  980. buffer[len++] = '\n';
  981. buffer[len] = 0;
  982. scheme_write_byte_string(buffer, len,
  983. scheme_get_param(scheme_current_config(), MZCONFIG_ERROR_PORT));
  984. }
  985. void scheme_ensure_console_ready()
  986. {
  987. rktio_create_console();
  988. }
  989. void scheme_log(Scheme_Logger *logger, int level, int flags,
  990. const char *msg, ...)
  991. {
  992. GC_CAN_IGNORE va_list args;
  993. char *buffer;
  994. intptr_t len;
  995. if (logger) {
  996. if (logger->local_timestamp == SCHEME_INT_VAL(logger->root_timestamp[0]))
  997. if (logger->want_level < level)
  998. return;
  999. }
  1000. HIDE_FROM_XFORM(va_start(args, msg));
  1001. len = sch_vsprintf(NULL, 0, msg, args, &buffer, NULL, NULL);
  1002. HIDE_FROM_XFORM(va_end(args));
  1003. buffer[len] = 0;
  1004. scheme_log_message(logger, level, buffer, len, NULL);
  1005. }
  1006. void scheme_log_w_data(Scheme_Logger *logger, int level, int flags,
  1007. Scheme_Object *data,
  1008. const char *msg, ...)
  1009. {
  1010. GC_CAN_IGNORE va_list args;
  1011. char *buffer;
  1012. intptr_t len;
  1013. if (logger) {
  1014. if (logger->local_timestamp == SCHEME_INT_VAL(logger->root_timestamp[0]))
  1015. if (logger->want_level < level)
  1016. return;
  1017. }
  1018. HIDE_FROM_XFORM(va_start(args, msg));
  1019. len = sch_vsprintf(NULL, 0, msg, args, &buffer, NULL, NULL);
  1020. HIDE_FROM_XFORM(va_end(args));
  1021. buffer[len] = 0;
  1022. scheme_log_message(logger, level, buffer, len, data);
  1023. }
  1024. static char *error_write_to_string_w_max(Scheme_Object *v, int len, intptr_t *lenout)
  1025. {
  1026. Scheme_Object *o, *args[2];
  1027. o = scheme_get_param(scheme_current_config(), MZCONFIG_ERROR_PRINT_VALUE_HANDLER);
  1028. if ((SAME_OBJ(o, def_err_val_proc)
  1029. && SAME_OBJ(scheme_get_param(scheme_current_config(), MZCONFIG_PORT_PRINT_HANDLER),
  1030. scheme_default_global_print_handler))) {
  1031. intptr_t l;
  1032. char *s;
  1033. s = scheme_print_to_string_w_max(v, &l, len);
  1034. if (lenout)
  1035. *lenout = l;
  1036. return s;
  1037. } else {
  1038. Scheme_Config *config;
  1039. Scheme_Cont_Frame_Data cframe, cframe2;
  1040. args[0] = v;
  1041. args[1] = scheme_make_integer(len);
  1042. config = scheme_extend_config(scheme_current_config(),
  1043. MZCONFIG_ERROR_PRINT_VALUE_HANDLER,
  1044. def_err_val_proc);
  1045. config = scheme_extend_config(config,
  1046. MZCONFIG_PRINT_UNREADABLE,
  1047. scheme_true);
  1048. scheme_push_continuation_frame(&cframe);
  1049. scheme_install_config(config);
  1050. scheme_push_break_enable(&cframe2, 0, 0);
  1051. o = _scheme_apply(o, 2, args);
  1052. scheme_pop_break_enable(&cframe2, 0);
  1053. scheme_pop_continuation_frame(&cframe);
  1054. if (SCHEME_CHAR_STRINGP(o)) {
  1055. o = scheme_char_string_to_byte_string(o);
  1056. }
  1057. if (SCHEME_BYTE_STRINGP(o)) {
  1058. char *s = SCHEME_BYTE_STR_VAL(o);
  1059. if (SCHEME_BYTE_STRTAG_VAL(o) > len) {
  1060. char *naya;
  1061. naya = scheme_malloc_atomic(len + 1);
  1062. memcpy(naya, s, len);
  1063. s[len] = 0;
  1064. if (lenout)
  1065. *lenout = len;
  1066. } else if (lenout)
  1067. *lenout = SCHEME_BYTE_STRTAG_VAL(o);
  1068. return s;
  1069. } else {
  1070. if (lenout)
  1071. *lenout = 3;
  1072. return "...";
  1073. }
  1074. }
  1075. }
  1076. static Scheme_Object *check_arity_property_value_ok(int argc, Scheme_Object *argv[])
  1077. {
  1078. if (!scheme_check_proc_arity(NULL, 1, 0, 1, argv))
  1079. scheme_arg_mismatch("guard-for-prop:arity-string",
  1080. "property value is not a procedure (arity 1): ",
  1081. argv[0]);
  1082. return argv[0];
  1083. }
  1084. static char *make_arity_expect_string(const char *name, int namelen,
  1085. int minc, int maxc,
  1086. int argc, Scheme_Object **argv,
  1087. intptr_t *_len, int is_method,
  1088. const char *map_name)
  1089. /* minc == -1 => name is really a case-lambda, native closure, or proc-struct.
  1090. minc == -2 => use generic arity-mismatch message */
  1091. {
  1092. intptr_t len, pos, slen;
  1093. int xargc, xminc, xmaxc;
  1094. char *s, *arity_str = NULL;
  1095. const char *prefix_msg1, *prefix_msg2, *suffix_msg;
  1096. int arity_len = 0;
  1097. s = init_buf(&len, &slen);
  1098. if (!name)
  1099. name = "#<procedure>";
  1100. xargc = argc - (is_method ? 1 : 0);
  1101. xminc = minc - (is_method ? 1 : 0);
  1102. xmaxc = maxc - (is_method ? 1 : 0);
  1103. if ((minc == -1) && SCHEME_CHAPERONE_PROC_STRUCTP((Scheme_Object *)name)) {
  1104. Scheme_Object *arity_maker;
  1105. while (1) {
  1106. arity_maker = scheme_struct_type_property_ref(arity_property, (Scheme_Object *)name);
  1107. if (arity_maker) {
  1108. Scheme_Object *v, *a[1];
  1109. a[0] = (Scheme_Object *)name;
  1110. v = scheme_apply(arity_maker, 1, a);
  1111. if (SCHEME_CHAR_STRINGP(v)) {
  1112. v = scheme_char_string_to_byte_string(v);
  1113. arity_str = SCHEME_BYTE_STR_VAL(v);
  1114. arity_len = SCHEME_BYTE_STRLEN_VAL(v);
  1115. if (arity_len > len)
  1116. arity_len = len;
  1117. name = scheme_get_proc_name((Scheme_Object *)name, &namelen, 1);
  1118. if (!name) {
  1119. name = "#<procedure>";
  1120. namelen = strlen(name);
  1121. }
  1122. break;
  1123. } else
  1124. break;
  1125. } else {
  1126. Scheme_Object *v;
  1127. int is_method;
  1128. v = (Scheme_Object *)name;
  1129. if (SCHEME_CHAPERONEP(v))
  1130. v = SCHEME_CHAPERONE_VAL(v);
  1131. if (scheme_is_struct_instance(scheme_reduced_procedure_struct, v))
  1132. v = NULL; /* hide any wider type that a nested structure might report */
  1133. else
  1134. v = scheme_extract_struct_procedure(v, -1, NULL, &is_method);
  1135. if (!v || is_method || !SCHEME_CHAPERONE_PROC_STRUCTP(v))
  1136. break;
  1137. name = (const char *)v;
  1138. }
  1139. SCHEME_USE_FUEL(1);
  1140. }
  1141. if (!arity_str) {
  1142. /* If the arity is something simple, we'll make a good error
  1143. message. Otherwise, we'll just use the "no matching case"
  1144. version. */
  1145. Scheme_Object *arity;
  1146. arity = scheme_arity((Scheme_Object *)name);
  1147. if (SCHEME_INTP(arity)) {
  1148. minc = maxc = SCHEME_INT_VAL(arity);
  1149. xmaxc = xminc = minc - (is_method ? 1 : 0);
  1150. name = scheme_get_proc_name((Scheme_Object *)name, &namelen, 1);
  1151. if (!name) {
  1152. name = "#<procedure>";
  1153. namelen = strlen(name);
  1154. }
  1155. }
  1156. }
  1157. }
  1158. if (map_name) {
  1159. prefix_msg1 = map_name;
  1160. prefix_msg2 = (": argument mismatch;\n"
  1161. " the given procedure's expected number of arguments does not match\n"
  1162. " the given number of lists\n"
  1163. " given procedure: ");
  1164. suffix_msg = "";
  1165. } else {
  1166. prefix_msg1 = "";
  1167. prefix_msg2 = "";
  1168. suffix_msg = (": arity mismatch;\n"
  1169. " the expected number of arguments does not match the given number");
  1170. }
  1171. if (arity_str) {
  1172. pos = scheme_sprintf(s, slen,
  1173. "%s%s%t%s\n"
  1174. " expected: %t\n"
  1175. " given: %d",
  1176. prefix_msg1, prefix_msg2,
  1177. name, (intptr_t)namelen,
  1178. suffix_msg,
  1179. arity_str, (intptr_t)arity_len, xargc);
  1180. } else if (minc < 0) {
  1181. const char *n;
  1182. int nlen;
  1183. if (minc == -2) {
  1184. n = name;
  1185. nlen = (namelen < 0 ? strlen(n) : namelen);
  1186. } else
  1187. n = scheme_get_proc_name((Scheme_Object *)name, &nlen, 1);
  1188. if (!n) {
  1189. n = "#<case-lambda-procedure>";
  1190. nlen = strlen(n);
  1191. }
  1192. pos = scheme_sprintf(s, slen,
  1193. "%s%s%t%s\n"
  1194. " given: %d",
  1195. prefix_msg1, prefix_msg2,
  1196. n, (intptr_t)nlen,
  1197. suffix_msg,
  1198. xargc);
  1199. } else if (!maxc)
  1200. pos = scheme_sprintf(s, slen,
  1201. "%s%s%t%s\n"
  1202. " expected: 0\n"
  1203. " given: %d",
  1204. prefix_msg1, prefix_msg2,
  1205. name, (intptr_t)namelen,
  1206. suffix_msg,
  1207. xargc);
  1208. else if (maxc < 0)
  1209. pos = scheme_sprintf(s, slen,
  1210. "%s%s%t%s\n"
  1211. " expected: at least %d\n"
  1212. " given: %d",
  1213. prefix_msg1, prefix_msg2,
  1214. name, (intptr_t)namelen,
  1215. suffix_msg,
  1216. xminc, xargc);
  1217. else if (minc == maxc)
  1218. pos = scheme_sprintf(s, slen,
  1219. "%s%s%t%s\n"
  1220. " expected: %d\n"
  1221. " given: %d",
  1222. prefix_msg1, prefix_msg2,
  1223. name, (intptr_t)namelen,
  1224. suffix_msg,
  1225. xminc, xargc);
  1226. else
  1227. pos = scheme_sprintf(s, slen,
  1228. "%s%s%t%s\n"
  1229. " expected: %d to %d\n"
  1230. " given: %d",
  1231. prefix_msg1, prefix_msg2,
  1232. name, (intptr_t)namelen,
  1233. suffix_msg,
  1234. xminc, xmaxc, xargc);
  1235. if (xargc && argv) {
  1236. len -= (xargc * 4);
  1237. len /= xargc;
  1238. if ((xargc < 50) && (len >= 3)) {
  1239. int i;
  1240. for (i = (is_method ? 1 : 0); i < argc; i++) {
  1241. intptr_t l;
  1242. char *o;
  1243. if (i == (is_method ? 1 : 0)) {
  1244. strcpy(s + pos, "\n arguments...:\n ");
  1245. pos += 20;
  1246. } else {
  1247. strcpy(s + pos, "\n ");
  1248. pos += 4;
  1249. }
  1250. o = error_write_to_string_w_max(argv[i], len, &l);
  1251. memcpy(s + pos, o, l);
  1252. pos += l;
  1253. }
  1254. s[pos] = 0;
  1255. }
  1256. }
  1257. *_len = pos;
  1258. return s;
  1259. }
  1260. void scheme_wrong_count_m(const char *name, int minc, int maxc,
  1261. int argc, Scheme_Object **argv, int is_method)
  1262. /* minc == -1 => name is really a proc.
  1263. minc == -2 => use generic "no matching clause" message */
  1264. {
  1265. char *s;
  1266. intptr_t len;
  1267. Scheme_Thread *p = scheme_current_thread;
  1268. if (argv == p->tail_buffer) {
  1269. /* See calls in scheme_do_eval: */
  1270. scheme_realloc_tail_buffer(p);
  1271. }
  1272. /* minc = 1 -> name is really a case-lambda or native proc */
  1273. if (minc == -1) {
  1274. /* Extract arity, check for is_method in case-lambda, etc. */
  1275. if (SAME_TYPE(SCHEME_TYPE((Scheme_Object *)name), scheme_closure_type)) {
  1276. Scheme_Lambda *data;
  1277. data = SCHEME_CLOSURE_CODE((Scheme_Object *)name);
  1278. name = scheme_get_proc_name((Scheme_Object *)name, NULL, 1);
  1279. minc = data->num_params;
  1280. if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_REST) {
  1281. minc -= 1;
  1282. maxc = -1;
  1283. } else
  1284. maxc = minc;
  1285. } else if (SAME_TYPE(SCHEME_TYPE((Scheme_Object *)name), scheme_case_closure_type)) {
  1286. Scheme_Case_Lambda *cl = (Scheme_Case_Lambda *)name;
  1287. if (cl->count) {
  1288. Scheme_Lambda *data;
  1289. data = (Scheme_Lambda *)SCHEME_CLOSURE_CODE(cl->array[0]);
  1290. if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_IS_METHOD)
  1291. is_method = 1;
  1292. } else if (cl->name && SCHEME_BOXP(cl->name)) {
  1293. /* See note in schpriv.h about the IS_METHOD hack */
  1294. is_method = 1;
  1295. }
  1296. #ifdef MZ_USE_JIT
  1297. } else if (SAME_TYPE(SCHEME_TYPE((Scheme_Object *)name), scheme_native_closure_type)) {
  1298. Scheme_Object *pa;
  1299. pa = scheme_get_native_arity((Scheme_Object *)name, -1);
  1300. if (SCHEME_BOXP(pa)) {
  1301. pa = SCHEME_BOX_VAL(pa);
  1302. is_method = 1;
  1303. }
  1304. if (SCHEME_INTP(pa)) {
  1305. minc = SCHEME_INT_VAL(pa);
  1306. if (minc < 0) {
  1307. minc = (-minc) - 1;
  1308. maxc = -1;
  1309. } else
  1310. maxc = minc;
  1311. name = scheme_get_proc_name((Scheme_Object *)name, NULL, 1);
  1312. } else if (SCHEME_STRUCTP(pa)) {
  1313. /* This happens when a non-case-lambda is not yet JITted.
  1314. It's an arity-at-least record. */
  1315. pa = ((Scheme_Structure *)pa)->slots[0];
  1316. minc = SCHEME_INT_VAL(pa);
  1317. maxc = -1;
  1318. name = scheme_get_proc_name((Scheme_Object *)name, NULL, 1);
  1319. } else {
  1320. /* complex; use "no matching case" msg */
  1321. }
  1322. #endif
  1323. }
  1324. }
  1325. /* Watch out for impossible is_method claims: */
  1326. if (!argc || !minc)
  1327. is_method = 0;
  1328. if (maxc > SCHEME_MAX_ARGS)
  1329. maxc = -1;
  1330. s = make_arity_expect_string(name, -1, minc, maxc, argc, argv, &len, is_method, NULL);
  1331. scheme_raise_exn(MZEXN_FAIL_CONTRACT_ARITY, "%t", s, len);
  1332. }
  1333. void scheme_wrong_count(const char *name, int minc, int maxc, int argc,
  1334. Scheme_Object **argv)
  1335. {
  1336. /* don't allocate here, in case rands == p->tail_buffer */
  1337. scheme_wrong_count_m(name, minc, maxc, argc, argv, 0);
  1338. }
  1339. void scheme_case_lambda_wrong_count(const char *name,
  1340. int argc, Scheme_Object **argv,
  1341. int is_method,
  1342. int count, ...)
  1343. {
  1344. char *s;
  1345. intptr_t len;
  1346. /* Watch out for impossible is_method claims: */
  1347. if (!argc)
  1348. is_method = 0;
  1349. s = make_arity_expect_string(name, -1, -2, 0, argc, argv, &len, is_method, NULL);
  1350. scheme_raise_exn(MZEXN_FAIL_CONTRACT_ARITY, "%t", s, len);
  1351. }
  1352. char *scheme_make_arity_expect_string(const char *map_name,
  1353. Scheme_Object *proc,
  1354. int argc, Scheme_Object **argv,
  1355. intptr_t *_slen)
  1356. {
  1357. const char *name;
  1358. int namelen = -1;
  1359. int mina, maxa;
  1360. if (SCHEME_CHAPERONEP(proc)) {
  1361. proc = SCHEME_CHAPERONE_VAL(proc);
  1362. }
  1363. if (SCHEME_PRIMP(proc)) {
  1364. name = ((Scheme_Primitive_Proc *)proc)->name;
  1365. mina = ((Scheme_Primitive_Proc *)proc)->mina;
  1366. if (mina < 0) {
  1367. /* set min1 to -2 to indicates cases */
  1368. mina = -2;
  1369. maxa = 0;
  1370. } else {
  1371. maxa = ((Scheme_Primitive_Proc *)proc)->mu.maxa;
  1372. if (maxa > SCHEME_MAX_ARGS)
  1373. maxa = -1;
  1374. }
  1375. } else if (SCHEME_CLSD_PRIMP(proc)) {
  1376. name = ((Scheme_Closed_Primitive_Proc *)proc)->name;
  1377. mina = ((Scheme_Closed_Primitive_Proc *)proc)->mina;
  1378. maxa = ((Scheme_Closed_Primitive_Proc *)proc)->maxa;
  1379. } else if (SAME_TYPE(SCHEME_TYPE(proc), scheme_case_closure_type)) {
  1380. name = scheme_get_proc_name(proc, &namelen, 1);
  1381. mina = -2;
  1382. maxa = 0;
  1383. #ifdef MZ_USE_JIT
  1384. } else if (SAME_TYPE(SCHEME_TYPE((Scheme_Object *)proc), scheme_native_closure_type)) {
  1385. Scheme_Object *pa;
  1386. pa = scheme_get_native_arity((Scheme_Object *)proc, -1);
  1387. if (SCHEME_BOXP(pa)) {
  1388. pa = SCHEME_BOX_VAL(pa);
  1389. }
  1390. if (SCHEME_INTP(pa)) {
  1391. mina = SCHEME_INT_VAL(pa);
  1392. if (mina < 0) {
  1393. mina = (-mina) - 1;
  1394. maxa = -1;
  1395. } else
  1396. maxa = mina;
  1397. } else if (SCHEME_STRUCTP(pa)) {
  1398. /* This happens when a non-case-lambda is not yet JITted.
  1399. It's an arity-at-least record. */
  1400. pa = ((Scheme_Structure *)pa)->slots[0];
  1401. mina = SCHEME_INT_VAL(pa);
  1402. maxa = -1;
  1403. } else {
  1404. /* complex; use "no matching case" msg */
  1405. mina = -2;
  1406. maxa = 0;
  1407. }
  1408. name = scheme_get_proc_name((Scheme_Object *)proc, &namelen, 1);
  1409. #endif
  1410. } else if (SCHEME_CHAPERONE_STRUCTP(proc)) {
  1411. name = (const char *)proc;
  1412. mina = -1;
  1413. maxa = 0;
  1414. } else {
  1415. Scheme_Lambda *data;
  1416. data = (Scheme_Lambda *)SCHEME_CLOSURE_CODE(proc);
  1417. mina = maxa = data->num_params;
  1418. if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_REST) {
  1419. --mina;
  1420. maxa = -1;
  1421. }
  1422. name = scheme_get_proc_name(proc, &namelen, 1);
  1423. }
  1424. return make_arity_expect_string(name, namelen, mina, maxa, argc, argv, _slen, 0, map_name);
  1425. }
  1426. char *scheme_make_args_string(const char *s, int which, int argc, Scheme_Object **argv, intptr_t *_olen)
  1427. {
  1428. char *other;
  1429. intptr_t len;
  1430. GC_CAN_IGNORE char *isres = "arguments";
  1431. other = init_buf(&len, NULL);
  1432. if (argc < 0) {
  1433. isres = "results";
  1434. argc = -argc;
  1435. }
  1436. len /= (argc - (((which >= 0) && (argc > 1)) ? 1 : 0));
  1437. if ((argc < 50) && (len >= 3)) {
  1438. int i, pos;
  1439. sprintf(other, "; %s%s were:", s, isres);
  1440. pos = strlen(other);
  1441. for (i = 0; i < argc; i++) {
  1442. if (i != which) {
  1443. intptr_t l;
  1444. char *o;
  1445. o = error_write_to_string_w_max(argv[i], len, &l);
  1446. memcpy(other + pos, " ", 1);
  1447. memcpy(other + pos + 1, o, l);
  1448. pos += l + 1;
  1449. }
  1450. }
  1451. other[pos] = 0;
  1452. if (_olen)
  1453. *_olen = pos;
  1454. } else {
  1455. sprintf(other, "; given %d arguments total", argc);
  1456. if (_olen)
  1457. *_olen = strlen(other);
  1458. }
  1459. return other;
  1460. }
  1461. char *scheme_make_arg_lines_string(const char *indent, int which, int argc, Scheme_Object **argv, intptr_t *_olen)
  1462. {
  1463. char *other;
  1464. intptr_t len, plen;
  1465. if (!argc || ((argc == 1) && (which == 0))) {
  1466. other = " [none]";
  1467. if (_olen)
  1468. *_olen = strlen(other);
  1469. return other;
  1470. }
  1471. other = init_buf(&len, NULL);
  1472. plen = strlen(indent);
  1473. len -= ((argc - 1) * (plen + 1));
  1474. len /= (argc - (((which >= 0) && (argc > 1)) ? 1 : 0));
  1475. if (len >= 3) {
  1476. int i, pos;
  1477. pos = 0;
  1478. for (i = 0; i < argc; i++) {
  1479. if (i != which) {
  1480. intptr_t l;
  1481. char *o;
  1482. memcpy(other + pos, "\n", 1);
  1483. pos++;
  1484. memcpy(other + pos, indent, plen);
  1485. pos += plen;
  1486. o = error_write_to_string_w_max(argv[i], len, &l);
  1487. memcpy(ot

Large files files are truncated, but you can click here to view the full file