35

我正在编写有关构建自己的 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
4

8 回答 8

38

仅包括

#include <editline/readline.h>

如果安装了命令行工具,它应该存在。该文件包含 libedit 的“readline wrapper”,还包括历史函数。<editline/history.h>OS X 上不存在包含文件。

我用那个修改测试了你的代码,它编译并运行没有问题。

于 2014-04-05T21:08:58.540 回答
7

使用 OSX 优胜美地。我删除了 #include<editline/history.h>

然后用cc -std=c99 -Wall test.c -ledit -o test

现在工作正常

于 2015-09-28T08:37:25.560 回答
4

我在 El Capitan, Remove 上#include <editline/history.h>,并为我使用cc -std=c99 -Wall test.c -ledit -o test作品。
在输出flad之前添加标志-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
于 2015-12-30T04:39:34.933 回答
3

我在 Ubuntu 14.04 上。

尝试这个:

sudo apt-get install libeditline-dev

并包括这样的:

#include <editline.h>

最后编译如下:

添加-leditline标志

我希望这会有所帮助。

于 2015-03-03T13:47:26.063 回答
2

我在 OSX Mavericks 并删除了对我有用的行:

#include <editline/history.h>
于 2014-04-07T20:39:12.273 回答
1

我从建立你自己的列表开始,遇到了同样的问题。以上答案都不适合我。经过一番研究,我发现 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. build 4061)

现在唯一的问题是,这本书指出了这一点,是 c 代码应该是可移植的,而这不是。下一步是添加预处理器指令,以便它在 linux 上使用 readline,在 macos 上使用 editline。

于 2017-08-26T08:48:22.697 回答
1

那些关注 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”函数的错误。

于 2016-04-19T13:36:43.787 回答
0

在 Debian Buster 10 上,我必须使用以下命令安装软件包:

sudo apt install libeditline-dev 

代替:

#include <editline/readline.h>
#include <editline/history.h>

我刚刚包括:

#include <editline.h>

使用 -leditline 标志运行程序并完美运行。

于 2020-11-19T15:21:00.850 回答