From 5b89f59f1e31fb669444b340e75370ff9cb683c9 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 23 Aug 2014 16:49:30 +0200 Subject: python2 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- COPYING | 2 +- Makefile | 10 ++-- info/gpp.texinfo | 2 +- src/gpp.py | 148 +++++++++++++++++++++++++++++++++++++------------------ 4 files changed, 108 insertions(+), 54 deletions(-) diff --git a/COPYING b/COPYING index 2820325..ab19927 100644 --- a/COPYING +++ b/COPYING @@ -1,6 +1,6 @@ gpp – Bash based general purpose preprocessor -Copyright © 2013 Mattias Andrée (maandree@member.fsf.org) +Copyright © 2013, 2014 Mattias Andrée (maandree@member.fsf.org) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/Makefile b/Makefile index 440b453..851d2cf 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,8 @@ PREFIX = /usr DATA = /share BIN = /bin PKGNAME = gpp -PY3 = python3 -SHEBANG = /usr$(BIN)/env $(PY3) +PY = python3 +SHEBANG = /usr$(BIN)/env $(PY) COMMAND = gpp LICENSES = $(DATA)/licenses @@ -28,10 +28,10 @@ info: gpp.info makeinfo "$<" info/%.texinfo.install: info/%.texinfo - $(PY3) gpp -s '?' -D GPP=$(COMMAND) < "$<" > "$@" + $(PY) gpp -s '?' -D GPP=$(COMMAND) < "$<" > "$@" gpp: src/gpp.py - VERSION=$(VERSION) SHEBANG="$(SHEBANG)" $(PY3) "$<" -u -u < "$<" > "$@" + VERSION='$(VERSION)' SHEBANG='$(SHEBANG)' $(PY) "$<" < "$<" > "$@" .PHONY: install install: install-core install-doc @@ -67,5 +67,5 @@ uninstall: .PHONY: clean clean: - -rm -f gpp gpp.info + -rm -f gpp gpp.info *.install* info/*.install diff --git a/info/gpp.texinfo b/info/gpp.texinfo index 535a044..2698230 100644 --- a/info/gpp.texinfo +++ b/info/gpp.texinfo @@ -94,7 +94,7 @@ lines. @chapter Invoking Syntax for invoking @command{?{GPP}}: -@command {?{GPP} [options...]} +@command{?{GPP} [options...]} Short options must not be joined and the value for a flag must be in a diff --git a/src/gpp.py b/src/gpp.py index 53e9257..cd3910b 100755 --- a/src/gpp.py +++ b/src/gpp.py @@ -1,9 +1,9 @@ -#!/usr/bin/env python3 #!@{SHEBANG} +# -*- coding: utf-8 -*- ''' gpp – Bash based general purpose preprocessor -Copyright © 2013 Mattias Andrée (maandree@member.fsf.org) +Copyright © 2013, 2014 Mattias Andrée (maandree@member.fsf.org) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,8 +25,21 @@ import sys import shlex from subprocess import Popen, PIPE +if sys.version_info.major < 3: + def bytes(string): + r = bytearray(len(string)) + b = buffer(r) + r[:] = string + return r + +if sys.version_info.major < 3: + def bytelist(string): + return [ord(c) for c in string] +else: + bytelist = list + symbol = '@' -encoding = 'utf-8' +encoding = sys.getdefaultencoding() iterations = 1 input_file = '/dev/stdin' output_file = '/dev/stdout' @@ -63,9 +76,9 @@ for i in range(1, len(args)): print('gpp ' + VERSION) sys.exit(0) elif arg in ('-c', '--copying'): - print('gpp – Bash based general purpose preprocessor') + print('gpp -- Bash based general purpose preprocessor') print('') - print('Copyright © 2013 Mattias Andrée (maandree@member.fsf.org)') + print('Copyright (C) 2013, 2014 Mattias Andrée (maandree@member.fsf.org)') print('') print('This program is free software: you can redistribute it and/or modify') print('it under the terms of the GNU General Public License as published by') @@ -87,6 +100,9 @@ for i in range(1, len(args)): if input_file == '-': input_file = '/dev/stdin' if output_file == '-': output_file = '/dev/stdout' +symbol = bytelist(symbol.encode(encoding)) +symlen = len(symbol) + if iterations < 1: if input_file != output_file: data = None @@ -97,72 +113,98 @@ if iterations < 1: file.flush() sys.exit(0) +def linesplit(bs): + rc = [] + elem = [] + for b in bs: + if b == 10: + rc.append(elem) + elem = [] + else: + elem.append(b) + rc.append(elem) + return rc + +def linejoin(bss): + rc = [] + if len(bss) > 0: + rc += bss[0] + for bs in bss[1:]: + rc.append(10) + rc += bs + return rc + data = None with open(input_file, 'rb') as file: - data = file.read().decode(encoding, 'error').split('\n') + data = file.read() +data = linesplit(bytelist(data)) if unshebang == 1: - if data[0][:2] == '#!': - data[0] = '' + if (len(data[0]) >= 2) and (data[0][0] == ord('#')) and (data[0][1] == ord('!')): + data[0] = [] if unshebang >= 2: - if data[0][:2] == '#!': + if (len(data[0]) >= 2) and (data[0][0] == ord('#')) and (data[0][1] == ord('!')): data[0] = data[1] - data[1] = '' + data[1] = [] def pp(line): - rc = '' + rc = [] symb = False brackets = 0 esc = False dollar = False quote = [] - for c in line: + for i in range(len(line)): + c = line[i] if brackets > 0: if esc: esc = False - elif (c == ')') or (c == '}'): + elif (c in (ord(')'), ord('}'))): brackets -= 1 if brackets == 0: - rc += c + '"\'' + rc.append(c) + rc.append(ord('"')) + rc.append(ord('\'')) continue - elif (c == '(') or (c == '{'): + elif (c in (ord('('), ord('{'))): brackets += 1 - elif c == '\\': + elif c == ord('\\'): esc = True - rc += c + rc.append(c) elif symb: symb = False - if (c == '(') or (c == '{'): + if (c in (ord('('), ord('{'))): brackets += 1 - rc += '\'"$' + c - else: - rc += c - elif c == symbol: + rc.append(ord('\'')) + rc.append(ord('"')) + rc.append(ord('$')) + rc.append(c) + elif line[i : i + symlen] == symbol: symb = True elif len(quote) > 0: if esc: esc = False elif dollar: dollar = False - if c == '(': - quote.append(')') - elif c == '{': - quote.append('}') + if c == ord('('): + quote.append(ord(')')) + elif c == ord('{'): + quote.append(ord('}')) elif c == quote[-1]: quote[:] = quote[:-1] - elif (quote[-1] in ')}') and (c in '\'"`'): + elif (quote[-1] in (ord(')'), ord('}'))) and (c in (ord('"'), ord('\''), ord('`'))): quote.append(c) - elif (c == '\\') and (quote[-1] != "'"): + elif (c == ord('\\')) and (quote[-1] != ord('\'')): esc = True - elif c == '$': + elif c == ord('$'): dollar = True - rc += c - elif (c == '"') or (c == "'") or (c == '`'): + rc.append(c) + elif c in (ord('"'), ord('\''), ord('`')): quote.append(c) - rc += c + rc.append(c) else: - rc += c + rc.append(c) return rc for _ in range(iterations): @@ -171,42 +213,54 @@ for _ in range(iterations): for lineno in range(len(data)): line = data[lineno] - if line.startswith(symbol + '<'): - bashed.append(line[2:]) - entered = True - elif line.startswith(symbol + '>'): + if (len(line) > symlen) and (line[:symlen] == symbol) and (line[symlen] in (ord('<'), ord('>'))): bashed.append(line[2:]) - entered = False + entered = line[symlen] == ord('<') elif entered: bashed.append(line) else: - line = '\'%s\'' % line.replace('\'', '\'\\\'\'') - bashed.append('echo $\'\\e%i\\e\'%s' % (lineno, pp(line))) + buf = [] + for c in line: + if c == ord('\''): + buf.append(c) + buf.append(ord('\\')) + buf.append(c) + buf.append(c) + else: + buf.append(c) + line = [ord('\'')] + buf + [ord('\'')] + buf = bytelist(('echo $\'\\e%i\\e\'' % lineno).encode()) + bashed.append(buf + pp(line)) - bashed = '\n'.join(bashed).encode(encoding) + bashed = bytes(linejoin(bashed)) bash = Popen(["bash"], stdin = PIPE, stdout = PIPE, stderr = sys.stderr) bashed = bash.communicate(bashed)[0] if bash.returncode != 0: sys.exit(bash.returncode) - bashed = bashed.decode(encoding, 'error').split('\n') + bashed = linesplit(bytelist(bashed)) data = [] lineno = -1 for line in bashed: no = -1 - if line.startswith('\033'): - no = int(line[1:].split('\033')[0]) - line = '\033'.join(line[1:].split('\033')[1:]) + if (len(line) > 0) and (line[0] == 0o33): + no = 0 + for i in range(1, len(line)): + if line[i] == 0o33: + line = line[i + 1:] + break + no = no * 10 + (line[i] - ord('0')) if no > lineno: while no != lineno + 1: - data.append('') + data.append([]) lineno += 1 data.append(line) lineno += 1 +data = bytes(linejoin(data)) with open(output_file, 'wb') as file: - file.write('\n'.join(data).encode(encoding)) + file.write(data) file.flush() -- cgit v1.2.3-70-g09d2