omit tests if no ships of that type present
[fleet.git] / src / edu / berkeley / fleet / two / ShipDescription.java
1 package edu.berkeley.fleet.two;
2 import edu.berkeley.fleet.api.*;
3 import java.io.*;
4 import java.util.*;
5
6 /** NOT YET FINALIZED: A description (specification) of a ship */
7 public class ShipDescription implements Iterable<DockDescription> {
8
9     private String name;
10     private LinkedHashMap<String,DockDescription> docks     = new LinkedHashMap<String,DockDescription>();
11     private HashMap<String,String>                sections  = new HashMap<String,String>();
12     private HashMap<String,Constant>              constants = new HashMap<String,Constant>();
13
14     public String getName() { return name; }
15     public String getSection(String sectionName) { return sections.get(sectionName); }
16     public DockDescription getDockDescription(String name) { return docks.get(name); }
17     public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
18
19     public ShipDescription(String name, BufferedReader r) throws IOException {
20         if (name.endsWith(".ship")) name = name.substring(0, name.length()-".ship".length());
21         this.name = name;
22         String sectionName = null;
23         StringBuffer sb = new StringBuffer();
24         while(true) {
25             String s = r.readLine();
26             if (s==null || s.startsWith("==")) {
27                 if (sectionName != null) sections.put(sectionName, sb.toString());
28                 if (s==null) break;
29                 sb = new StringBuffer();
30                 sectionName = s.trim();
31                 while(sectionName.startsWith("="))
32                     sectionName = sectionName.substring(1);
33                 while(sectionName.endsWith("="))
34                     sectionName = sectionName.substring(0, sectionName.length()-1);
35                 sectionName = sectionName.trim().toLowerCase();
36                 continue;
37             }
38             sb.append(s+"\n");
39         }
40         for(String s : sections.keySet())
41             processSection(s);
42     }
43
44     public Constant getConstant(String name) {
45         return constants.get(name);
46     }
47
48     private void processSection(String section) throws IOException {
49         if (section.equals("")) {
50             BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
51             for(String s = br.readLine(); s != null; s = br.readLine()) {
52                 if (s.trim().length()==0) continue;
53                 String key = s.substring(0, s.indexOf(':')).trim();
54                 String val = s.substring(s.indexOf(':')+1).trim();
55                 if (key.toLowerCase().equals("ship"))
56                     name = val.trim();
57             }
58         } else if (section.equals("constants")) {
59             BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
60             for(String s = br.readLine(); s != null; s = br.readLine()) {
61                 if (s.indexOf(':')==-1) continue;
62                 String key = s.substring(0, s.indexOf(':')).trim();
63                 if (key.startsWith("constant")) {
64                     String constname = key.substring("constant".length()+1).trim();
65                     String val       = s.substring(s.indexOf(':')+1).trim();
66                     constants.put(constname, new Constant(val));
67                 }
68             }
69         } else if (section.equals("ports")) {
70             BufferedReader br = new BufferedReader(new StringReader(sections.get(section)));
71             boolean rightSide = false;
72             DockDescription p = null;
73             for(String s = br.readLine(); s != null; s = br.readLine()) {
74                 if (s.trim().length()==0) { rightSide = true; continue; }
75
76                 String key = s.substring(0, s.indexOf(':')).trim();
77                 boolean inbox = false;
78                 key = key.replaceAll("  +", " ");
79                 if      (key.equals("data in"))   { inbox = true;  }
80                 else if (key.equals("data out"))  { inbox = false; }
81                 else if (key.equals("in"))        { inbox = true;  }
82                 else if (key.equals("out"))       { inbox = false; }
83                 else if (key.startsWith("constant")) {
84                     String constname = key.substring("constant".length()+1).trim();
85                     String val       = s.substring(s.indexOf(':')+1).trim();
86                     p.addConstant(constname, new Constant(val));
87                     continue;
88                 } else if (key.startsWith("shortcut to")) {
89                     continue;
90                 }
91                 else throw new RuntimeException("unknown port type: \""+key+"\"");
92
93                 p = null;
94                 String val = s.substring(s.indexOf(':')+1).trim();
95                 String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val;
96                 String dest    = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1)  : "";
97                 p = docks.get(boxname);
98                 if (p==null) {
99                     p = new DockDescription(this, boxname, !rightSide, inbox);
100                     docks.put(boxname, p);
101                 }
102             }
103         }
104     }
105
106     public void printTeX(PrintWriter pw) throws Exception {
107         ShipDescription sd = this;
108         pw.println("\\pagebreak");
109         pw.println("\\section*{The {\\tt "+sd.getName()+"} Ship}");
110         pw.println("\\addcontentsline{toc}{subsection}{"+sd.getName()+"}");
111         String tex = sd.getSection("tex");
112         /*
113         for(DockDescription bbd : sd) {
114             pw.println("{\\bf "+(bbd.isInputDock() ? "Input: " : "Output: ")+"{\\tt "+bbd.getName()+"}}\n\n");
115         }
116         */
117         int boxGap = 5;
118         int boxHeight = 25;
119         int boxWidth = 75;
120
121         int leftSize = 0;
122         int rightSize = 0;
123         for(DockDescription bbd : sd)
124             if (bbd.isLeft()) leftSize += (boxHeight+boxGap);
125             else              rightSize += (boxHeight+boxGap);
126
127         int totalHeight = Math.max(leftSize, rightSize);
128         int shipWidth = (int)(boxWidth * 1.5);
129         int totalWidth = boxGap*2 + boxWidth*2 + shipWidth;
130
131         pw.println("");
132         pw.println("\\begin{center}");
133         pw.println("\\begin{empfile}["+sd.getName()+"]");
134         pw.println("\\begin{emp}["+sd.getName()+"]("+(totalWidth+10)+","+(totalHeight+10)+")");
135         pw.println("  beginfig(1)");
136         pw.println("      pickup pencircle scaled 1pt;");
137         pw.println("      draw "+
138                    "("+((totalWidth-shipWidth)/2)+","+0+")--"+
139                    "("+((totalWidth-shipWidth)/2)+","+totalHeight+")--"+
140                    "("+(totalWidth-((totalWidth-shipWidth)/2))+","+totalHeight+")--"+
141                    "("+(totalWidth-((totalWidth-shipWidth)/2))+","+0+")--"+
142                    "("+((totalWidth-shipWidth)/2)+","+0+");");
143         int left = 0;
144         int right = 0;
145         for(DockDescription bbd : sd) {
146             int ypos = (totalHeight - (boxGap/2) - (bbd.isLeft() ? left : right));
147             int half = (totalWidth-shipWidth)/2;
148             int p1 = bbd.isLeft() ? (half-5) : ((totalWidth-half)+5);
149             int p3 = bbd.isLeft() ? (p1 - boxWidth) : (p1 + boxWidth);
150             if (bbd.isInputDock()) {
151                 int p1x = p1;
152                 p1 = p3;
153                 p3 = p1x;
154             }
155             boolean goo = ((bbd.isLeft() && bbd.isInputDock()) || (!bbd.isLeft() && bbd.isOutputDock()));
156             int p2 = goo ? (p3 - (boxHeight/2)) : (p3 + (boxHeight/2));
157             if (bbd.isLeft()) left += (boxHeight+boxGap);
158             else              right += (boxHeight+boxGap);
159             if (goo) {
160                 pw.println("      label.rt(btex \\tt "+bbd.getName()+" etex, ("+(p1+3)+","+(ypos-boxHeight/2)+"));");
161             } else {
162                 pw.println("      label.lft(btex \\tt "+bbd.getName()+" etex, ("+(p1-3)+","+(ypos-boxHeight/2)+"));");
163             }
164             pw.println("      draw "+
165                        "  ("+p1+","+ypos+")--"+
166                        "  ("+p2+","+ypos+")--"+
167                        "  ("+p3+","+(ypos-(boxHeight/2))+")--"+
168                        "  ("+p2+","+(ypos-boxHeight)+")--"+
169                        "  ("+p1+","+(ypos-boxHeight)+")--"+
170                        "  ("+p1+","+ypos+");");
171             if (bbd.isLeft()) leftSize += boxHeight;
172             else              rightSize += boxHeight;
173         }
174         pw.println("  endfig;");
175         pw.println("\\end{emp}");
176         pw.println("\\end{empfile}");
177         pw.println("\\end{center}");
178         pw.println("");
179
180         if (tex!=null)
181             pw.println(tex);
182     }
183
184     // FIXME: merge with BitMask
185     public class Constant {
186         public long    setbits   = 0;
187         public long    clearbits = 0;
188         public boolean signExtend = false;
189         public int     numberOffset = 0;
190         public int     numberWidth = 0;
191         public Constant(String s) {
192             if (s.startsWith("0x")) {
193                 setbits = Long.parseLong(s.substring(2), 16);
194                 clearbits = ~setbits;
195             } else if (s.length() == 37) {
196                 for(int i=36; i>=0; i--) {
197                     char c = s.charAt(36-i);
198                     switch(c) {
199                         case '0': clearbits |= (1<<i); break;
200                         case '1': setbits   |= (1<<i); break;
201                         case '.': break;
202                         case 's': signExtend = true;  numberOffset = i; numberWidth++; break;
203                         case 'u': signExtend = false; numberOffset = i; numberWidth++; break;
204                     }
205                 }
206             } else {
207                 setbits = Long.parseLong(s);
208                 clearbits = ~setbits;
209             }
210         }
211     }
212
213 }