commit f1b59fb58004653c7c58c1735112f318cd16f678
parent 58c8d34fa4a368d94b4c5544d5cde18281af2364
Author: quantumish <freifeld.david@gmail.com>
Date: Mon, 19 Jun 2023 19:06:02 -0700
Proper proof of concept
Diffstat:
1 file changed, 105 insertions(+), 6 deletions(-)
diff --git a/cpreprocessor/__init__.py b/cpreprocessor/__init__.py
@@ -3,6 +3,106 @@ import encodings
from encodings import utf_8
import io
+from dataclasses import dataclass
+import sys
+from collections import namedtuple
+import re
+
+a = """
+#define TESTING 1
+
+def myfunc():
+ return TESTING
+
+#ifdef TESTING
+def debug_func():
+ print("whee")
+ if TESTING:
+ print("whoo")
+#endif
+
+"""
+
+
+def handle_define(tokens, state):
+ if len(tokens) == 1:
+ print("Error: bare #define", file=sys.stderr)
+ exit(1)
+ if len(tokens) > 2:
+ state.defs[tokens[1]] = " ".join(tokens[2:])
+ else:
+ state.defs[tokens[1]] = ""
+
+def handle_ifdef(tokens, state):
+ if len(tokens) == 1:
+ print("Error: bare #ifdef", file=sys.stderr)
+ exit(1)
+
+ if tokens[1] not in state.defs:
+ state.skip = True
+
+
+def handle_endif(tokens, state):
+ skip = False
+
+Directive = namedtuple("Directive", "name handler")
+
+handlers = [
+ Directive("#define", handle_define),
+ # Directive("#ifdef", handle_ifdef),
+ Directive("#endif", handle_endif)
+ # Directive("#ifndef", handle_ifndef)
+]
+
+def try_handle_directive(tokens, state):
+ if len(tokens) == 0: return False
+ for directive in handlers:
+ if tokens[0] == directive.name:
+ directive.handler(tokens, state)
+ del[state.lines[state.i]]
+ return True
+ return False
+
+@dataclass
+class State:
+ defs: dict
+ skip: bool
+ lines: list
+ i: int
+
+ def __init__(self, lines):
+ self.defs = {}
+ self.skip = False
+ self.lines = lines
+ self.i = 0
+
+def preprocess(code):
+ lines = code.split("\n")
+ state = State(lines)
+ while state.i < len(lines):
+ tokens = re.split("(?<=\S)\s+", state.lines[state.i])
+
+ if len(tokens) == 2 and tokens[0] == "#ifdef":
+ handle_ifdef(tokens, state)
+ del[state.lines[state.i]]
+ continue
+
+ for j in range(len(tokens)):
+ for definition in state.defs: # GROSS
+ tokens[j] = tokens[j].replace(definition, state.defs[definition])
+
+ if try_handle_directive(tokens, state):
+ continue
+
+ if state.skip:
+ del state.lines[state.i]
+ continue
+
+ state.lines[state.i] = " ".join(tokens)
+ state.i += 1
+
+ return "\n".join(lines)
+
def encode(input_string):
print(encoded_bytes)
out = (input_string+"a").encode()
@@ -17,14 +117,12 @@ def decode(encoded_bytes):
class IncrementalDecoder(utf_8.IncrementalDecoder):
def decode(self, inp, final=False):
- if inp != b"":
- # NOTE: buffer MUST start with '\n'
- self.buffer += b'\nprint("hi")'
+ self.buffer += inp
if final:
buff = self.buffer
self.buffer = b""
return super(IncrementalDecoder, self,).decode(
- buff, final=True
+ preprocess(buff.decode()).encode(), final=True
)
else:
return ""
@@ -37,10 +135,11 @@ class StreamReader(utf_8.StreamReader):
def custom_search_function(encoding_name):
- if encoding_name != "cprepross": return None
+ # print(encoding_name)
+ if encoding_name != "c_preprocessor": return None
utf8=encodings.search_function('utf8')
return codecs.CodecInfo(
- name='cprepross',
+ name='c_preprocessor',
encode = encode,
decode = decode,
incrementalencoder=utf8.incrementalencoder,