From 6b672e98ff36b25e289c0d9e2ccc28337baa3c27 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Fri, 18 Nov 2016 08:02:22 -0500 Subject: Add support for IF (Include File) rs274x command --- gerber/rs274x.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'gerber') diff --git a/gerber/rs274x.py b/gerber/rs274x.py index 5d64597..ff8addd 100644 --- a/gerber/rs274x.py +++ b/gerber/rs274x.py @@ -20,6 +20,7 @@ import copy import json +import os import re import sys @@ -146,7 +147,7 @@ class GerberFile(CamFile): return ((min_x, max_x), (min_y, max_y)) def write(self, filename, settings=None): - """ Write data out to a gerber file + """ Write data out to a gerber file. """ with open(filename, 'w') as f: for statement in self.statements: @@ -193,6 +194,9 @@ class GerberParser(object): AD_POLY = r"(?PAD)D(?P\d+)(?PP)[,](?P[^,%]*)" AD_MACRO = r"(?PAD)D(?P\d+)(?P{name})[,]?(?P[^,%]*)".format(name=NAME) AM = r"(?PAM)(?P{name})\*(?P[^%]*)".format(name=NAME) + # Include File + IF = r"(?PIF)(?P.*)" + # begin deprecated AS = r"(?PAS)(?P(AXBY)|(AYBX))" @@ -208,7 +212,7 @@ class GerberParser(object): # end deprecated PARAMS = (FS, MO, LP, AD_CIRCLE, AD_RECT, AD_OBROUND, AD_POLY, - AD_MACRO, AM, AS, IN, IP, IR, MI, OF, SF, LN) + AD_MACRO, AM, AS, IF, IN, IP, IR, MI, OF, SF, LN) PARAM_STMT = [re.compile(r"%?{0}\*%?".format(p)) for p in PARAMS] @@ -230,7 +234,11 @@ class GerberParser(object): REGION_MODE_STMT = re.compile(r'(?PG3[67])\*') QUAD_MODE_STMT = re.compile(r'(?PG7[45])\*') + # Keep include loop from crashing us + INCLUDE_FILE_RECURSION_LIMIT = 10 + def __init__(self): + self.filename = None self.settings = FileSettings() self.statements = [] self.primitives = [] @@ -248,13 +256,16 @@ class GerberParser(object): self.region_mode = 'off' self.quadrant_mode = 'multi-quadrant' self.step_and_repeat = (1, 1, 0, 0) + self._recursion_depth = 0 def parse(self, filename): + self.filename = filename with open(filename, "rU") as fp: data = fp.read() return self.parse_raw(data, filename) def parse_raw(self, data, filename=None): + self.filename = filename for stmt in self._parse(self._split_commands(data)): self.evaluate(stmt) self.statements.append(stmt) @@ -371,6 +382,17 @@ class GerberParser(object): yield stmt elif param["param"] == "OF": yield OFParamStmt.from_dict(param) + elif param["param"] == "IF": + # Don't crash on include loop + if self._recursion_depth < self.INCLUDE_FILE_RECURSION_LIMIT: + self._recursion_depth += 1 + with open(os.path.join(os.path.dirname(self.filename), param["filename"]), 'r') as f: + inc_data = f.read() + for stmt in self._parse(self._split_commands(inc_data)): + yield stmt + self._recursion_depth -= 1 + else: + raise IOError("Include file nesting depth limit exceeded.") elif param["param"] == "IN": yield INParamStmt.from_dict(param) elif param["param"] == "LN": -- cgit