rdelim.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2006,
  2. * 2011 Free Software Foundation, Inc.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public License
  6. * as published by the Free Software Foundation; either version 3 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301 USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22. #include "libguile/_scm.h"
  23. #include <stdio.h>
  24. #ifdef HAVE_STRING_H
  25. #include <string.h>
  26. #endif
  27. #include "libguile/chars.h"
  28. #include "libguile/modules.h"
  29. #include "libguile/ports.h"
  30. #include "libguile/rdelim.h"
  31. #include "libguile/root.h"
  32. #include "libguile/strings.h"
  33. #include "libguile/strports.h"
  34. #include "libguile/validate.h"
  35. SCM_DEFINE (scm_read_delimited_x, "%read-delimited!", 3, 3, 0,
  36. (SCM delims, SCM str, SCM gobble, SCM port, SCM start, SCM end),
  37. "Read characters from @var{port} into @var{str} until one of the\n"
  38. "characters in the @var{delims} string is encountered. If\n"
  39. "@var{gobble} is true, discard the delimiter character;\n"
  40. "otherwise, leave it in the input stream for the next read. If\n"
  41. "@var{port} is not specified, use the value of\n"
  42. "@code{(current-input-port)}. If @var{start} or @var{end} are\n"
  43. "specified, store data only into the substring of @var{str}\n"
  44. "bounded by @var{start} and @var{end} (which default to the\n"
  45. "beginning and end of the string, respectively).\n"
  46. "\n"
  47. " Return a pair consisting of the delimiter that terminated the\n"
  48. "string and the number of characters read. If reading stopped\n"
  49. "at the end of file, the delimiter returned is the\n"
  50. "@var{eof-object}; if the string was filled without encountering\n"
  51. "a delimiter, this value is @code{#f}.")
  52. #define FUNC_NAME s_scm_read_delimited_x
  53. {
  54. size_t j;
  55. size_t cstart;
  56. size_t cend;
  57. scm_t_wchar c;
  58. size_t num_delims;
  59. SCM_VALIDATE_STRING (1, delims);
  60. num_delims = scm_i_string_length (delims);
  61. SCM_VALIDATE_STRING (2, str);
  62. scm_i_get_substring_spec (scm_i_string_length (str),
  63. start, &cstart, end, &cend);
  64. if (SCM_UNBNDP (port))
  65. port = scm_current_input_port ();
  66. else
  67. SCM_VALIDATE_OPINPORT (4, port);
  68. for (j = cstart; j < cend; j++)
  69. {
  70. size_t k;
  71. c = scm_getc_unlocked (port);
  72. for (k = 0; k < num_delims; k++)
  73. {
  74. if (scm_i_string_ref (delims, k) == c)
  75. {
  76. if (scm_is_false (gobble))
  77. scm_ungetc_unlocked (c, port);
  78. return scm_cons (SCM_MAKE_CHAR (c),
  79. scm_from_size_t (j - cstart));
  80. }
  81. }
  82. if (c == EOF)
  83. return scm_cons (SCM_EOF_VAL,
  84. scm_from_size_t (j - cstart));
  85. scm_c_string_set_x (str, j, SCM_MAKE_CHAR (c));
  86. }
  87. return scm_cons (SCM_BOOL_F, scm_from_size_t (j - cstart));
  88. }
  89. #undef FUNC_NAME
  90. /*
  91. * %read-line
  92. * truncates any terminating newline from its input, and returns
  93. * a cons of the string read and its terminating character. Doing
  94. * so makes it easy to implement the hairy `read-line' options
  95. * efficiently in Scheme.
  96. */
  97. SCM_DEFINE (scm_read_line, "%read-line", 0, 1, 0,
  98. (SCM port),
  99. "Read a newline-terminated line from @var{port}, allocating storage as\n"
  100. "necessary. The newline terminator (if any) is removed from the string,\n"
  101. "and a pair consisting of the line and its delimiter is returned. The\n"
  102. "delimiter may be either a newline or the @var{eof-object}; if\n"
  103. "@code{%read-line} is called at the end of file, it returns the pair\n"
  104. "@code{(#<eof> . #<eof>)}.")
  105. #define FUNC_NAME s_scm_read_line
  106. {
  107. /* Threshold under which the only allocation performed is that of the
  108. resulting string and pair. */
  109. #define LINE_BUFFER_SIZE 256
  110. SCM line, strings, result;
  111. scm_t_wchar buf[LINE_BUFFER_SIZE], delim;
  112. size_t index;
  113. if (SCM_UNBNDP (port))
  114. port = scm_current_input_port ();
  115. SCM_VALIDATE_OPINPORT (1,port);
  116. index = 0;
  117. delim = 0;
  118. strings = SCM_BOOL_F;
  119. do
  120. {
  121. if (SCM_UNLIKELY (index >= LINE_BUFFER_SIZE))
  122. {
  123. /* The line is getting longer than BUF so store its current
  124. contents in STRINGS. */
  125. strings = scm_cons (scm_from_utf32_stringn (buf, index),
  126. scm_is_false (strings) ? SCM_EOL : strings);
  127. index = 0;
  128. }
  129. else
  130. {
  131. buf[index] = scm_getc_unlocked (port);
  132. switch (buf[index])
  133. {
  134. case EOF:
  135. case '\n':
  136. delim = buf[index];
  137. break;
  138. default:
  139. index++;
  140. }
  141. }
  142. }
  143. while (delim == 0);
  144. if (SCM_LIKELY (scm_is_false (strings)))
  145. /* The fast path. */
  146. line = scm_from_utf32_stringn (buf, index);
  147. else
  148. {
  149. /* Aggregate the intermediary results. */
  150. strings = scm_cons (scm_from_utf32_stringn (buf, index), strings);
  151. line = scm_string_concatenate (scm_reverse (strings));
  152. }
  153. if (delim == EOF && scm_i_string_length (line) == 0)
  154. result = scm_cons (SCM_EOF_VAL, SCM_EOF_VAL);
  155. else
  156. result = scm_cons (line,
  157. delim == EOF ? SCM_EOF_VAL : SCM_MAKE_CHAR (delim));
  158. return result;
  159. #undef LINE_BUFFER_SIZE
  160. }
  161. #undef FUNC_NAME
  162. SCM_DEFINE (scm_write_line, "write-line", 1, 1, 0,
  163. (SCM obj, SCM port),
  164. "Display @var{obj} and a newline character to @var{port}. If\n"
  165. "@var{port} is not specified, @code{(current-output-port)} is\n"
  166. "used. This function is equivalent to:\n"
  167. "@lisp\n"
  168. "(display obj [port])\n"
  169. "(newline [port])\n"
  170. "@end lisp")
  171. #define FUNC_NAME s_scm_write_line
  172. {
  173. scm_display (obj, port);
  174. return scm_newline (port);
  175. }
  176. #undef FUNC_NAME
  177. SCM
  178. scm_init_rdelim_builtins (void)
  179. {
  180. #include "libguile/rdelim.x"
  181. return SCM_UNSPECIFIED;
  182. }
  183. void
  184. scm_init_rdelim (void)
  185. {
  186. scm_c_define_gsubr ("%init-rdelim-builtins", 0, 0, 0,
  187. scm_init_rdelim_builtins);
  188. }
  189. /*
  190. Local Variables:
  191. c-file-style: "gnu"
  192. End:
  193. */