#!/usr/bin/env python from __future__ import absolute_import import argparse import logging import sys import os import libghdl import libghdl.thin.errorout_console from . import version from . import lsp from . import vhdl_ls logger = logging.getLogger('ghdl-ls') class LSPConnTrace(object): """Wrapper class to save in and out packets""" def __init__(self, basename, conn): self.conn = conn self.trace_in = open(basename + '.in', 'w') self.trace_out = open(basename + '.out', 'w') def readline(self): res = self.conn.readline() self.trace_in.write(res) return res def read(self, size): res = self.conn.read(size) self.trace_in.write(res) self.trace_in.flush() return res def write(self, out): self.conn.write(out) self.trace_out.write(out) self.trace_out.flush() def rotate_log_files(basename, num): for i in range(num, 0, -1): oldfile = '{}.{}'.format(basename, i - 1) if os.path.isfile(oldfile): os.rename(oldfile, '{}.{}'.format(basename, i)) if os.path.isfile(basename): os.rename(basename, '{}.0'.format(basename)) def main(): parser = argparse.ArgumentParser( description='VHDL Language Protocol Server') parser.add_argument( '--version', '-V', action='version', version='%(prog)s ' + version.__version__) parser.add_argument( '--verbose', '-v', action='count', default=0, help='Show debug output') parser.add_argument( '--log-file', help="Redirect logs to the given file instead of stderr") parser.add_argument( '--trace-file', help="Save rpc data to FILE.in and FILE.out") parser.add_argument( '--input', '-i', help="Read request from file") parser.add_argument( '--disp-config', action='store_true', help="Disp installation configuration and exit") args = parser.parse_args() if args.disp_config: libghdl.thin.errorout_console.Install_Handler() libghdl.disp_config() return # Setup logging if args.verbose >= 2: loglevel = logging.DEBUG elif args.verbose >= 1: loglevel = logging.INFO else: loglevel = logging.ERROR if args.log_file: rotate_log_files(args.log_file, 5) logstream = open(args.log_file, 'w') else: logstream = sys.stderr logging.basicConfig(format='%(asctime)-15s [%(levelname)s] %(message)s', stream=logstream, level=loglevel) if args.verbose != 0: sys.stderr.write('Args: {}\n'.format(sys.argv)) sys.stderr.write('Current directory: {}\n'.format(os.getcwd())) logger.info('Args: %s', sys.argv) logger.info('Current directory is %s', os.getcwd()) # Connection instream = sys.stdin.buffer if args.input is not None: instream = open(args.input, 'rb') conn = lsp.LSPConn(instream, sys.stdout.buffer) trace_file = args.trace_file if trace_file is None: trace_file = os.environ.get('GHDL_LS_TRACE') if trace_file is not None: if args.input is None: rotate_log_files(trace_file + '.in', 5) rotate_log_files(trace_file + '.out', 5) conn = LSPConnTrace(trace_file, conn) else: logger.info('Traces disabled when -i/--input') handler = vhdl_ls.VhdlLanguageServer() try: server = lsp.LanguageProtocolServer(handler, conn) server.run() except Exception: logger.exception('Uncaught error') sys.exit(1)