use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / charset.c
index fdb8eeb..97d6346 100644 (file)
@@ -1,13 +1,15 @@
 /* Basic character set support.
-   Copyright (C) 2001-2013 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-     2005, 2006, 2007, 2008, 2009, 2010, 2011
-     National Institute of Advanced Industrial Science and Technology (AIST)
-     Registration Number H14PRO021
 
-   Copyright (C) 2003, 2004
-     National Institute of Advanced Industrial Science and Technology (AIST)
-     Registration Number H13PRO009
+Copyright (C) 2001-2014 Free Software Foundation, Inc.
+
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+  2005, 2006, 2007, 2008, 2009, 2010, 2011
+  National Institute of Advanced Industrial Science and Technology (AIST)
+  Registration Number H14PRO021
+
+Copyright (C) 2003, 2004
+  National Institute of Advanced Industrial Science and Technology (AIST)
+  Registration Number H13PRO009
 
 This file is part of GNU Emacs.
 
@@ -26,8 +28,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define CHARSET_INLINE EXTERN_INLINE
-
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <limits.h>
@@ -388,12 +389,12 @@ load_charset_map (struct charset *charset, struct charset_map_entries *entries,
        {
          if (ascii_compatible_p)
            {
-             if (! ASCII_BYTE_P (from_c))
+             if (! ASCII_CHAR_P (from_c))
                {
                  if (from_c < nonascii_min_char)
                    nonascii_min_char = from_c;
                }
-             else if (! ASCII_BYTE_P (to_c))
+             else if (! ASCII_CHAR_P (to_c))
                {
                  nonascii_min_char = 0x80;
                }
@@ -477,32 +478,39 @@ read_hex (FILE *fp, bool *eof, bool *overflow)
    `file-name-handler-alist' to avoid running any Lisp code.  */
 
 static void
-load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int control_flag)
+load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
+                           int control_flag)
 {
   unsigned min_code = CHARSET_MIN_CODE (charset);
   unsigned max_code = CHARSET_MAX_CODE (charset);
   int fd;
-  FILE *fp;
+  FILE *fp = NULL;
   Lisp_Object suffixes;
   struct charset_map_entries *head, *entries;
   int n_entries;
   ptrdiff_t count;
-  USE_SAFE_ALLOCA;
 
-  suffixes = Fcons (build_string (".map"),
-                   Fcons (build_string (".TXT"), Qnil));
+  suffixes = list2 (build_string (".map"), build_string (".TXT"));
 
-  count = SPECPDL_INDEX ();
-  specbind (Qfile_name_handler_alist, Qnil);
-  fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil);
-  unbind_to (count, Qnil);
-  if (fd < 0
-      || ! (fp = fdopen (fd, "r")))
-    error ("Failure in loading charset map: %s", SDATA (mapfile));
+  dynwind_begin ();
+  record_unwind_protect_ptr (fclose_ptr_unwind, &fp);
+  {
+    dynwind_begin ();
+    specbind (Qfile_name_handler_alist, Qnil);
+    fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, false);
+    fp = fd < 0 ? 0 : fdopen (fd, "r");
+    if (!fp)
+      {
+        int open_errno = errno;
+        emacs_close (fd);
+        report_file_errno ("Loading charset map", mapfile, open_errno);
+      }
+    dynwind_end ();
+  }
 
-  /* Use SAFE_ALLOCA instead of alloca, as `charset_map_entries' is
-     large (larger than MAX_ALLOCA).  */
-  head = SAFE_ALLOCA (sizeof *head);
+  /* Use record, as `charset_map_entries' is large (larger than
+     MAX_ALLOCA).  */
+  head = xmalloc (sizeof *head);
   entries = head;
   memset (entries, 0, sizeof (struct charset_map_entries));
 
@@ -531,9 +539,9 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
       if (from < min_code || to > max_code || from > to || c > MAX_CHAR)
        continue;
 
-      if (n_entries > 0 && (n_entries % 0x10000) == 0)
+      if (n_entries == 0x10000)
        {
-         entries->next = SAFE_ALLOCA (sizeof *entries->next);
+         entries->next = xmalloc (sizeof *entries->next);
          entries = entries->next;
          memset (entries, 0, sizeof (struct charset_map_entries));
          n_entries = 0;
@@ -545,9 +553,10 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
       n_entries++;
     }
   fclose (fp);
+  fp = NULL;
 
   load_charset_map (charset, head, n_entries, control_flag);
