stream.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* stream.h Copyright (C) Codemist Ltd, 1995 */
  2. /*
  3. * Header defining the structure of stream objects in CSL, and also
  4. * the format for "library" files used with the fast-load mechanism.
  5. */
  6. /* Signature: 0efbd03e 07-Mar-2000 */
  7. #ifndef header_stream_h
  8. #define header_stream_h 1
  9. extern FILE *non_terminal_input;
  10. typedef int character_reader(void); /* used only with procedural IO */
  11. typedef int character_writer(int); /* ditto */
  12. typedef int character_stream_reader(Lisp_Object);
  13. typedef int character_stream_writer(int, Lisp_Object);
  14. typedef int32 other_stream_op(int32, Lisp_Object);
  15. extern Lisp_Object Lopen(Lisp_Object nil, Lisp_Object name, Lisp_Object dir);
  16. /*
  17. * The values used here are placed where characters might be, or possibly
  18. * OR'd with character codes. They are now such that even if I am using
  19. * 16-bit characters (Unicode of Kanji) all ought to be well.
  20. */
  21. #define ESCAPED_CHAR 0x20000
  22. #define NOT_CHAR 0x40000
  23. extern int char_to_terminal(int c, Lisp_Object f);
  24. extern int char_to_file(int c, Lisp_Object f);
  25. extern int char_to_pipeout(int c, Lisp_Object f);
  26. extern int char_to_synonym(int c, Lisp_Object f);
  27. extern int char_to_broadcast(int c, Lisp_Object f);
  28. extern int char_to_illegal(int c, Lisp_Object f);
  29. extern int char_to_list(int c, Lisp_Object f);
  30. extern int code_to_list(int c, Lisp_Object f);
  31. extern int count_character(int c, Lisp_Object f);
  32. extern int binary_outchar(int c, Lisp_Object f);
  33. extern int char_to_function(int c, Lisp_Object f);
  34. extern int32 write_action_terminal(int32 c, Lisp_Object f);
  35. extern int32 write_action_file(int32 c, Lisp_Object f);
  36. extern int32 write_action_pipe(int32 c, Lisp_Object f);
  37. extern int32 write_action_synonym(int32 c, Lisp_Object f);
  38. extern int32 write_action_broadcast(int32 c, Lisp_Object f);
  39. extern int32 write_action_twoway(int32 c, Lisp_Object f);
  40. extern int32 write_action_illegal(int32 c, Lisp_Object f);
  41. extern int32 write_action_list(int32 c, Lisp_Object f);
  42. extern int char_from_terminal(Lisp_Object f);
  43. extern int char_from_file(Lisp_Object f);
  44. extern int char_from_synonym(Lisp_Object f);
  45. extern int char_from_concatenated(Lisp_Object f);
  46. extern int char_from_echo(Lisp_Object f);
  47. extern int char_from_illegal(Lisp_Object f);
  48. extern int char_from_list(Lisp_Object f);
  49. extern int char_from_vector(Lisp_Object f);
  50. extern int32 read_action_terminal(int32 c, Lisp_Object f);
  51. extern int32 read_action_file(int32 c, Lisp_Object f);
  52. extern int32 read_action_output_file(int32 c, Lisp_Object f);
  53. extern int32 read_action_synonym(int32 c, Lisp_Object f);
  54. extern int32 read_action_concatenated(int32 c, Lisp_Object f);
  55. extern int32 read_action_echo(int32 c, Lisp_Object f);
  56. extern int32 read_action_twoway(int32 c, Lisp_Object f);
  57. extern int32 read_action_illegal(int32 c, Lisp_Object f);
  58. extern int32 read_action_list(int32 c, Lisp_Object f);
  59. extern int32 read_action_vector(int32 c, Lisp_Object f);
  60. extern char memory_print_buffer[32];
  61. /*
  62. * The following typedef shows the expected layout of a Lisp_STREAM object,
  63. * but it is not used directly because I need to insist that each field is
  64. * exactly 4 bytes wide. Thus when I access things that contain pointers I
  65. * will perform horrible casts. This is essential if I am to be able to host
  66. * this system on certain 64-bit systems.
  67. *
  68. * typedef struct Lisp_STREAM
  69. * {
  70. * Header h;
  71. * Lisp_Object type;
  72. * Lisp_Object write_data;
  73. * Lisp_Object read_data;
  74. * FILE *file;
  75. * character_stream_writer *write_fn;
  76. * other_stream_op *write_other_fn;
  77. * int32 line_length;
  78. * int32 char_pos;
  79. * character_stream_reader *read_fn;
  80. * other_stream_op *read_other_fn;
  81. * int32 pushed_char;
  82. * } Lisp_STREAM;
  83. */
  84. #define STREAM_SIZE 48L
  85. #define stream_type(v) elt(v, 0)
  86. #define stream_write_data(v) elt(v, 1)
  87. #define stream_read_data(v) elt(v, 2)
  88. #define stream_file(v) ((FILE *)elt(v, 3))
  89. #define stream_write_fn(v) ((character_stream_writer *)elt(v, 4))
  90. #define stream_write_other(v) ((other_stream_op *)elt(v,5))
  91. #define stream_line_length(v) elt(v, 6)
  92. #define stream_char_pos(v) elt(v, 7)
  93. #define stream_read_fn(v) ((character_stream_reader *)elt(v, 8))
  94. #define stream_read_other(v) ((other_stream_op *)elt(v,9))
  95. #define stream_pushed_char(v) elt(v, 10)
  96. #define set_stream_file(v, x) (elt(v, 3) = (Lisp_Object)(x))
  97. #define set_stream_write_fn(v, x) (elt(v, 4) = (Lisp_Object)(x))
  98. #define set_stream_write_other(v, x) (elt(v, 5) = (Lisp_Object)(x))
  99. #define set_stream_read_fn(v, x) (elt(v, 8) = (Lisp_Object)(x))
  100. #define set_stream_read_other(v, x) (elt(v, 9) = (Lisp_Object)(x))
  101. #define STREAM_HEADER (TAG_ODDS + TYPE_STREAM + (STREAM_SIZE<<10))
  102. #define STREAM_FLAG_PIPE 1
  103. #define is_stream(v) (is_vector(v) && vechdr(v) == STREAM_HEADER)
  104. #ifdef DEBUG
  105. #define putc_stream(c, f) (!is_stream(f) || stream_write_fn(f)==0 ? term_printf("putc %s %d\n", \
  106. __FILE__, __LINE__), ensure_screen(), my_exit(1), 0 : \
  107. stream_write_fn(f)(c, f))
  108. #define getc_stream(f) (!is_stream(f) || stream_read_fn(f)==0 ? term_printf("putc %s %d\n", \
  109. __FILE__, __LINE__), ensure_screen(), my_exit(1), 0 : \
  110. stream_read_fn(f)(f))
  111. #define other_write_action(c, f) (!is_stream(f) || stream_write_other(f)==0 ? term_printf("putc %s %d\n", \
  112. __FILE__, __LINE__), ensure_screen(), my_exit(1), 0 : \
  113. stream_write_other(f)(c, f))
  114. #define other_read_action(c, f) (!is_stream(f) || stream_read_other(f)==0 ? term_printf("putc %s %d\n", \
  115. __FILE__, __LINE__), ensure_screen(), my_exit(1), 0 : \
  116. stream_read_other(f)(c, f))
  117. #else
  118. #define putc_stream(c, f) (stream_write_fn(f)(c, f))
  119. #define getc_stream(f) (stream_read_fn(f)(f))
  120. #define other_write_action(c, f) (stream_write_other(f)(c, f))
  121. #define other_read_action(c, f) (stream_read_other(f)(c, f))
  122. #endif
  123. /*
  124. * For other_write_action if the top four bits of the operand select an
  125. * action to be performed, while the remaining 28 are available to pass
  126. * an operand.
  127. */
  128. #define WRITE_GET_INFO 0x00000000
  129. # define WRITE_GET_LINE_LENGTH 0
  130. # define WRITE_GET_COLUMN 1
  131. # define WRITE_IS_CONSOLE 2
  132. #define WRITE_CLOSE 0x10000000
  133. #define WRITE_FLUSH 0x20000000
  134. #define WRITE_SET_LINELENGTH 0x30000000
  135. #define WRITE_SET_COLUMN 0x40000000
  136. #define WRITE_SET_LINELENGTH_DEFAULT 0x50000000
  137. /*
  138. * For other_read_action() if the operand is in the range -1 to 65535 then
  139. * it is a character to be unread (-1 is used for EOF). Otherwise if the most
  140. * significant bit is a "1" then the request is a seek (with a 31-bit address
  141. * within the stream to go to). The remaining few cases are things that do
  142. * not need additional data passed.
  143. */
  144. #define READ_SEEK 0x80000000
  145. #define READ_TELL 0x00010000
  146. #define READ_CLOSE 0x00010001
  147. #define READ_FLUSH 0x00010002
  148. #define READ_IS_CONSOLE 0x00010003
  149. #define READ_END 0x00010004
  150. extern Lisp_Object make_stream_handle(void);
  151. extern CSLbool use_wimp, sigint_must_longjmp;
  152. extern jmp_buf sigint_buf;
  153. extern character_reader *procedural_input;
  154. extern character_writer *procedural_output;
  155. /*
  156. * This version of the directory structure can cope with up to 2047
  157. * modules in any single library.
  158. */
  159. #if defined DEMO_BUILD || defined DEMO_MODE
  160. #define IMAGE_FORMAT_VERSION 'd'
  161. #else
  162. #define IMAGE_FORMAT_VERSION '4'
  163. #endif
  164. #ifndef DIRECTORY_SIZE
  165. # define DIRECTORY_SIZE 8 /* Initial directory size */
  166. #endif
  167. typedef struct directory_header
  168. {
  169. char C, S, L, version; /* Identification */
  170. unsigned char dirext, /* Extra bits for dirused, dirsize */
  171. dirsize, /* Number of directory entries provided */
  172. dirused, /* Number currently in use */
  173. updated; /* In need of compaction & other flags */
  174. char eof[4]; /* fseek/ftell location of end of file */
  175. } directory_header;
  176. #define get_dirused(d) ((int)((d).dirused + (((d).dirext & 0x0f)<<8)))
  177. #define get_dirsize(d) ((int)((d).dirsize + (((d).dirext & 0xf0)<<4)))
  178. typedef struct directory_entry
  179. {
  180. char data[44];
  181. /*
  182. char newline; * Makes file easier to read as a text file! *
  183. * but also used to indicate encryption *
  184. char name[12]; * blank padded to 12 characters *
  185. * but with special rules for root image etc *
  186. char date[24];
  187. char position[4]; * Machine byte-order insensitive format *
  188. char size[3]; * Ditto *
  189. */
  190. } directory_entry;
  191. /*
  192. * I use these macros rather than just the structure definition shown above
  193. * so that the behaviour of the code is not sensitive to attempts by a C
  194. * compiler to align things for me. Think C 5.0 on the Macintosh (and
  195. * probably many other C compilers) put padder bytes in the original
  196. * structure to give word-alignment.
  197. */
  198. #define D_newline data[0]
  199. #define D_name data[1]
  200. #define D_space data[12]
  201. #define D_date data[13]
  202. #define D_position data[37]
  203. #define D_size data[41]
  204. #define name_size 12
  205. #define date_size 24
  206. #define DIRNAME_LENGTH 64
  207. #define NEWLINE_CHAR 0x0a
  208. /*
  209. * The D_newline location in a directory originally held a newline,
  210. * because doing so resulted in image files baing a little bit easier
  211. * to interpret when looked at with a simple text editor. But then
  212. * it turned out that the C value `\n' was not the same on all computers,
  213. * and so I used a literal hex value 0x0a instead, expecting it to
  214. * be the same as '\n' on "most" systems. Yet later I wanted a backwards-
  215. * compatible way to extend dierctory entries to indicate that some files
  216. * are stored encrypted. The route follows is that unencrypted files
  217. * have NEWLINE_CHAR in the D_newline position, while values that + n
  218. * indicate files encrypted with key number n. Note that if I try to
  219. * read an encrypted sub-file but my key is wrong I will just get garbage
  220. * bytes back, so all code that handles files from the image will need
  221. * to be prepared to respond tolerably gracefully to such a situation.
  222. * I already have a CRC check at the end of every sub-file, but often
  223. * that will be too late, and anyway I may need to review that to ensure that
  224. * it actually checksums the plain-text not the cipher text.
  225. */
  226. typedef struct directory
  227. {
  228. directory_header h;
  229. FILE *f;
  230. char filename[DIRNAME_LENGTH];
  231. directory_entry d[1]; /* Will usually have many more entries */
  232. } directory;
  233. #ifdef COMMON
  234. # define MIDDLE_INITIAL 'C'
  235. #else
  236. # define MIDDLE_INITIAL 'S'
  237. #endif
  238. /*
  239. * Flags for the UPDATED field
  240. */
  241. #define D_WRITE_OK 1
  242. #define D_UPDATED 2
  243. #define D_COMPACT 4
  244. #define D_PENDING 8
  245. extern directory *fasl_files[MAX_FASL_PATHS];
  246. extern directory *open_pds(char *name, CSLbool forinput);
  247. extern CSLbool finished_with(int h);
  248. #endif /* header_stream_h */
  249. /* end of stream.h */