]> code.delx.au - gnu-emacs/blobdiff - lispref/internals.texi
(Sets And Lists): Add memql.
[gnu-emacs] / lispref / internals.texi
index 08323a17f1a98c62769945bad991a366e0c1deee..db7694585aa19c1d31e33664dcf9ee0d520d1952 100644 (file)
@@ -1,6 +1,7 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990, 1991, 1992, 1993, 1998 Free Software Foundation, Inc. 
+@c Copyright (C) 1990, 1991, 1992, 1993, 1998, 1999, 2002, 2003, 2004,
+@c   2005, 2006 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @setfilename ../info/internals
 @node GNU Emacs Internals, Standard Errors, Tips, Top
@@ -12,7 +13,7 @@ the preloaded Lisp libraries in it, how storage is allocated, and some
 internal aspects of GNU Emacs that may be of interest to C programmers.
 
 @menu
-* Building Emacs::      How to the dumped Emacs is made.
+* Building Emacs::      How the dumped Emacs is made.
 * Pure Storage::        A kludge to make preloaded Lisp functions sharable.
 * Garbage Collection::  Reclaiming space for Lisp objects no longer used.
 * Memory Usage::        Info about total size of Lisp objects made so far.
@@ -80,8 +81,9 @@ faster.  On modern machines, it is usually not advisable.
 
   After @file{loadup.el} reads @file{site-load.el}, it finds the
 documentation strings for primitive and preloaded functions (and
-variables) in the file @file{etc/DOC} where they are stored, by calling
-@code{Snarf-documentation} (@pxref{Accessing Documentation}).
+variables) in the file @file{etc/DOC} where they are stored, by
+calling @code{Snarf-documentation} (@pxref{Definition of
+Snarf-documentation,, Accessing Documentation}).
 
 @cindex @file{site-init.el}
   You can specify other Lisp expressions to execute just before dumping
@@ -115,6 +117,18 @@ expect in an ordinary unmodified Emacs.  If you feel you must override
 normal features for your site, do it with @file{default.el}, so that
 users can override your changes if they wish.  @xref{Startup Summary}.
 
+  In a package that can be preloaded, it is sometimes useful to
+specify a computation to be done when Emacs subsequently starts up.
+For this, use @code{eval-at-startup}:
+
+@defmac eval-at-startup body@dots{}
+This evaluates the @var{body} forms, either immediately if running in
+an Emacs that has already started up, or later when Emacs does start
+up.  Since the value of the @var{body} forms is not necessarily
+available when the @code{eval-at-startup} form is run, that form
+always returns @code{nil}.
+@end defmac
+
 @defun dump-emacs to-file from-file
 @cindex unexec
 This function dumps the current state of Emacs into an executable file
@@ -141,19 +155,24 @@ standard preloaded Lisp libraries.  In the file @file{emacs}, it is
 marked as read-only (on operating systems that permit this), so that
 the memory space can be shared by all the Emacs jobs running on the
 machine at once.  Pure storage is not expandable; a fixed amount is
-allocated when Emacs is compiled, and if that is not sufficient for the
-preloaded libraries, @file{temacs} crashes.  If that happens, you must
-increase the compilation parameter @code{PURESIZE} in the file
-@file{src/puresize.h}.  This normally won't happen unless you try to
-preload additional libraries or add features to the standard ones.
+allocated when Emacs is compiled, and if that is not sufficient for
+the preloaded libraries, @file{temacs} allocates dynamic memory for
+the part that didn't fit.  If that happens, you should increase the
+compilation parameter @code{PURESIZE} in the file
+@file{src/puresize.h} and rebuild Emacs, even though the resulting
+image will work: garbage collection is disabled in this situation,
+causing a memory leak.  Such an overflow normally won't happen unless you
+try to preload additional libraries or add features to the standard
+ones.  Emacs will display a warning about the overflow when it
+starts.
 
 @defun purecopy object
 This function makes a copy in pure storage of @var{object}, and returns
 it.  It copies a string by simply making a new string with the same