-  SAFE_FREE ();
+  dynwind_end ();
 }
 
 static void
@@ -907,7 +916,7 @@ usage: (define-charset-internal ...)  */)
 
   if (! charset.code_linear_p)
     {
-      charset.code_space_mask = xzalloc (256);
+      charset.code_space_mask = xzalloc_atomic (256);
       for (i = 0; i < 4; i++)
        for (j = charset.code_space[i * 4]; j <= charset.code_space[i * 4 + 1];
             j++)
@@ -1178,7 +1187,7 @@ usage: (define-charset-internal ...)  */)
                         charset.iso_final) = id;
       if (new_definition_p)
        Viso_2022_charset_list = nconc2 (Viso_2022_charset_list,
-                                        Fcons (make_number (id), Qnil));
+                                        list1 (make_number (id)));
       if (ISO_CHARSET_TABLE (1, 0, 'J') == id)
        charset_jisx0201_roman = id;
       else if (ISO_CHARSET_TABLE (2, 0, '@') == id)
@@ -1198,7 +1207,7 @@ usage: (define-charset-internal ...)  */)
        emacs_mule_bytes[charset.emacs_mule_id] = charset.dimension + 2;
       if (new_definition_p)
        Vemacs_mule_charset_list = nconc2 (Vemacs_mule_charset_list,
-                                          Fcons (make_number (id), Qnil));
+                                          list1 (make_number (id)));
     }
 
   if (new_definition_p)
@@ -1206,7 +1215,7 @@ usage: (define-charset-internal ...)  */)
       Vcharset_list = Fcons (args[charset_arg_name], Vcharset_list);
       if (charset.supplementary_p)
        Vcharset_ordered_list = nconc2 (Vcharset_ordered_list,
-                                       Fcons (make_number (id), Qnil));
+                                       list1 (make_number (id)));
       else
        {
          Lisp_Object tail;
@@ -1223,7 +1232,7 @@ usage: (define-charset-internal ...)  */)
                                           Vcharset_ordered_list);
          else if (NILP (tail))
            Vcharset_ordered_list = nconc2 (Vcharset_ordered_list,
-                                           Fcons (make_number (id), Qnil));
+                                           list1 (make_number (id)));
          else
            {
              val = Fcons (XCAR (tail), XCDR (tail));
@@ -1515,7 +1524,7 @@ find_charsets_in_text (const unsigned char *ptr, ptrdiff_t nchars,
 
            if (!NILP (table))
              c = translate_char (table, c);
-           if (ASCII_BYTE_P (c))
+           if (ASCII_CHAR_P (c))
              ASET (charsets, charset_ascii, Qt);
            else
              ASET (charsets, charset_eight_bit, Qt);
@@ -1855,10 +1864,7 @@ DEFUN ("decode-char", Fdecode_char, Sdecode_char, 2, 3, 0,
        doc: /* Decode the pair of CHARSET and CODE-POINT into a character.
 Return nil if CODE-POINT is not valid in CHARSET.
 
-CODE-POINT may be a cons (HIGHER-16-BIT-VALUE . LOWER-16-BIT-VALUE).
-
-Optional argument RESTRICTION specifies a way to map the pair of CCS
-and CODE-POINT to a character.  Currently not supported and just ignored.  */)
+CODE-POINT may be a cons (HIGHER-16-BIT-VALUE . LOWER-16-BIT-VALUE).  */)
   (Lisp_Object charset, Lisp_Object code_point, Lisp_Object restriction)
 {
   int c, id;
@@ -1875,10 +1881,7 @@ and CODE-POINT to a character.  Currently not supported and just ignored.  */)
 
 DEFUN ("encode-char", Fencode_char, Sencode_char, 2, 3, 0,
        doc: /* Encode the character CH into a code-point of CHARSET.
-Return nil if CHARSET doesn't include CH.
-
-Optional argument RESTRICTION specifies a way to map CH to a
-code-point in CCS.  Currently not supported and just ignored.  */)
+Return nil if CHARSET doesn't include CH.  */)
   (Lisp_Object ch, Lisp_Object charset, Lisp_Object restriction)
 {
   int c, id;
@@ -2046,6 +2049,8 @@ CH in the charset.  */)
 
 DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 2, 0,
        doc: /* Return the charset of highest priority that contains CH.
+ASCII characters are an exception: for them, this function always
+returns `ascii'.
 If optional 2nd arg RESTRICTION is non-nil, it is a list of charsets
 from which to find the charset.  It may also be a coding system.  In
 that case, find the charset from what supported by that coding system.  */)
