from pypy.rpython.tool import rffi_platform as platform from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace, interp2app from pypy.translator.tool.cbuild import ExternalCompilationInfo # On various platforms, linking only with libreadline is not enough; # we also need to link with some variant of curses or libtermcap. # We follow the logic of CPython below. def try_with_lib(extralibs, **kwds): global most_recent_error # at least on Gentoo Linux, readline.h doesn't compile if stdio.h is not # included before eci = ExternalCompilationInfo( includes = ["stdio.h", "readline/readline.h", "readline/history.h"], libraries = extralibs + ['readline'], ) try: platform.verify_eci(eci) return eci except platform.CompilationError, e: most_recent_error = e return None eci = (try_with_lib([]) or try_with_lib(['ncursesw']) or try_with_lib(['ncurses']) or try_with_lib(['curses']) or try_with_lib(['termcap'], library_dirs=['/usr/lib/termcap'])) if eci is None: raise most_recent_error # ____________________________________________________________ def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) # get a binding to c library functions and define their args and return types # char *readline(char *) c_readline = external('readline', [rffi.CCHARP], rffi.CCHARP) # void rl_initiliaze(void) c_rl_initialize = external('rl_initialize', [], lltype.Void) # void using_history(void) c_using_history = external('using_history', [], lltype.Void) # void add_history(const char *) c_add_history = external('add_history', [rffi.CCHARP], lltype.Void) #------------------------------------------------------------ # special initialization of readline class ReadlineState(object): lastline = "" # XXX possibly temporary hack readlinestate = ReadlineState() def setup_readline(space, w_module): c_using_history() # XXX CPython initializes more stuff here c_rl_initialize() # install sys.__raw_input__, a hook that will be used by raw_input() space.setitem(space.sys.w_dict, space.wrap('__raw_input__'), space.wrap(app_readline_func)) def readline_func(space, prompt): ll_res = c_readline(prompt) if not ll_res: raise OperationError(space.w_EOFError, space.w_None) res = rffi.charp2str(ll_res) if res and res != readlinestate.lastline: readlinestate.lastline = res c_add_history(res) return space.wrap(res) readline_func.unwrap_spec = [ObjSpace, str] app_readline_func = interp2app(readline_func)