-characters in pure storage.  It recursively copies the contents of
-vectors and cons cells.  It does not make copies of other objects such
-as symbols, but just returns them unchanged.  It signals an error if
-asked to copy markers.
+characters, but without text properties, in pure storage.  It
+recursively copies the contents of vectors and cons cells.  It does
+not make copies of other objects such as symbols, but just returns
+them unchanged.  It signals an error if asked to copy markers.
 
 This function is a no-op except while Emacs is being built and dumped;
 it is usually called only in the file @file{emacs/lisp/loaddefs.el}, but
@@ -215,7 +234,7 @@ to them, since there is no longer a way to reach them.  Their space
 might as well be reused, since no one will miss them.  The second
 (``sweep'') phase of the garbage collector arranges to reuse them.
 
-??? Maybe add something describing weak hash tables here?
+@c ??? Maybe add something describing weak hash tables here?
 
 @cindex free list
   The sweep phase puts unused cons cells onto a @dfn{free list}
@@ -254,10 +273,11 @@ information:
  (@var{used-syms} . @var{free-syms})
 @end group
  (@var{used-miscs} . @var{free-miscs})
- @var{used-string-chars} 
+ @var{used-string-chars}
  @var{used-vector-slots}
  (@var{used-floats} . @var{free-floats})
- (@var{used-intervals} . @var{free-intervals}))
+ (@var{used-intervals} . @var{free-intervals})
+ (@var{used-strings} . @var{free-strings}))
 @end example
 
 Here is an example:
@@ -267,7 +287,8 @@ Here is an example:
 (garbage-collect)
      @result{} ((106886 . 13184) (9769 . 0)
                 (7731 . 4651) 347543 121628
-                (31 . 94) (1273 . 168))
+                (31 . 94) (1273 . 168)
+                (25474 . 3569))
 @end group
 @end example
 
@@ -318,7 +339,20 @@ data structure used for representing text properties.
 @item free-intervals
 The number of intervals for which space has been obtained
 from the operating system, but that are not currently being used.
+
+@item used-strings
+The number of strings in use.
+
+@item free-strings
+The number of string headers for which the space was obtained from the
+operating system, but which are currently not in use.  (A string
+object consists of a header and the storage for the string text
+itself; the latter is only allocated when the string is created.)
 @end table
+
+If there was overflow in pure space (see the previous section),
+@code{garbage-collect} returns @code{nil}, because a real garbage
+collection can not be done in this situation.
 @end deffn
 
 @defopt garbage-collection-messages
@@ -327,6 +361,12 @@ beginning and end of garbage collection.  The default value is
 @code{nil}, meaning there are no such messages.
 @end defopt
 
+@defvar post-gc-hook
+This is a normal hook that is run at the end of garbage collection.
+Garbage collection is inhibited while the hook functions run, so be
+careful writing them.
+@end defvar
+
 @defopt gc-cons-threshold
 The value of this variable is the number of bytes of storage that must
 be allocated for Lisp objects after one garbage collection in order to
@@ -349,7 +389,18 @@ until the subsequent garbage collection, at which time
 @code{garbage-collect} will set the threshold back to 10,000.
 @end defopt
 
-  The value return by @code{garbage-collect} describes the amount of
+@defopt gc-cons-percentage
+The value of this variable specifies the amount of consing before a
+garbage collection occurs, as a fraction of the current heap size.
+This criterion and @code{gc-cons-threshold} apply in parallel, and
+garbage collection occurs only when both criteria are satisfied.
+
+As the heap size increases, the time to perform a garbage collection
+increases.  Thus, it can be desirable to do them less frequently in
+proportion.
+@end defopt
+
+  The value returned by @code{garbage-collect} describes the amount of
 memory used by Lisp data, broken down by data type.  By contrast, the
 function @code{memory-limit} provides information on the total amount of
 memory Emacs is currently using.
@@ -364,6 +415,28 @@ You can use this to get a general idea of how your actions affect the
 memory usage.
 @end defun
 
+@defvar memory-full
+This variable is @code{t} if Emacs is close to out of memory for Lisp
+objects, and @code{nil} otherwise.
+@end defvar
+
+@defun memory-use-counts
+This returns a list of numbers that count the number of objects
+created in this Emacs session.  Each of these counters increments for
+a certain kind of object.  See the documentation string for details.
+@end defun
+
+@defvar gcs-done
+This variable contains the total number of garbage collections
+done so far in this Emacs session.
+@end defvar
+
+@defvar gc-elapsed
+This variable contains the total number of seconds of elapsed time
+during garbage collection so far in this Emacs session, as a floating
+point number.
+@end defvar
+
 @node Memory Usage
 @section Memory Usage
 
