29 import codecs, os, sys
30 from gettext
import gettext
as _
69 def __init__(self, release_ver, fileformat_ver):
109 raise ValueError,
"Invalid format token: '%s'" % fmt
125 while fmt.endswith(
'\n'):
126 if not s.endswith(
'\n'):
139 fmttok = fmt.split(
' ')
141 if len(stok) != len(fmttok):
144 return [
parse_token(st, ft)
for (st, ft)
in zip(stok, fmttok)]
150 if line.endswith(
'\r\n'):
151 yield line[:-2] +
'\n'
171 def read_file(f, name, log, load_symbol, load_pixmap,
172 force_boundingbox =
False):
173 f = codecs.iterdecode(f,
'utf-8')
176 def lineno_incrementor(f):
180 f = lineno_incrementor(f)
183 object_lists_save = []
201 if objtype == OBJ_LINE:
202 data =
read_line(line, origin, format, log)
204 ob = rev.add_object(data)
205 elif objtype == OBJ_NET:
206 data =
read_net(line, origin, format, log)
208 ob = rev.add_object(data)
209 elif objtype == OBJ_BUS:
210 data =
read_bus(line, origin, format, log)
212 ob = rev.add_object(data)
213 elif objtype == OBJ_BOX:
214 data =
read_box(line, origin, format, log)
216 ob = rev.add_object(data)
217 elif objtype == OBJ_PICTURE:
218 data =
read_picture(line, f, origin, format, log, load_pixmap)
220 ob = rev.add_object(data)
221 elif objtype == OBJ_CIRCLE:
224 ob = rev.add_object(data)
225 elif objtype == OBJ_COMPLEX:
226 data =
read_complex(line, origin, format, log, load_symbol)
228 ob = rev.add_object(data)
229 elif objtype == OBJ_TEXT:
230 data =
read_text(line, f, origin, format, log)
232 ob = rev.add_object(data)
233 elif objtype == OBJ_PATH:
234 data =
read_path(line, f, origin, format, log)
236 ob = rev.add_object(data)
237 elif objtype == OBJ_PIN:
238 data =
read_pin(line, origin, format, log)
240 ob = rev.add_object(data)
241 elif objtype == OBJ_ARC:
242 data =
read_arc(line, origin, format, log)
244 ob = rev.add_object(data)
245 elif objtype == STARTATTACH_ATTR:
247 log.error(_(
"unexpected attribute list start marker"))
251 log.error(_(
"can't attach attributes to this object type"))
257 except StopIteration:
258 log.error(_(
"unterminated attribute list"))
264 if line[0] == ENDATTACH_ATTR:
267 if line[0] != OBJ_TEXT:
269 _(
"tried to attach a non-text item as an attribute"))
272 attrib =
read_text(line, f, origin, format, log)
273 if attrib
is not None:
274 rev.relocate_object(rev.add_object(attrib), ob,
None)
277 elif objtype == START_EMBEDDED:
279 log.error(_(
"unexpected embedded symbol start marker"))
281 component_data = rev.get_object_data(ob)
283 log.error(_(
"embedded symbol start marker following "
284 "non-component object"))
286 if not component_data.symbol.embedded:
287 log.error(_(
"embedded symbol start marker following "
288 "component with non-embedded symbol"))
290 if component_data.symbol.prim_objs
is not None:
291 log.error(_(
"embedded symbol start marker following "
294 object_lists_save.append((rev, ob, origin))
296 component_data.symbol.prim_objs = rev
297 origin = origin[0] + component_data.x, origin[1] + component_data.y
298 elif objtype == END_EMBEDDED:
299 if not object_lists_save:
300 log.error(_(
"unexpected embedded symbol end marker"))
302 rev, ob, origin = object_lists_save.pop()
303 elif objtype == ENDATTACH_ATTR:
304 log.error(_(
"unexpected attribute list end marker"))
305 elif objtype == INFO_FONT:
308 elif objtype == COMMENT:
311 elif objtype == VERSION_CHAR:
313 objtype, release_ver, fileformat_ver = \
314 sscanf(line,
"%c %u %u\n")
317 objtype, release_ver =
sscanf(line,
"%c %u\n")
319 log.error(_(
"failed to parse version string"))
323 assert objtype == VERSION_CHAR
327 if release_ver <= VERSION_20030921:
330 if fileformat_ver == 0:
331 log.warn(_(
"Read an old format sym/sch file! "
332 "Please run g[sym|sch]update on this file"))
334 format =
FileFormat(release_ver, fileformat_ver)
336 log.error(_(
"read garbage"))
338 for ob
in rev.get_objects():
339 data = rev.get_object_data(ob)
341 or not data.symbol.embedded:
343 if data.symbol.prim_objs
is None:
344 log.error(_(
"embedded symbol is missing"))
351 attached_name, attached_value = \
353 visibility[attached_name] = attached.visibility
355 inherited_name, inherited_value = \
357 if inherited_name
in visibility:
358 inherited.visibility = visibility[inherited_name]
360 if not format.enhanced_pinbus_format:
376 log.error(_(
"file is lacking pin orientation information"))
386 if not format.supports_linefill_attributes:
387 type, x1, y1, radius, color =
sscanf(buf,
"%c %d %d %d %d\n")
401 type, x1, y1, radius, color, circle_width, \
402 circle_end, circle_type, circle_length, circle_space, \
403 circle_fill, fill_width, angle1, pitch1, angle2, pitch2 =
sscanf(
404 buf,
"%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n")
406 log.error(_(
"failed to parse circle object"))
409 if type != OBJ_CIRCLE:
413 log.warn(_(
"circle has radius zero"))
415 log.warn(_(
"circle has negative radius (%d), setting to 0") % radius)
418 if color < 0
or color > MAX_COLORS:
419 log.warn(_(
"circle has invalid color (%d), setting to %d")
420 % (color, DEFAULT_COLOR))
421 color = DEFAULT_COLOR
429 width = circle_width,
430 cap_style = circle_end,
431 dash_style = circle_type,
432 dash_length = circle_length,
433 dash_space = circle_space),
449 def read_arc(buf, (origin_x, origin_y), format, log):
451 if not format.supports_linefill_attributes:
452 type, x1, y1, radius, start_angle, sweep_angle, color =
sscanf(
453 buf,
"%c %d %d %d %d %d %d\n")
460 type, x1, y1, radius, start_angle, sweep_angle, color, \
461 arc_width, arc_end, arc_type, arc_length, arc_space =
sscanf(
462 buf,
"%c %d %d %d %d %d %d %d %d %d %d %d\n")
464 log.error(_(
"failed to parse arc object"))
471 log.warn(_(
"arc has radius zero"))
473 log.warn(_(
"arc has negative radius (%d), setting to 0") % radius)
476 if color < 0
or color > MAX_COLORS:
477 log.warn(_(
"arc has invalid color (%d), setting to %d")
478 % (color, DEFAULT_COLOR))
479 color = DEFAULT_COLOR
485 startangle = start_angle,
486 sweepangle = sweep_angle,
491 dash_style = arc_type,
492 dash_length = arc_length,
493 dash_space = arc_space))
500 def read_box(buf, (origin_x, origin_y), format, log):
502 if not format.supports_linefill_attributes:
503 type, x1, y1, width, height, color =
sscanf(
504 buf,
"%c %d %d %d %d %d\n")
518 type, x1, y1, width, height, color, \
519 box_width, box_end, box_type, box_length, box_space, \
520 box_filling, fill_width, angle1, pitch1, angle2, pitch2 =
sscanf(
521 buf,
"%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n")
523 log.error(_(
"failed to parse box object"))
529 if width == 0
or height == 0:
530 log.warn(_(
"box has width/height zero"))
532 if color < 0
or color > MAX_COLORS:
533 log.warn(_(
"box has invalid color (%d), setting to %d")
534 % (color, DEFAULT_COLOR))
535 color = DEFAULT_COLOR
552 dash_style = box_type,
553 dash_length = box_length,
554 dash_space = box_space),
568 def read_bus(buf, (origin_x, origin_y), format, log):
570 if not format.enhanced_pinbus_format:
571 type, x1, y1, x2, y2, color =
sscanf(
572 buf,
"%c %d %d %d %d %d\n")
575 type, x1, y1, x2, y2, color, ripper_dir =
sscanf(
576 buf,
"%c %d %d %d %d %d %d\n")
578 log.error(_(
"failed to parse bus object"))
584 if x1 == x2
and y1 == y2:
585 log.warn(_(
"bus has length zero"))
587 if color < 0
or color > MAX_COLORS:
588 log.warn(_(
"bus has invalid color (%d), setting to %d")
589 % (color, DEFAULT_COLOR))
590 color = DEFAULT_COLOR
592 if ripper_dir < -1
or ripper_dir > 1:
593 log.warn(_(
"bus has invalid ripper direction (%d)") % ripper_dir)
617 type, x1, y1, selectable, angle, mirror, basename =
sscanf(
618 buf,
"%c %d %d %d %d %d %s\n")
620 log.error(_(
"failed to parse complex object"))
623 if type != OBJ_COMPLEX:
626 if angle
not in [0, 90, 180, 270]:
627 log.warn(_(
"component has invalid angle (%d), setting to 0") % angle)
630 if mirror != 0
and mirror != 1:
631 log.warn(_(
"component has invalid mirror flag (%d), "
632 "setting to 0") % mirror)
637 if basename.startswith(
'EMBEDDED'):
640 symbol = load_symbol(basename,
False)
641 assert not symbol.embedded
646 selectable = selectable,
658 if not format.supports_linefill_attributes:
659 type, x1, y1, x2, y2, color =
sscanf(buf,
"%c %d %d %d %d %d\n")
666 type, x1, y1, x2, y2, color, \
667 line_width, line_end, line_type, line_length, line_space =
sscanf(
668 buf,
"%c %d %d %d %d %d %d %d %d %d %d\n")
670 log.error(_(
"failed to parse line object"))
678 if x1 == x2
and y1 == y2:
679 log.warn(_(
"line has length zero"))
681 if color < 0
or color > MAX_COLORS:
682 log.warn(_(
"line has invalid color (%d), setting to %d")
683 % (color, DEFAULT_COLOR))
684 color = DEFAULT_COLOR
694 cap_style = line_end,
695 dash_style = line_type,
696 dash_length = line_length,
697 dash_space = line_space))
704 def read_net(buf, (origin_x, origin_y), format, log):
706 type, x1, y1, x2, y2, color =
sscanf(buf,
"%c %d %d %d %d %d\n")
708 log.error(_(
"failed to parse net object"))
714 if x1 == x2
and y1 == y2:
715 log.warn(_(
"net has length zero"))
717 if color < 0
or color > MAX_COLORS:
718 log.warn(_(
"net has invalid color (%d), setting to %d")
719 % (color, DEFAULT_COLOR))
720 color = DEFAULT_COLOR
743 def read_path(first_line, f, (origin_x, origin_y), format, log):
746 line_width, line_end, line_type, line_length, line_space, \
747 fill_type, fill_width, angle1, pitch1, angle2, pitch2, \
749 first_line,
"%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n")
751 log.error(_(
"failed to parse path object"))
758 if color < 0
or color > MAX_COLORS:
759 log.warn(_(
"path has invalid color (%d), setting to %d")
760 % (color, DEFAULT_COLOR))
761 color = DEFAULT_COLOR
764 for i
in xrange(0, num_lines):
767 except StopIteration:
768 log.error(_(
"unexpected end of file after %d lines "
769 "while reading path") % i)
774 if pathstr.endswith(
'\n'):
775 pathstr = pathstr[:-1]
778 pathdata = pathstr.encode(
'utf-8'),
782 cap_style = line_end,
783 dash_style = line_type,
784 dash_length = line_length,
785 dash_space = line_space),
807 def read_picture(first_line, f, (origin_x, origin_y), format, log,
810 type, x1, y1, width, height, angle, mirrored, embedded =
sscanf(
811 first_line,
"%c %d %d %d %d %d %d %d\n")
813 log.error(_(
"failed to parse picture definition"))
816 if type != OBJ_PICTURE:
819 if width == 0
or height == 0:
820 log.warn(_(
"picture has width/height zero"))
822 if mirrored != 0
and mirrored != 1:
823 log.warn(_(
"picture has wrong 'mirrored' parameter (%d), "
824 "setting to 0") % mirrored)
827 if angle
not in [0, 90, 180, 270]:
828 log.warn(_(
"picture has unsupported angle (%d), setting to 0") % angle)
833 except StopIteration:
834 log.error(_(
"unexpected end of file while reading picture file name"))
837 if filename.endswith(
'\n'):
838 filename = filename[:-1]
842 log.warn(_(
"image has no filename"))
847 log.warn(_(
"picture has wrong 'embedded' parameter (%d), "
848 "setting to not embedded") % embedded)
849 pixmap = load_pixmap(filename,
False)
850 assert not pixmap.embedded
857 log.error(_(
"failed to load image from embedded data: %s")
875 def read_pin(buf, (origin_x, origin_y), format, log):
877 if not format.enhanced_pinbus_format:
878 type, x1, y1, x2, y2, color =
sscanf(buf,
"%c %d %d %d %d %d\n")
882 type, x1, y1, x2, y2, color, pin_type, whichend =
sscanf(
883 buf,
"%c %d %d %d %d %d %d %d\n")
885 log.error(_(
"failed to parse pin object"))
892 log.warn(_(
"pin does not have the whichone field set--"
893 "verify and correct manually!"))
894 elif whichend < -1
or whichend > 1:
895 log.warn(_(
"pin has invalid whichend (%d), "
896 "setting to first end") % whichend)
899 if color < 0
or color > MAX_COLORS:
900 log.warn(_(
"pin has invalid color (%d), setting to %d")
901 % (color, DEFAULT_COLOR))
902 color = DEFAULT_COLOR
909 log.warn(_(
"pin has invalid type (%d), setting to 0") % pin_type)
915 x1, y1, x2, y2 = x2, y2, x1, y1
926 is_inverted = is_inverted)
939 def read_text(first_line, f, (origin_x, origin_y), format, log):
941 if format.supports_multiline_text:
942 type, x, y, color, size, visibility, show_name_value, angle, \
943 alignment, num_lines =
sscanf(
944 first_line,
"%c %d %d %d %d %d %d %d %d %d\n")
945 elif not format.supports_text_alignment:
946 type, x, y, color, size, visibility, show_name_value, angle = \
947 sscanf(first_line,
"%c %d %d %d %d %d %d %d\n")
948 alignment = LOWER_LEFT
951 type, x, y, color, size, visibility, show_name_value, angle, \
953 first_line,
"%c %d %d %d %d %d %d %d %d\n")
956 log.error(_(
"failed to parse text object"))
963 log.warn(_(
"text has size zero"))
965 if angle
not in [0, 90, 180, 270]:
966 log.warn(_(
"text has unsupported angle (%d), setting to 0") % angle)
969 if alignment
not in [LOWER_LEFT, MIDDLE_LEFT, UPPER_LEFT,
970 LOWER_MIDDLE, MIDDLE_MIDDLE, UPPER_MIDDLE,
971 LOWER_RIGHT, MIDDLE_RIGHT, UPPER_RIGHT]:
972 log.warn(_(
"text has unsupported alignment (%d), "
973 "setting to LOWER_LEFT") % alignment)
974 alignment = LOWER_LEFT
976 if color < 0
or color > MAX_COLORS:
977 log.warn(_(
"text has invalid color (%d), setting to %d")
978 % (color, DEFAULT_COLOR))
979 color = DEFAULT_COLOR
982 log.error(_(
"text has invalid number of lines (%d)") % num_lines)
985 for i
in xrange(0, num_lines):
988 except StopIteration:
989 log.error(_(
"unexpected end of file after %d lines of text") % i)
994 if text.endswith(
'\n'):
997 tmp = text.replace(
'\\\\',
'')
998 if tmp.count(
'\\_') % 2:
999 log.warn(_(
"mismatched overbar markers"))
1000 if '\\' in tmp.replace(
'\\_',
''):
1001 log.warn(_(
"stray backslash character(s)"))
1008 visibility = visibility,
1009 show_name_value = show_name_value,
1011 alignment = alignment,
1012 text = text.encode(
'utf-8'))
def read_line
Read a line object from a string in gEDA format.
def read_complex
Read a component object from a string in gEDA format.
Reading and writing base64-encoded data.
Attribute parsing and lookup.
Reading schematic/symbol files.
Schematic net segment, bus segment, or pin.
def read_arc
Read an arc object from a string in gEDA format.
Raised when reading invalid or unterminated base64-encoded data.
def find_attached_attribs
Return the attributes directly attached to a net or component.
High-level revision proxy class.
def read_path
Read a path object from a string and a file in gEDA format.
def find_inherited_attribs
Return the attributes inherited by a component via its symbol.
def parse_token
Helper function for sscanf.
def read_net
Read a net object from a string in gEDA format.
def decode
Read a string in base64 representation from a file.
High-level object proxy class.
def pin_update_whichend
Guess the orientation of pins.
def read_box
Read a box object from a string in gEDA format.
def read_text
Read a text object from a string and a file in gEDA format.
def read_circle
Read a circle object from a string in gEDA format.
Schematic text or attribute.
High-level proxy classes for the storage backend.
A particular state of the contents of a file.
def read_bus
Read a bus object from a string in gEDA format.
Referenced symbols and pixmaps.
def read_pin
Read a pin object from a string in gEDA format.
def strip_carriage_return
Replace "\r\n" line endings with "\n" line endings.
def read_file
Read a symbol or schematic file in libgeda format from a file object.
def sscanf
Parse a string of space-separated values.
def parse_string
Parse an attribute string of the form name=value into its name and value parts.
def read_picture
Read a picture object from a string and a file in gEDA format.