我正在研究这个关于构建你自己的 LISP 的教程(http://www.buildyourownlisp.com/chapter4_interactive_prompt),由于某种原因,当我尝试编译时,我得到了这个:
REPL.c:4:10: fatal error: 'editline/readline.h' file not found
#include <editline/history.h>
^
1 error generated.
我已经安装了 macOS 开发者工具,brew 显示 readline 已安装,但当我尝试brew install editline 时它不知道该怎么做。
这是我的代码:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <editline/readline.h>
4 #include <editline/history.h>
5
6 int main(int argc, char** argv) {
7
8 /* version/exit info */
9 puts("Edward Version 0.0.1");
10 puts("Press Ctrl+c to Exit\n");
11
12 /* endless loop for main REPL */
13 while (1) {
14 /* output prompt and read line */
15 char* input = readline("lispy> ");
16
17 /* put input in history */
18 add_history(input);
19
20 /* Echo input back */
21 printf("No you're a %s\n", input);
22
23 /* free input */
24 free(input);
25 }
26 return 0;
27 }
这显然是非常基本的,但我真的很想让这个项目滚动起来,所以我希望我能弄清楚这一点。这就是我用来编译的:
cc -std=c99 -Wall REPL.c -ledit -o REPL
仅包括
#include <editline/readline.h>
如果安装了命令行工具,它应该存在。该文件包含 libedit 的“readline 包装器”,还包括历史功能。 OS X 上不存在包含文件
<editline/history.h>
。
我用该修改测试了你的代码,它编译并运行没有问题。
使用 OSX Yosemite。我删除了
#include<editline/history.h>
然后使用
cc -std=c99 -Wall test.c -ledit -o test
现在工作正常
我在 El Capitan 上, 删除
#include <editline/history.h>
,
并使用 cc -std=c99 -Wall test.c -ledit -o test
对我有用。
-ledit
,这是一个链接过程,允许编译器直接在程序中嵌入对editline的调用。或者,您会收到以下错误消息,
Undefined symbols for architecture x86_64:
"_add_history", referenced from:
_main in prompt-086f90.o
"_readline", referenced from:
_main in prompt-086f90.o
ld: symbol(s) not found for architecture x86_64
我使用的是 Ubuntu 14.04。
试试这个:
sudo apt-get install libeditline-dev
并包括这样的内容:
#include <editline.h>
最终编译如下:
在标志中添加
-leditline
我希望这能有所帮助。
我在 OSX Mavericks 上,删除这条线对我有用:
#include <editline/history.h>
针对那些关注 FreeBSD 的人的解决方案(也可能适用于其他 Unices):
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
...
然后运行:
$ cc test.c -Wall -std=c99 -lreadline -o test
在编译步骤中如果没有“-lreadline”,它就不会被链接,并且您将收到有关“readline”函数的未定义引用的错误。
在 Debian Buster 10 上,我必须使用以下命令安装软件包:
sudo apt install libeditline-dev
代替:
#include <editline/readline.h>
#include <editline/history.h>
我刚刚包括:
#include <editline.h>
使用 -leditline 标志运行程序并完美运行。
如果您使用的是 ubuntu,请添加 editline 库
sudo apt-get install libtedit-dev
我开始使用 Build Your Own Lisp 并遇到了同样的问题。 上述答案都不适合我。 经过一番研究,我发现 macOs 没有提供 readline 函数的 gnu readline 库,不同版本的 MacOs 使用名为 editline 的库提供 readline 模拟。开始...
man editline
#include <histedit.h>
好的,editline 为您提供了一些行输入和历史记录的结构, 以及对它们进行操作的函数。首先,您必须实例化这些结构。 editline 的文档不是很有帮助,因为它不包含任何示例。 Apple 提供了头文件,这会有所帮助。 http://www.opensource.apple.com/source/libedit/libedit-13/src/histedit.h
我对此很陌生,但对我来说仍然很困惑。有一些版本的 libedit 源代码可以作为 debian 包提供。幸运的是,比我更聪明的人已经深入研究并使用 lbedit 实现了命令行。他的代码在这里:https://www.cs.utah.edu/~bigler/code/libedit.html。 我采用了 Bigler 先生的代码以及 Build your own list 中的代码,并将它们放在一起得到了这个。
/* repl-macos.c
* Repl code example from builyourownlisp.com
* Modified by NB aug 2017
* Code example for editline from
* www.cs.utah.edu/~bigler/code/libedit.html
*/
#include <stdio.h>
#include <string.h>
#include <histedit.h>
char* prompt(EditLine *e){
return "lispy> ";
}
int main(int argc, char** argv){
EditLine *el; // Line editor state
History *herstory; // the rest is history
// Temp Variables
int count;
const char *usrin;
int keepreading = 1;
HistEvent ev;
// Initialize the editline state
el = el_init(argv[0], stdin, stdout, stderr);
el_set(el, EL_PROMPT, &prompt);
el_set(el, EL_EDITOR, "emacs");
// Initialize history
herstory = history_init();
if(!herstory){
fprintf(stderr, "Couldn't initialize history\n");
return 1;
}
//set history size
history(herstory, &ev, H_SETSIZE, 800);
// Set up the call back functions for history functionality
el_set(el, EL_HIST, history, herstory);
puts("Begin moLisp interpreter");
puts("Type 'exit' at prompt to exit");
while(keepreading){
usrin = el_gets(el, &count);
// add the command to the history, and echo it back to the user
if(count > 0){
history(herstory, &ev, H_ENTER, usrin);
if(strcmp(usrin, "exit\n"))
printf("No, You're a %s", usrin);
else{
puts("bye");
--keepreading;
}
}
}
// Clean up memory
// by freeing the memory pointed to within the structs that
// libedit has created.
history_end(herstory);
el_end(el);
return 0;
}
注意:所使用的结构体的实例化发生在外部 while 循环,以及释放这些结构正在使用的内存的函数也是如此。因此,我添加了退出命令,否则如果退出 while 循环的唯一方法是中断程序,我认为存在内存泄漏。编译:
gcc repl-macos.c -ledit -Wall -o repl-edit
-ledit 需要链接编辑行
如果有任何相关性,我正在使用 macOs 10.4.11 这是我的编译器,输出
gcc --version
powerpc-apple-darwin8-gcc-4.0.0 (GCC) 4.0.0 20041026(Apple Computer, Inc. 版本 4061)
现在唯一的问题是,这本书指出了这一点 c 代码应该是可移植的,但事实并非如此。下一步是添加预处理器指令,以便它在 Linux 上使用 readline,在 Macos 上使用 editline。