@@ -2302,13 +2307,15 @@ init_charset (void)
          obscure problem (eg bug#6401), so better abort.  */
       fprintf (stderr, "Error: charsets directory not found:\n\
 %s\n\
-Emacs will not function correctly without the character map files.\n\
+Emacs will not function correctly without the character map files.\n%s\
 Please check your installation!\n",
-                   SDATA (tempdir));
+               SDATA (tempdir),
+               egetenv("EMACSDATA") ? "The EMACSDATA environment \
+variable is set, maybe it has the wrong value?\n" : "");
       exit (1);
     }
 
-  Vcharset_map_path = Fcons (tempdir, Qnil);
+  Vcharset_map_path = list1 (tempdir);
 }
 
 
@@ -2348,6 +2355,8 @@ static struct charset charset_table_init[180];
 void
 syms_of_charset (void)
 {
+#include "charset.x"
+
   DEFSYM (Qcharsetp, "charsetp");
 
   DEFSYM (Qascii, "ascii");
@@ -2381,33 +2390,9 @@ syms_of_charset (void)
   }
 
   charset_table = charset_table_init;
-  charset_table_size = sizeof charset_table_init / sizeof *charset_table_init;
+  charset_table_size = ARRAYELTS (charset_table_init);
   charset_table_used = 0;
 
-  defsubr (&Scharsetp);
-  defsubr (&Smap_charset_chars);
-  defsubr (&Sdefine_charset_internal);
-  defsubr (&Sdefine_charset_alias);
-  defsubr (&Scharset_plist);
-  defsubr (&Sset_charset_plist);
-  defsubr (&Sunify_charset);
-  defsubr (&Sget_unused_iso_final_char);
-  defsubr (&Sdeclare_equiv_charset);
-  defsubr (&Sfind_charset_region);
-  defsubr (&Sfind_charset_string);
-  defsubr (&Sdecode_char);
-  defsubr (&Sencode_char);
-  defsubr (&Ssplit_char);
-  defsubr (&Smake_char);
-  defsubr (&Schar_charset);
-  defsubr (&Scharset_after);
-  defsubr (&Siso_charset);
-  defsubr (&Sclear_charset_maps);
-  defsubr (&Scharset_priority_list);
-  defsubr (&Sset_charset_priority);
-  defsubr (&Scharset_id_internal);
-  defsubr (&Ssort_charsets);
-
   DEFVAR_LISP ("charset-map-path", Vcharset_map_path,
               doc: /* List of directories to search for charset map files.  */);
   Vcharset_map_path = Qnil;
@@ -2427,19 +2412,19 @@ the value may be a list of mnemonics.  */);
   Vcurrent_iso639_language = Qnil;
 
   charset_ascii
-    = define_charset_internal (Qascii, 1, "\x00\x7F\x00\x00\x00\x00",
+    = define_charset_internal (Qascii, 1, "\x00\x7F\0\0\0\0\0",
                               0, 127, 'B', -1, 0, 1, 0, 0);
   charset_iso_8859_1
-    = define_charset_internal (Qiso_8859_1, 1, "\x00\xFF\x00\x00\x00\x00",
+    = define_charset_internal (Qiso_8859_1, 1, "\x00\xFF\0\0\0\0\0",
                               0, 255, -1, -1, -1, 1, 0, 0);
   charset_unicode
-    = define_charset_internal (Qunicode, 3, "\x00\xFF\x00\xFF\x00\x10",
+    = define_charset_internal (Qunicode, 3, "\x00\xFF\x00\xFF\x00\x10\0",
                               0, MAX_UNICODE_CHAR, -1, 0, -1, 1, 0, 0);
   charset_emacs
-    = define_charset_internal (Qemacs, 3, "\x00\xFF\x00\xFF\x00\x3F",
+    = define_charset_internal (Qemacs, 3, "\x00\xFF\x00\xFF\x00\x3F\0",
                               0, MAX_5_BYTE_CHAR, -1, 0, -1, 1, 1, 0);
   charset_eight_bit
-    = define_charset_internal (Qeight_bit, 1, "\x80\xFF\x00\x00\x00\x00",
+    = define_charset_internal (Qeight_bit, 1, "\x80\xFF\0\0\0\0\0",
                               128, 255, -1, 0, -1, 0, 1,
                               MAX_5_BYTE_CHAR + 1);
   charset_unibyte = charset_iso_8859_1;