// // used to initialize the infoTable table (see below) // private static void addInfo(String name, int opcode, String args) { InsnInfo info = new InsnInfo(); info.name = name; info.opcode = opcode; info.args = args; infoTable.put(name, info); }
// // used for relative branch targets (ie $+5, $-12, ...) // void plantRelativeGoto(String name, int val) throws jasError { InsnInfo insn = InsnInfo.get(name); if (insn.args.equals("label")) { bufferInsn(new Insn(insn.opcode, val, true)); } else { // forward the request for "normal" instructions plant(name, val); } }
// // used for ldc <quoted-string> // void plantString(String name, String val) throws jasError { InsnInfo insn = InsnInfo.get(name); autoNumber(); flushInsnBuffer(); if (name.startsWith("ldc")) { bufferInsn(new Insn(insn.opcode, new StringCP(val))); } else { throw new jasError("Bad arguments for instruction " + name); } }
// // used for iinc // void plant(String name, int v1, int v2) throws jasError { InsnInfo insn = InsnInfo.get(name); autoNumber(); flushInsnBuffer(); if (insn.args.equalsIgnoreCase("ii")) { bufferInsn(new IincInsn(v1, v2, insn.args.charAt(0) == 'I')); } else { throw new jasError("Bad arguments for instruction " + name); } }
// // used for instructions that take no arguments // void plant(String name) throws jasError { InsnInfo insn = InsnInfo.get(name); autoNumber(); flushInsnBuffer(); if (insn.args.equals("")) { bufferInsn(new Insn(insn.opcode)); } else { throw new jasError("Missing arguments for instruction " + name); } }
// // used for instructions that take a field and a signature as parameters // (e.g. getstatic, putstatic) // void plant(String name, String v1, String v2) throws jasError { InsnInfo info = InsnInfo.get(name); CodeAttr code = _getCode(); autoNumber(); flushInsnBuffer(); if (info.args.equals("field")) { String split[] = ScannerUtils.splitClassField(v1); if (split[1] == null) throw new jasError("can't extract field from " + v1); bufferInsn(new Insn(info.opcode, new FieldCP(split[0], split[1], v2))); } else { throw new jasError("Bad arguments for instruction " + name); } }
// // used for instructions that take a word as a parameter // (e.g. branches, newarray, invokemethod) // void plant(String name, String val) throws jasError { InsnInfo insn = InsnInfo.get(name); CodeAttr code = _getCode(); autoNumber(); flushInsnBuffer(); if (insn.args.equals("method")) { String split[] = ScannerUtils.splitClassMethodSignature(val); bufferInsn(new Insn(insn.opcode, new MethodCP(split[0], split[1], split[2]))); } else if (insn.args.equals("interface")) { String split[] = ScannerUtils.splitClassMethodSignature(val); bufferInsn( new InvokeinterfaceInsn( new InterfaceCP(split[0], split[1], split[2]), ScannerUtils.getArgumentsAndReturnSizes(split[2]) >> 2)); } else if (name.startsWith("ldc")) { bufferInsn(new Insn(insn.opcode, new ClassCP(val))); } else if (insn.args.equals("atype")) { int atype = 0; if (val.equals("boolean")) { atype = 4; } else if (val.equals("char")) { atype = 5; } else if (val.equals("float")) { atype = 6; } else if (val.equals("double")) { atype = 7; } else if (val.equals("byte")) { atype = 8; } else if (val.equals("short")) { atype = 9; } else if (val.equals("int")) { atype = 10; } else if (val.equals("long")) { atype = 11; } else { throw new jasError("Bad array type: " + name); } bufferInsn(new Insn(insn.opcode, atype, false)); } else if (insn.args.indexOf("label") >= 0) { bufferInsn(new Insn(insn.opcode, getLabel(val), scanner.line_num)); } else if (insn.args.equals("class")) { bufferInsn(new Insn(insn.opcode, new ClassCP(val))); } else { throw new jasError("(gloups)Bad arguments for instruction " + name); } }
// // used for instructions that take an integer parameter // (branches are part of this, the int is converted to a label) // void plant(String name, int val) throws jasError { InsnInfo insn = InsnInfo.get(name); CodeAttr code = _getCode(); autoNumber(); flushInsnBuffer(); if (insn.args.equalsIgnoreCase("i")) { bufferInsn(new Insn(insn.opcode, val, insn.args.charAt(0) == 'I')); } else if (name.startsWith("ldc")) { bufferInsn(new Insn(insn.opcode, new IntegerCP(val))); } else if (insn.args.equals("label")) { plant(name, String.valueOf(val)); // the target is not signed // assume it is a label } else { throw new jasError("Bad arguments for instruction " + name); } }
// // used for invokeinterface and multianewarray // void plant(String name, String val, int nargs) throws jasError { InsnInfo insn = InsnInfo.get(name); CodeAttr code = _getCode(); autoNumber(); flushInsnBuffer(); if (insn.args.equals("interface")) { String split[] = ScannerUtils.splitClassMethodSignature(val); bufferInsn( new InvokeinterfaceInsn( new InterfaceCP(split[0], split[1], split[2]), ScannerUtils.getArgumentsAndReturnSizes(split[2]) >> 2)); } else if (insn.args.equals("marray")) { bufferInsn(new MultiarrayInsn(new ClassCP(val), nargs)); } else { throw new jasError("Bad arguments for instruction " + name); } }
// // used for ldc and other instructions that take a numeric argument // void plant(String name, Number val) throws jasError { InsnInfo insn = InsnInfo.get(name); CodeAttr code = _getCode(); autoNumber(); flushInsnBuffer(); if (insn.args.equalsIgnoreCase("i") && (val instanceof Integer)) { bufferInsn(new Insn(insn.opcode, val.intValue(), insn.args.charAt(0) == 'I')); } else if (name.startsWith("ldc")) { if (val instanceof Integer) { bufferInsn(new Insn(insn.opcode, new IntegerCP(val.intValue()))); } else if (val instanceof Float) { bufferInsn(new Insn(insn.opcode, new FloatCP(val.floatValue()))); } else if (val instanceof Long) { bufferInsn(new Insn(insn.opcode, new LongCP(val.longValue()))); } else if (val instanceof Double) { bufferInsn(new Insn(insn.opcode, new DoubleCP(val.doubleValue()))); } } else { throw new jasError("Bad arguments for instruction " + name); } }
// // recognize and return the next complete token // public token next_token() throws java.io.IOException, jasError { token_line_num = line_num; for (; ; ) switch (next_char) { case ';': // a comment case '\n': // return single SEP token (skip multiple newlines // interspersed with whitespace or comments) skip_empty_lines(); token_line_num = line_num; return new token(sym.SEP); case -1: // EOF token char_num = -1; return new token(sym.EOF); case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': // a number { int pos = 0; do { chars[pos] = (char) next_char; pos++; if (pos == chars_size) chars_expand(); advance(); } while (!separator(next_char)); String str = new String(chars, 0, pos); token tok; // This catches directives like ".method" if ((tok = ReservedWords.get(str)) != null) return tok; Number num; try { num = ScannerUtils.convertNumber(str); } catch (NumberFormatException e) { if (chars[0] != '.') throw new jasError("Badly formatted number"); throw new jasError("Unknown directive or badly formed number."); } if (num instanceof Integer) { int_line = line.toString(); int_line_num = token_line_num; int_char_num = char_num; return new int_token(sym.Int, num.intValue()); } return new num_token(sym.Num, num); } case '"': // quoted string { boolean already = false; for (int pos = 0; ; ) { if (already) already = false; else advance(); if (next_char == '"') { advance(); // skip close quote return new str_token(sym.Str, new String(chars, 0, pos)); } if (next_char == -1) throw new jasError("Unterminated string"); char chval = (char) next_char; if (chval == '\\') { advance(); switch (next_char) { case -1: already = true; continue; case 'n': chval = '\n'; break; case 'r': chval = '\r'; break; case 't': chval = '\t'; break; case 'f': chval = '\f'; break; case 'b': chval = '\b'; break; case '"': chval = '"'; break; case '\'': chval = '\''; break; case '\\': chval = '\\'; break; case 'u': chval = uniEscape(); if (next_char == -1) { already = true; continue; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int res = next_char & 7; advance(); if (next_char < '0' || next_char > '7') already = true; else { res = res * 8 + (next_char & 7); advance(); if (next_char < '0' || next_char > '7') already = true; else { int val = res * 8 + (next_char & 7); if (val >= 0x100) already = true; else res = val; } } chval = (char) res; } break; default: throw new jasError("Bad backslash escape sequence"); } } chars[pos] = chval; pos++; if (pos == chars_size) chars_expand(); } } case '\'': // quotation for overloading reserved words for (int pos = 0; ; ) { advance(); if (separator(next_char)) throw new jasError("Unterminated ''-enclosed name"); if (next_char == '\'') { if (pos == 0) throw new jasError("Empty ''-enclosed name"); advance(); // skip close quote if (!separator(next_char)) throw new jasError("Not separator after ''-enclosed name"); return new str_token(sym.Word, new String(chars, 0, pos)); } char chval = (char) next_char; if (next_char == '\\') chval = nameEscape(); chars[pos] = chval; pos++; if (pos == chars_size) chars_expand(); } case ' ': case '\t': case '\r': // whitespace advance(); break; case '=': // EQUALS token advance(); return new token(sym.EQ); case ':': // COLON token advance(); return new token(sym.COLON); default: { // read up until a separatorcharacter int pos = 0; boolean only_name = false; do { char chval = (char) next_char; if (next_char == '\\') { chval = nameEscape(); only_name = true; } chars[pos] = chval; pos++; if (pos == chars_size) chars_expand(); advance(); } while (!separator(next_char)); // convert the byte array into a String String str = new String(chars, 0, pos); if (!only_name) { token tok; // Jasmin keyword or directive ? if ((tok = ReservedWords.get(str)) != null) return tok; // its a JVM instruction ? if (InsnInfo.contains(str)) return new str_token(sym.Insn, str); if (str.charAt(0) == '$') { String s = str.substring(1); Object v; int n = 10; boolean neg = false; boolean sign = false; switch (s.charAt(0)) { default: break; case '-': neg = true; ; case '+': s = s.substring(1); if (s.startsWith("0x")) { n = 16; s = s.substring(2); } try { n = Integer.parseInt(s, n); } catch (NumberFormatException e) { throw new jasError("Badly relative offset number"); } if (neg) n = -n; return new relative_num_token(sym.Relative, n); } // Perform variable substitution if ((v = dict.get(s)) != null) return (token) v; } // not begin from '$' } // !only_name // Unrecognized string token (e.g. a classname) return new str_token(sym.Word, str); } /* default */ } /* switch and for */ }