+ if (CODING_SYSTEM_USE_ENTITY_REFERENCE (str->codesys)
+ && (c == '&') )
+ {
+ str->er_buf[0] = '&';
+ str->er_counter++;
+ }
+ else
+ DECODE_ADD_UCS_CHAR (c, dst);
+ }
+ else if (c == ';')
+ {
+ Lisp_Object string = make_string (str->er_buf,
+ str->er_counter);
+ Lisp_Object rest = Vcoded_charset_entity_reference_alist;
+ Lisp_Object cell;
+ Lisp_Object ret;
+ Lisp_Object pat;
+ Lisp_Object ccs;
+ int base;
+
+ while (!NILP (rest))
+ {
+ cell = Fcar (rest);
+ ccs = Fcar (cell);
+ if (NILP (ccs = Ffind_charset (ccs)))
+ continue;
+
+ cell = Fcdr (cell);
+ ret = Fcar (cell);
+ if (STRINGP (ret))
+ pat = ret;
+ else
+ continue;
+
+ cell = Fcdr (cell);
+ cell = Fcdr (cell);
+ ret = Fcar (cell);
+ if (EQ (ret, Qd))
+ {
+ pat = concat3 (build_string ("^&"),
+ pat, build_string ("\\([0-9]+\\)$"));
+ base = 10;
+ }
+ else if (EQ (ret, Qx))
+ {
+ pat = concat3 (build_string ("^&"),
+ pat, build_string ("\\([0-9a-f]+\\)$"));
+ base = 16;
+ }
+ else if (EQ (ret, QX))
+ {
+ pat = concat3 (build_string ("^&"),
+ pat, build_string ("\\([0-9A-F]+\\)$"));
+ base = 16;
+ }
+ else
+ continue;
+
+ if (!NILP (Fstring_match (pat, string, Qnil, Qnil)))
+ {
+ int code
+ = XINT (Fstring_to_number
+ (Fsubstring (string,
+ Fmatch_beginning (make_int (1)),
+ Fmatch_end (make_int (1))),
+ make_int (base)));
+
+ DECODE_ADD_UCS_CHAR (DECODE_CHAR (ccs, code), dst);
+ goto decoded;
+ }
+ rest = Fcdr (rest);
+ }
+ if (!NILP (Fstring_match (build_string ("^&MCS-\\([0-9A-F]+\\)$"),
+ string, Qnil, Qnil)))
+ {
+ int code
+ = XINT (Fstring_to_number
+ (Fsubstring (string,
+ Fmatch_beginning (make_int (1)),
+ Fmatch_end (make_int (1))),
+ make_int (16)));
+
+ DECODE_ADD_UCS_CHAR (code, dst);
+ }
+ else
+ {
+ Dynarr_add_many (dst, str->er_buf, str->er_counter);
+ Dynarr_add (dst, ';');
+ }
+ decoded:
+ str->er_counter = 0;
+ }
+ else if ( (str->er_counter >= 16) || (c >= 0x7F) )
+ {
+ Dynarr_add_many (dst, str->er_buf, str->er_counter);
+ str->er_counter = 0;
+ DECODE_ADD_UCS_CHAR (c, dst);
+ }
+ else
+ str->er_buf[str->er_counter++] = c;
+}
+
+INLINE_HEADER void
+COMPOSE_FLUSH_CHARS (struct decoding_stream *str, unsigned_char_dynarr* dst);
+INLINE_HEADER void
+COMPOSE_FLUSH_CHARS (struct decoding_stream *str, unsigned_char_dynarr* dst)
+{
+ unsigned i;
+
+ for (i = 0; i < str->combined_char_count; i++)
+ decode_add_er_char (str, str->combined_chars[i], dst);
+ str->combined_char_count = 0;
+ str->combining_table = Qnil;
+}
+
+void COMPOSE_ADD_CHAR (struct decoding_stream *str, Emchar character,
+ unsigned_char_dynarr* dst);
+void
+COMPOSE_ADD_CHAR (struct decoding_stream *str,
+ Emchar character, unsigned_char_dynarr* dst)
+{
+ if (CODING_SYSTEM_DISABLE_COMPOSITION (str->codesys))
+ decode_add_er_char (str, character, dst);
+ else if (!CHAR_TABLEP (str->combining_table))
+ {
+ Lisp_Object ret
+ = get_char_id_table (XCHAR_TABLE(Vcharacter_composition_table),
+ character);
+
+ if (NILP (ret))
+ decode_add_er_char (str, character, dst);
+ else
+ {
+ str->combined_chars[0] = character;
+ str->combined_char_count = 1;
+ str->combining_table = ret;
+ }
+ }
+ else
+ {
+ Lisp_Object ret
+ = get_char_id_table (XCHAR_TABLE(str->combining_table),
+ character);
+
+ if (CHARP (ret))
+ {
+ Emchar char2 = XCHARVAL (ret);
+ ret =
+ get_char_id_table (XCHAR_TABLE(Vcharacter_composition_table),
+ char2);
+ if (NILP (ret))
+ {
+ decode_add_er_char (str, character, dst);
+ str->combined_char_count = 0;
+ str->combining_table = Qnil;
+ }
+ else
+ {
+ str->combined_chars[0] = char2;
+ str->combined_char_count = 1;
+ str->combining_table = ret;
+ }
+ }
+ else if (CHAR_TABLEP (ret))
+ {
+ str->combined_chars[str->combined_char_count++] = character;
+ str->combining_table = ret;
+ }
+ else
+ {
+ COMPOSE_FLUSH_CHARS (str, dst);
+ decode_add_er_char (str, character, dst);
+ }
+ }
+}
+#else /* not UTF2000 */
+#define COMPOSE_FLUSH_CHARS(str, dst)
+#define COMPOSE_ADD_CHAR(str, ch, dst) DECODE_ADD_UCS_CHAR (ch, dst)
+#endif /* UTF2000 */
+
+static ssize_t decoding_reader (Lstream *stream,
+ unsigned char *data, size_t size);
+static ssize_t decoding_writer (Lstream *stream,
+ const unsigned char *data, size_t size);
+static int decoding_rewinder (Lstream *stream);
+static int decoding_seekable_p (Lstream *stream);
+static int decoding_flusher (Lstream *stream);
+static int decoding_closer (Lstream *stream);
+
+static Lisp_Object decoding_marker (Lisp_Object stream);
+
+DEFINE_LSTREAM_IMPLEMENTATION ("decoding", lstream_decoding,
+ sizeof (struct decoding_stream));
+
+static Lisp_Object
+decoding_marker (Lisp_Object stream)
+{
+ Lstream *str = DECODING_STREAM_DATA (XLSTREAM (stream))->other_end;
+ Lisp_Object str_obj;
+
+ /* We do not need to mark the coding systems or charsets stored
+ within the stream because they are stored in a global list
+ and automatically marked. */
+
+ XSETLSTREAM (str_obj, str);
+ mark_object (str_obj);
+ if (str->imp->marker)
+ return (str->imp->marker) (str_obj);
+ else
+ return Qnil;
+}
+
+/* Read SIZE bytes of data and store it into DATA. We are a decoding stream
+ so we read data from the other end, decode it, and store it into DATA. */
+
+static ssize_t
+decoding_reader (Lstream *stream, unsigned char *data, size_t size)
+{
+ struct decoding_stream *str = DECODING_STREAM_DATA (stream);
+ unsigned char *orig_data = data;
+ ssize_t read_size;
+ int error_occurred = 0;
+
+ /* We need to interface to mule_decode(), which expects to take some
+ amount of data and store the result into a Dynarr. We have
+ mule_decode() store into str->runoff, and take data from there
+ as necessary. */
+
+ /* We loop until we have enough data, reading chunks from the other
+ end and decoding it. */
+ while (1)
+ {
+ /* Take data from the runoff if we can. Make sure to take at
+ most SIZE bytes, and delete the data from the runoff. */