--- /dev/null
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.util.*;
+
+/** NOT YET FINALIZED: A description (specification) of a ship */
+public class ShipDescription implements Iterable<DockDescription> {
+
+ private String name;
+ private LinkedHashMap<String,DockDescription> docks = new LinkedHashMap<String,DockDescription>();
+ private HashMap<String,String> sections = new HashMap<String,String>();
+ private HashMap<String,Constant> constants = new HashMap<String,Constant>();
+
+ public String getName() { return name; }
+ public String getSection(String sectionName) { return sections.get(sectionName); }
+ public DockDescription getDockDescription(String name) { return docks.get(name); }
+ public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
+
+ public ShipDescription(String name, BufferedReader r) throws IOException {
+ this.name = name;
+ String sectionName = null;
+ StringBuffer sb = new StringBuffer();
+ while(true) {
+ String s = r.readLine();
+ if (s==null || s.startsWith("==")) {
+ if (sectionName != null) sections.put(sectionName, sb.toString());
+ if (s==null) break;
+ sb = new StringBuffer();
+ sectionName = s.trim();
+ while(sectionName.startsWith("="))
+ sectionName = sectionName.substring(1);
+ while(sectionName.endsWith("="))
+ sectionName = sectionName.substring(0, sectionName.length()-1);
+ sectionName = sectionName.trim().toLowerCase();
+ continue;
+ }
+ sb.append(s+"\n");
+ }
+ for(String s : sections.keySet())
+ processSection(s);
+ }
+
+ public Constant getConstant(String name) {
+ return constants.get(name);
+ }
+
+ private void processSection(String section) throws IOException {
+ if (section.equals("")) {
+ BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+ for(String s = br.readLine(); s != null; s = br.readLine()) {
+ if (s.trim().length()==0) continue;
+ String key = s.substring(0, s.indexOf(':')).trim();
+ String val = s.substring(s.indexOf(':')+1).trim();
+ if (key.toLowerCase().equals("ship"))
+ name = val.trim();
+ }
+ } else if (section.equals("constants")) {
+ BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+ for(String s = br.readLine(); s != null; s = br.readLine()) {
+ if (s.indexOf(':')==-1) continue;
+ String key = s.substring(0, s.indexOf(':')).trim();
+ if (key.startsWith("constant")) {
+ String constname = key.substring("constant".length()+1).trim();
+ String val = s.substring(s.indexOf(':')+1).trim();
+ constants.put(constname, new Constant(val));
+ }
+ }
+ } else if (section.equals("ports")) {
+ BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
+ boolean rightSide = false;
+ DockDescription p = null;
+ for(String s = br.readLine(); s != null; s = br.readLine()) {
+ if (s.trim().length()==0) { rightSide = true; continue; }
+
+ String key = s.substring(0, s.indexOf(':')).trim();
+ boolean inbox = false;
+ key = key.replaceAll(" +", " ");
+ if (key.equals("data in")) { inbox = true; }
+ else if (key.equals("data out")) { inbox = false; }
+ else if (key.equals("in")) { inbox = true; }
+ else if (key.equals("out")) { inbox = false; }
+ else if (key.startsWith("constant")) {
+ String constname = key.substring("constant".length()+1).trim();
+ String val = s.substring(s.indexOf(':')+1).trim();
+ p.addConstant(constname, new Constant(val));
+ continue;
+ } else if (key.startsWith("shortcut to")) {
+ continue;
+ }
+ else throw new RuntimeException("unknown port type: \""+key+"\"");
+
+ p = null;
+ String val = s.substring(s.indexOf(':')+1).trim();
+ String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val;
+ String dest = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1) : "";
+ p = docks.get(boxname);
+ if (p==null) {
+ p = new DockDescription(this, boxname, !rightSide, inbox);
+ docks.put(boxname, p);
+ }
+ }
+ }
+ }
+
+ public void printTeX(PrintWriter pw) throws Exception {
+ ShipDescription sd = this;
+ pw.println("\\pagebreak");
+ pw.println("\\section*{The {\\tt "+sd.getName()+"} Ship}");
+ pw.println("\\addcontentsline{toc}{subsection}{"+sd.getName()+"}");
+ String tex = sd.getSection("tex");
+ /*
+ for(DockDescription bbd : sd) {
+ pw.println("{\\bf "+(bbd.isInputDock() ? "Input: " : "Output: ")+"{\\tt "+bbd.getName()+"}}\n\n");
+ }
+ */
+ int boxGap = 5;
+ int boxHeight = 25;
+ int boxWidth = 75;
+
+ int leftSize = 0;
+ int rightSize = 0;
+ for(DockDescription bbd : sd)
+ if (bbd.isLeft()) leftSize += (boxHeight+boxGap);
+ else rightSize += (boxHeight+boxGap);
+
+ int totalHeight = Math.max(leftSize, rightSize);
+ int shipWidth = (int)(boxWidth * 1.5);
+ int totalWidth = boxGap*2 + boxWidth*2 + shipWidth;
+
+ pw.println("");
+ pw.println("\\begin{center}");
+ pw.println("\\begin{empfile}["+sd.getName()+"]");
+ pw.println("\\begin{emp}["+sd.getName()+"]("+(totalWidth+10)+","+(totalHeight+10)+")");
+ pw.println(" beginfig(1)");
+ pw.println(" pickup pencircle scaled 1pt;");
+ pw.println(" draw "+
+ "("+((totalWidth-shipWidth)/2)+","+0+")--"+
+ "("+((totalWidth-shipWidth)/2)+","+totalHeight+")--"+
+ "("+(totalWidth-((totalWidth-shipWidth)/2))+","+totalHeight+")--"+
+ "("+(totalWidth-((totalWidth-shipWidth)/2))+","+0+")--"+
+ "("+((totalWidth-shipWidth)/2)+","+0+");");
+ int left = 0;
+ int right = 0;
+ for(DockDescription bbd : sd) {
+ int ypos = (totalHeight - (boxGap/2) - (bbd.isLeft() ? left : right));
+ int half = (totalWidth-shipWidth)/2;
+ int p1 = bbd.isLeft() ? (half-5) : ((totalWidth-half)+5);
+ int p3 = bbd.isLeft() ? (p1 - boxWidth) : (p1 + boxWidth);
+ if (bbd.isInputDock()) {
+ int p1x = p1;
+ p1 = p3;
+ p3 = p1x;
+ }
+ boolean goo = ((bbd.isLeft() && bbd.isInputDock()) || (!bbd.isLeft() && bbd.isOutputDock()));
+ int p2 = goo ? (p3 - (boxHeight/2)) : (p3 + (boxHeight/2));
+ if (bbd.isLeft()) left += (boxHeight+boxGap);
+ else right += (boxHeight+boxGap);
+ if (goo) {
+ pw.println(" label.rt(btex \\tt "+bbd.getName()+" etex, ("+(p1+3)+","+(ypos-boxHeight/2)+"));");
+ } else {
+ pw.println(" label.lft(btex \\tt "+bbd.getName()+" etex, ("+(p1-3)+","+(ypos-boxHeight/2)+"));");
+ }
+ pw.println(" draw "+
+ " ("+p1+","+ypos+")--"+
+ " ("+p2+","+ypos+")--"+
+ " ("+p3+","+(ypos-(boxHeight/2))+")--"+
+ " ("+p2+","+(ypos-boxHeight)+")--"+
+ " ("+p1+","+(ypos-boxHeight)+")--"+
+ " ("+p1+","+ypos+");");
+ if (bbd.isLeft()) leftSize += boxHeight;
+ else rightSize += boxHeight;
+ }
+ pw.println(" endfig;");
+ pw.println("\\end{emp}");
+ pw.println("\\end{empfile}");
+ pw.println("\\end{center}");
+ pw.println("");
+
+ if (tex!=null)
+ pw.println(tex);
+ }
+
+ public class Constant {
+ public long setbits = 0;
+ public long clearbits = 0;
+ public boolean signExtend = false;
+ public int numberOffset = 0;
+ public int numberWidth = 0;
+ public Constant(String s) {
+ if (s.startsWith("0x")) {
+ setbits = Long.parseLong(s.substring(2), 16);
+ clearbits = ~setbits;
+ } else if (s.length() == 37) {
+ for(int i=36; i>=0; i--) {
+ char c = s.charAt(36-i);
+ switch(c) {
+ case '0': clearbits |= (1<<i); break;
+ case '1': setbits |= (1<<i); break;
+ case '.': break;
+ case 's': signExtend = true; numberOffset = i; numberWidth++; break;
+ case 'u': signExtend = false; numberOffset = i; numberWidth++; break;
+ }
+ }
+ } else {
+ setbits = Long.parseLong(s);
+ clearbits = ~setbits;
+ }
+ }
+ }
+
+}