<2022-09-14 Wed>
emacs
源码分析(一)
最近心头又一热,想再学学emacs
的源码,对于emacs-lisp
这个语言越来越喜欢,所以有上面Emacs Lisp Intro
的学习,看看info
页,做做它的习题,感觉挺爽。
因为如果从emacs
的源代码入手直接开始学习我觉得非常难,就像之前看emacs
的源码一样,到最后进行不下去了也就只能放弃了。所以先选择熟悉emacs-lisp
语言,相信对于最终emacs
的源码分析会很有帮助。
但是对于emacs
的内存结构也一直好奇,为什么Lisp_Object
要是一个不完全类型?它是怎么实现诸如Lips_String
,Lisp_Vector
这样的结构的?等等。
我这里选择的版本是27.2
或者28.1
。
globals.h
是如何生成的
这个文件是在编译过程中生成的,里面有很多宏定义是代码里需要用到的,比如在跟踪init_alloc_once()
时,第一个变量gc_cons_threshold
的定义就来自globals.h
文件,相信对于理解内存结构会很有帮助。经过查找会发现在src/Makefile.in
中有如下内容:
gl-stamp: $(libsrc)/make-docfile$(EXEEXT) $(GLOBAL_SOURCES)
$(AM_V_GLOBALS)$(libsrc)/make-docfile -d $(srcdir) -g $(obj) > globals.tmp
$(AM_V_at)$(top_srcdir)/build-aux/move-if-change globals.tmp globals.h
$(AM_V_at)echo timestamp > $@
globals.h: gl-stamp; @true
这里就很容易理解了,globals.h
是通过make-docfile
生成的,将命令隔离出来运行一下看看:
$ make-docfile -d ~/dnld/emacs-28.1/src -g emacs.o > emacs.o.make-docfile
生成的emacs.o.make-docfile
内容如下:
/* This file was auto-generated by make-docfile. */
/* DO NOT EDIT. */
struct emacs_globals {
Lisp_Object f_Vafter_init_time;
#define Vafter_init_time globals.f_Vafter_init_time
Lisp_Object f_Vbefore_init_time;
#define Vbefore_init_time globals.f_Vbefore_init_time
Lisp_Object f_Vcommand_line_args;
#define Vcommand_line_args globals.f_Vcommand_line_args
Lisp_Object f_Vdump_mode;
#define Vdump_mode globals.f_Vdump_mode
Lisp_Object f_Vdynamic_library_alist;
#define Vdynamic_library_alist globals.f_Vdynamic_library_alist
Lisp_Object f_Vemacs_copyright;
#define Vemacs_copyright globals.f_Vemacs_copyright
Lisp_Object f_Vemacs_version;
#define Vemacs_version globals.f_Vemacs_version
Lisp_Object f_Vinstallation_directory;
#define Vinstallation_directory globals.f_Vinstallation_directory
Lisp_Object f_Vinvocation_directory;
#define Vinvocation_directory globals.f_Vinvocation_directory
Lisp_Object f_Vinvocation_name;
#define Vinvocation_name globals.f_Vinvocation_name
Lisp_Object f_Vkill_emacs_hook;
#define Vkill_emacs_hook globals.f_Vkill_emacs_hook
Lisp_Object f_Vpath_separator;
#define Vpath_separator globals.f_Vpath_separator
Lisp_Object f_Vreport_emacs_bug_address;
#define Vreport_emacs_bug_address globals.f_Vreport_emacs_bug_address
Lisp_Object f_Vsystem_configuration;
#define Vsystem_configuration globals.f_Vsystem_configuration
Lisp_Object f_Vsystem_configuration_features;
#define Vsystem_configuration_features globals.f_Vsystem_configuration_features
Lisp_Object f_Vsystem_configuration_options;
#define Vsystem_configuration_options globals.f_Vsystem_configuration_options
Lisp_Object f_Vsystem_messages_locale;
#define Vsystem_messages_locale globals.f_Vsystem_messages_locale
Lisp_Object f_Vsystem_time_locale;
#define Vsystem_time_locale globals.f_Vsystem_time_locale
Lisp_Object f_Vsystem_type;
#define Vsystem_type globals.f_Vsystem_type
bool f_inhibit_x_resources;
#define inhibit_x_resources globals.f_inhibit_x_resources
bool f_noninteractive1;
#define noninteractive1 globals.f_noninteractive1
};
extern struct emacs_globals globals;
#ifndef DEFINE_SYMBOLS
extern
#endif
struct Lisp_Symbol lispsym[5];
#define iQfile_name_handler_alist 0
DEFINE_LISP_SYMBOL (Qfile_name_handler_alist)
#define iQkill_emacs 1
DEFINE_LISP_SYMBOL (Qkill_emacs)
#define iQkill_emacs_hook 2
DEFINE_LISP_SYMBOL (Qkill_emacs_hook)
#define iQrisky_local_variable 3
DEFINE_LISP_SYMBOL (Qrisky_local_variable)
#define iQrun_hook_query_error_with_timeout 4
DEFINE_LISP_SYMBOL (Qrun_hook_query_error_with_timeout)
EXFUN (Fdaemon_initialized, 0);
EXFUN (Fdaemonp, 0);
EXFUN (Fdump_emacs, 2);
EXFUN (Finvocation_directory, 0);
EXFUN (Finvocation_name, 0);
_Noreturn EXFUN (Fkill_emacs, 1) ATTRIBUTE_COLD;
#ifdef DEFINE_SYMBOLS
static char const *const defsym_name[] = {
"file-name-handler-alist",
"kill-emacs",
"kill-emacs-hook",
"risky-local-variable",
"run-hook-query-error-with-timeout",
};
#endif
#define Qnil builtin_lisp_symbol (0)
#if DEFINE_NON_NIL_Q_SYMBOL_MACROS
# define Qkill_emacs builtin_lisp_symbol (1)
# define Qkill_emacs_hook builtin_lisp_symbol (2)
# define Qrisky_local_variable builtin_lisp_symbol (3)
# define Qrun_hook_query_error_with_timeout builtin_lisp_symbol (4)
#endif