@@ -410,6 +483,11 @@ The total number of intervals that have been allocated so far
 in this Emacs session.
 @end defvar
 
+@defvar strings-consed
+The total number of strings that have been allocated so far in this
+Emacs session.
+@end defvar
+
 @node Writing Emacs Primitives
 @appendixsec Writing Emacs Primitives
 @cindex primitive function internals
@@ -427,36 +505,31 @@ appearance.)
 @smallexample
 @group
 DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
-  "Eval args until one of them yields non-nil; return that value.\n\
-The remaining args are not evalled at all.\n\
+  doc: /* Eval args until one of them yields non-nil, then return that
+value. The remaining args are not evalled at all.
+If all args return nil, return nil.
 @end group
 @group
-If all args return nil, return nil.")
+usage: (or CONDITIONS ...)  */)
   (args)
      Lisp_Object args;
 @{
-  register Lisp_Object val;
-  Lisp_Object args_left;
+  register Lisp_Object val = Qnil;
   struct gcpro gcpro1;
 @end group
 
 @group
-  if (NILP (args))
-    return Qnil;
-
-  args_left = args;
-  GCPRO1 (args_left);
+  GCPRO1 (args);
 @end group
 
 @group
-  do
+  while (CONSP (args))
     @{
-      val = Feval (Fcar (args_left));
+      val = Feval (XCAR (args));
       if (!NILP (val))
-        break;
-      args_left = Fcdr (args_left);
+       break;
+      args = XCDR (args);
     @}
-  while (!NILP (args_left));
 @end group
 
 @group
@@ -507,7 +580,7 @@ indicating a special form that receives unevaluated arguments, or
 @code{MANY}, indicating an unlimited number of evaluated arguments (the
 equivalent of @code{&rest}).  Both @code{UNEVALLED} and @code{MANY} are
 macros.  If @var{max} is a number, it may not be less than @var{min} and
-it may not be greater than seven.
+it may not be greater than eight.
 
 @item interactive
 This is an interactive specification, a string such as might be used as
@@ -517,10 +590,23 @@ called interactively.  A value of @code{""} indicates a function that
 should receive no arguments when called interactively.
 
 @item doc
-This is the documentation string.  It is written just like a
-documentation string for a function defined in Lisp, except you must
-write @samp{\n\} at the end of each line.  In particular, the first line
-should be a single sentence.
+This is the documentation string.  It uses C comment syntax rather
+than C string syntax because comment syntax requires nothing special
+to include multiple lines.  The @samp{doc:} identifies the comment
+that follows as the documentation string.  The @samp{/*} and @samp{*/}
+delimiters that begin and end the comment are not part of the
+documentation string.
+
+If the last line of the documentation string begins with the keyword
+@samp{usage:}, the rest of the line is treated as the argument list
+for documentation purposes.  This way, you can use different argument
+names in the documentation string from the ones used in the C code.
+@samp{usage:} is required if the function has an unlimited number of
+arguments.
+
+All the usual rules for documentation strings in Lisp code
+(@pxref{Documentation Tips}) apply to C code documentation strings
+too.
 @end table
 
   After the call to the @code{DEFUN} macro, you must write the argument
@@ -534,34 +620,47 @@ arguments, and the second is the address of a block containing their
 values.  They have types @code{int} and @w{@code{Lisp_Object *}}.
 
   Within the function @code{For} itself, note the use of the macros
-@code{GCPRO1} and @code{UNGCPRO}.  @code{GCPRO1} is used to ``protect''
-a variable from garbage collection---to inform the garbage collector that
-it must look in that variable and regard its contents as an accessible
-object.  This is necessary whenever you call @code{Feval} or anything
-that can directly or indirectly call @code{Feval}.  At such a time, any
-Lisp object that you intend to refer to again must be protected somehow.
-@code{UNGCPRO} cancels the protection of the variables that are
-protected in the current function.  It is necessary to do this explicitly.
-
-  For most data types, it suffices to protect at least one pointer to
-the object; as long as the object is not recycled, all pointers to it
-remain valid.  This is not so for strings, because the garbage collector
-can move them.  When the garbage collector moves a string, it relocates
-all the pointers it knows about; any other pointers become invalid.
-Therefore, you must protect all pointers to strings across any point
-where garbage collection may be possible.
-
-  The macro @code{GCPRO1} protects just one local variable.  If you want
-to protect two, use @code{GCPRO2} instead; repeating @code{GCPRO1} will
-not work.  Macros @code{GCPRO3} and @code{GCPRO4} also exist.
-
-  These macros implicitly use local variables such as @code{gcpro1}; you
-must declare these explicitly, with type @code{struct gcpro}.  Thus, if
-you use @code{GCPRO2}, you must declare @code{gcpro1} and @code{gcpro2}.
+@code{GCPRO1} and @code{UNGCPRO}.  @code{GCPRO1} is used to
+``protect'' a variable from garbage collection---to inform the garbage
+collector that it must look in that variable and regard its contents
+as an accessible object.  GC protection is necessary whenever you call
+@code{Feval} or anything that can directly or indirectly call
+@code{Feval}.  At such a time, any Lisp object that this function may
+refer to again must be protected somehow.
+
+  It suffices to ensure that at least one pointer to each object is
+GC-protected; that way, the object cannot be recycled, so all pointers
+to it remain valid.  Thus, a particular local variable can do without
+protection if it is certain that the object it points to will be
+preserved by some other pointer (such as another local variable which
+has a @code{GCPRO})@footnote{Formerly, strings were a special
+exception; in older Emacs versions, every local variable that might
+point to a string needed a @code{GCPRO}.}.  Otherwise, the local
+variable needs a @code{GCPRO}.
+
+  The macro @code{GCPRO1} protects just one local variable.  If you
+want to protect two variables, use @code{GCPRO2} instead; repeating
+@code{GCPRO1} will not work.  Macros @code{GCPRO3}, @code{GCPRO4},
+@code{GCPRO5}, and @code{GCPRO6} also exist.  All these macros
+implicitly use local variables such as @code{gcpro1}; you must declare
+these explicitly, with type @code{struct gcpro}.  Thus, if you use
+@code{GCPRO2}, you must declare @code{gcpro1} and @code{gcpro2}.
 Alas, we can't explain all the tricky details here.
 
+  @code{UNGCPRO} cancels the protection of the variables that are
+protected in the current function.  It is necessary to do this
+explicitly.
+
+  Built-in functions that take a variable number of arguments actually
+accept two arguments at the C level: the number of Lisp arguments, and
+a @code{Lisp_Object *} pointer to a C vector containing those Lisp
+arguments.  This C vector may be part of a Lisp vector, but it need
+not be.  The responsibility for using @code{GCPRO} to protect the Lisp
+arguments from GC if necessary rests with the caller in this case,
+since the caller allocated or found the storage for them.
+
   You must not use C initializers for static or global variables unless
-the variables are never stored in once Emacs is dumped.  These variables
+the variables are never written once Emacs is dumped.  These variables
 with initializers are allocated in an area of memory that becomes
 read-only (on certain operating systems) as a result of dumping Emacs.
 @xref{Pure Storage}.
@@ -595,6 +694,7 @@ file, add to it a @code{syms_of_@var{filename}} (e.g.,
 of these functions are called, and add a call to
 @code{syms_of_@var{filename}} there.
 
+@anchor{Defining Lisp variables in C}
 @vindex byte-boolean-vars
   The function @code{syms_of_@var{filename}} is also the place to define
 any C variables that are to be visible as Lisp variables.
@@ -623,7 +723,7 @@ of macros and functions to manipulate Lisp objects.
 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
   Scoordinates_in_window_p, 2, 2,
   "xSpecify coordinate pair: \nXExpression which evals to window: ",
-  "Return non-nil if COORDINATES is in WINDOW.\n\  
+  "Return non-nil if COORDINATES is in WINDOW.\n\
 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
 ...
 @end group
@@ -692,10 +792,10 @@ number of arguments.  They work by calling @code{Ffuncall}.
 @file{lisp.h} contains the definitions for some important macros and
 functions.
 
-  If you define a function which is side-effect free, update the code in
-@file{byte-opt.el} which binds @code{side-effect-free-fns} and
-@code{side-effect-and-error-free-fns} to include it.  This will help the
-optimizer.
+  If you define a function which is side-effect free, update the code
+in @file{byte-opt.el} which binds @code{side-effect-free-fns} and
+@code{side-effect-and-error-free-fns} so that the compiler optimizer
+knows about it.
 
 @node Object Internals
 @appendixsec Object Internals
@@ -705,9 +805,9 @@ optimizer.
 data are stored in a heap and the only access that programs have to it
 is through pointers.  Pointers are thirty-two bits wide in most
 implementations.  Depending on the operating system and type of machine
-for which you compile Emacs, twenty-eight bits are used to address the
-object, and the remaining four bits are used for a GC mark bit and the
-tag that identifies the object's type.
+for which you compile Emacs, twenty-nine bits are used to address the
+object, and the remaining three bits are used for the tag that
+identifies the object's type.
 
   Because Lisp objects are represented as tagged pointers, it is always
 possible to determine the Lisp data type of any object.  The C data type
@@ -744,10 +844,11 @@ Here is a list of the @code{struct buffer_text} fields:
 
 @table @code
 @item beg
-This field contains the Actual address of the buffer contents.
+This field contains the actual address of the buffer contents.
 
-@item got
+@item gpt
 This holds the character position of the gap in the buffer.
+@xref{Buffer Gap}.
 
 @item z
 This field contains the character position of the end of the buffer
@@ -760,7 +861,7 @@ Contains the byte position of the gap.
 Holds the byte position of the end of the buffer text.
 
 @item gap_size
-Contains the size of buffer's gap.
+Contains the size of buffer's gap.  @xref{Buffer Gap}.
 
 @item modiff
 This field counts buffer-modification events for this buffer.  It is
@@ -769,30 +870,30 @@ incremented for each such event, and never otherwise changed.
 @item save_modiff
 Contains the previous value of @code{modiff}, as of the last time a
 buffer was visited or saved in a file.
-    
+
 @item overlay_modiff
 Counts modifications to overlays analogous to @code{modiff}.
-       
+
 @item beg_unchanged
 Holds the number of characters at the start of the text that are known
 to be unchanged since the last redisplay that finished.
-    
+
 @item end_unchanged
 Holds the number of characters at the end of the text that are known to
 be unchanged since the last redisplay that finished.
-    
+
 @item unchanged_modified
 Contains the value of @code{modiff} at the time of the last redisplay
 that finished.  If this value matches @code{modiff},
 @code{beg_unchanged} and @code{end_unchanged} contain no useful
 information.
-    
+
 @item overlay_unchanged_modified
 Contains the value of @code{overlay_modiff} at the time of the last
 redisplay that finished.  If this value matches @code{overlay_modiff},
 @code{beg_unchanged} and @code{end_unchanged} contain no useful
 information.
-       
+
 @item markers
 The markers that refer to this buffer.  This is actually a single
 marker, and successive elements in its marker @code{chain} are the other
@@ -831,19 +932,19 @@ Contains the character position of point in a buffer.
 Contains the byte position of point in a buffer.
 
 @item begv
-This field contains the character position of the beginning of the 
+This field contains the character position of the beginning of the
 accessible range of text in the buffer.
 
 @item begv_byte
-This field contains the byte position of the beginning of the 
+This field contains the byte position of the beginning of the
 accessible range of text in the buffer.
 
 @item zv
-This field contains the character position of the end of the 
+This field contains the character position of the end of the
 accessible range of text in the buffer.
 
 @item zv_byte
-This field contains the byte position of the end of the 
+This field contains the byte position of the end of the
 accessible range of text in the buffer.
 
 @item base_buffer
@@ -878,7 +979,7 @@ the last time the buffer was displayed in a window.
 This flag is set when narrowing changes in a buffer.
 
 @item prevent_redisplay_optimizations_p
-A flag indicating the redisplay optiomizations should not be used 
+this flag indicates that redisplay optimizations should not be used
 to display this buffer.
 
 @item undo_list
@@ -890,7 +991,7 @@ be unique.  @xref{Buffer Names}.
 
 @item filename
 The name of the file visited in this buffer, or @code{nil}.
+
 @item directory
 The directory for expanding relative file names.
 
@@ -900,7 +1001,7 @@ This and other fields concerned with saving are not kept in the
 @code{buffer_text} structure because indirect buffers are never saved.
 
 @item auto_save_file_name
-File name used for auto-saving this buffer.  This is not in the 
+File name used for auto-saving this buffer.  This is not in the
 @code{buffer_text} because it's not used in indirect buffers at all.
 
 @item read_only
@@ -928,7 +1029,7 @@ Mode line element that controls the format of the mode line.  If this
 is @code{nil}, no mode line will be displayed.
 
 @item header_line_format
-This field is analoguous to @code{mode_line_format} for the mode 
+This field is analogous to @code{mode_line_format} for the mode
 line displayed at the top of windows.
 
 @item keymap
@@ -1029,6 +1130,9 @@ The value of @code{buffer-file-coding-system} in this buffer.
 @item file_format
 The value of @code{buffer-file-format} in this buffer.
 
+@item auto_save_file_format
+The value of @code{buffer-auto-save-file-format} in this buffer.
+
 @item pt_marker
 In an indirect buffer, or a buffer that is the base of an indirect
 buffer, this holds a marker that records point for this buffer when the
@@ -1038,7 +1142,7 @@ buffer is not current.
 In an indirect buffer, or a buffer that is the base of an indirect
 buffer, this holds a marker that records @code{begv} for this buffer
 when the buffer is not current.
+
 @item zv_marker
 In an indirect buffer, or a buffer that is the base of an indirect
 buffer, this holds a marker that records @code{zv} for this buffer when
@@ -1073,7 +1177,7 @@ displayed in a window.
 
 @item scroll_up_aggressively
 The value of @code{scroll-up-aggressively} in this buffer.
+
 @item scroll_down_aggressively
 The value of @code{scroll-down-aggressively} in this buffer.
 @end table
@@ -1157,7 +1261,7 @@ window to show the text around point, it moves point to a location that
 is on the screen.
 
 @item frozen_window_start_p
-This field is set temporarily to 1 to indicate to redisplay that 
+This field is set temporarily to 1 to indicate to redisplay that
 @code{start} of this window should not be changed, even if point
 gets invisible.
 
@@ -1166,7 +1270,7 @@ Non-@code{nil} means current value of @code{start} was the beginning of a line
 when it was chosen.
 
 @item too_small_ok
-Non-@code{nil} means don't delete this window for becoming ``too small''.
+Non-@code{nil} means don't delete this window for becoming ``too small.''
 
 @item height_fixed_p
 This field is temporarily set to 1 to fix the height of the selected
@@ -1232,7 +1336,7 @@ onto the screen.
 
 @item redisplay_end_trigger
 If redisplay in this window goes beyond this buffer position, it runs
-run the @code{redisplay-end-trigger-hook}.
+the @code{redisplay-end-trigger-hook}.
 
 @ignore
 @item orig_height
@@ -1331,7 +1435,7 @@ A function called whenever the process receives a signal, or @code{nil}.
 The associated buffer of the process.
 
 @item pid
-An integer, the Unix process @sc{id}.
+An integer, the operating system's process @acronym{ID}.
 
 @item childp
 A flag, non-@code{nil} if this is really a child process.
@@ -1361,7 +1465,7 @@ needs to be reported, either by running the sentinel or by inserting a
 message in the process buffer.
 
 @item pty_flag
-Non-@code{nil} if communication with the subprocess uses a @sc{pty};
+Non-@code{nil} if communication with the subprocess uses a @acronym{PTY};
 @code{nil} if it uses a pipe.
 
 @item infd
@@ -1392,7 +1496,7 @@ Size of carryover in decoding.
 Coding-system for encoding the output to this process.
 
 @item encoding_buf
-A working buffer for enecoding.
+A working buffer for encoding.
 
 @item encoding_carryover
 Size of carryover in encoding.
@@ -1401,3 +1505,7 @@ Size of carryover in encoding.
 Flag to set @code{coding-system} of the process buffer from the
 coding system used to decode process output.
 @end table
+
+@ignore
+   arch-tag: 4b2c33bc-d7e4-43f5-bc20-27c0db52a53e
+@end ignore