00001 package de.fub.bytecode.generic;
00002
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.util.ByteSequence;
00005 import java.io.*;
00006 import java.util.Enumeration;
00007 import java.util.Hashtable;
00008 import java.util.Vector;
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 public class InstructionList implements Serializable {
00030 private InstructionHandle start = null, end = null;
00031 private int length = 0;
00032 private int[] byte_positions;
00033
00034 private Vector observers;
00035
00036
00037
00038
00039 public InstructionList() {}
00040
00041
00042
00043
00044
00045 public InstructionList(byte[] code) {
00046 ByteSequence bytes = new ByteSequence(code);
00047 InstructionHandle[] ihs = new InstructionHandle[code.length];
00048 int[] pos = new int[code.length];
00049 int count = 0;
00050
00051
00052
00053
00054 try {
00055 while(bytes.available() > 0) {
00056
00057 int off = bytes.getIndex();
00058 pos[count] = off;
00059
00060
00061
00062
00063 Instruction i = Instruction.readInstruction(bytes);
00064 InstructionHandle ih;
00065 if(i instanceof BranchInstruction)
00066 ih = append((BranchInstruction)i);
00067 else
00068 ih = append(i);
00069
00070 ih.setPosition(off);
00071 ihs[count] = ih;
00072
00073 count++;
00074 }
00075 } catch(IOException e) { throw new ClassGenException(e.toString()); }
00076
00077 byte_positions = new int[count];
00078 System.arraycopy(pos, 0, byte_positions, 0, count);
00079
00080
00081
00082
00083 for(int i=0; i < count; i++) {
00084 if(ihs[i] instanceof BranchHandle) {
00085 BranchInstruction bi = (BranchInstruction)ihs[i].instruction;
00086 int target = bi.position + bi.getIndex();
00087
00088
00089 InstructionHandle ih = findHandle(ihs, pos, count, target);
00090
00091 if(ih == null)
00092 throw new ClassGenException("Couldn't find target for branch: " + bi);
00093
00094 bi.setTarget(ih);
00095
00096
00097 if(bi instanceof Select) {
00098 Select s = (Select)bi;
00099 int[] indices = s.getIndices();
00100
00101 for(int j=0; j < indices.length; j++) {
00102 target = bi.position + indices[j];
00103 ih = findHandle(ihs, pos, count, target);
00104
00105 if(ih == null)
00106 throw new ClassGenException("Couldn't find target for switch: " + bi);
00107
00108 s.setTarget(j, ih);
00109 }
00110 }
00111 }
00112 }
00113 }
00114
00115
00116
00117
00118 public InstructionList(BranchInstruction i) {
00119 append(i);
00120 }
00121
00122
00123
00124
00125
00126
00127 public InstructionList(CompoundInstruction c) {
00128 append(c.getInstructionList());
00129 }
00130
00131
00132
00133
00134 public InstructionList(Instruction i) {
00135 append(i);
00136 }
00137
00138
00139 public void addObserver(InstructionListObserver o) {
00140 if(observers == null)
00141 observers = new Vector();
00142
00143 observers.add(o);
00144 }
00145
00146
00147
00148
00149
00150
00151 public BranchHandle append(BranchInstruction i) {
00152 BranchHandle ih = BranchHandle.getBranchHandle(i);
00153 append(ih);
00154
00155 return ih;
00156 }
00157
00158
00159
00160
00161
00162
00163 public InstructionHandle append(CompoundInstruction c) {
00164 return append(c.getInstructionList());
00165 }
00166
00167
00168
00169
00170
00171
00172 public InstructionHandle append(Instruction i) {
00173 InstructionHandle ih = InstructionHandle.getInstructionHandle(i);
00174 append(ih);
00175
00176 return ih;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 public InstructionHandle append(Instruction i, CompoundInstruction c) {
00186 return append(i, c.getInstructionList());
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 public InstructionHandle append(Instruction i, Instruction j) {
00197 return append(i, new InstructionList(j));
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207 public InstructionHandle append(Instruction i, InstructionList il) {
00208 InstructionHandle ih;
00209
00210 if((ih = findInstruction2(i)) == null)
00211 throw new ClassGenException("Instruction " + i +
00212 " is not contained in this list.");
00213
00214 return append(ih, il);
00215 }
00216
00217
00218
00219
00220
00221 private void append(InstructionHandle ih) {
00222 if(isEmpty()) {
00223 start = end = ih;
00224 ih.next = ih.prev = null;
00225 }
00226 else {
00227 end.next = ih;
00228 ih.prev = end;
00229 ih.next = null;
00230 end = ih;
00231 }
00232
00233 length++;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242 public BranchHandle append(InstructionHandle ih, BranchInstruction i) {
00243 BranchHandle bh = BranchHandle.getBranchHandle(i);
00244 InstructionList il = new InstructionList();
00245 il.append(bh);
00246
00247 append(ih, il);
00248
00249 return bh;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 public InstructionHandle append(InstructionHandle ih, CompoundInstruction c) {
00259 return append(ih, c.getInstructionList());
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 public InstructionHandle append(InstructionHandle ih, Instruction i) {
00269 return append(ih, new InstructionList(i));
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279 public InstructionHandle append(InstructionHandle ih, InstructionList il) {
00280 if(il == null)
00281 throw new ClassGenException("Appending null InstructionList");
00282
00283 if(il.isEmpty())
00284 return ih;
00285
00286 InstructionHandle next = ih.next, ret = il.start;
00287
00288 ih.next = il.start;
00289 il.start.prev = ih;
00290
00291 il.end.next = next;
00292
00293 if(next != null)
00294 next.prev = il.end;
00295 else
00296 end = il.end;
00297
00298 length += il.length;
00299
00300 il.clear();
00301
00302 return ret;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 public InstructionHandle append(InstructionList il) {
00312 if(il == null)
00313 throw new ClassGenException("Appending null InstructionList");
00314
00315 if(il.isEmpty())
00316 return null;
00317
00318 if(isEmpty()) {
00319 start = il.start;
00320 end = il.end;
00321 length = il.length;
00322
00323 il.clear();
00324
00325 return start;
00326 } else
00327 return append(end, il);
00328 }
00329 private void clear() {
00330 start = end = null;
00331 length = 0;
00332 }
00333 public boolean contains(Instruction i) {
00334 return findInstruction1(i) != null;
00335 }
00336 public boolean contains(InstructionHandle i) {
00337 if(i == null)
00338 return false;
00339
00340 for(InstructionHandle ih=start; ih != null; ih = ih.next)
00341 if(ih == i)
00342 return true;
00343
00344 return false;
00345 }
00346
00347
00348
00349 public InstructionList copy() {
00350 Hashtable map = new Hashtable();
00351 InstructionList il = new InstructionList();
00352
00353
00354
00355
00356
00357 for(InstructionHandle ih=start; ih != null; ih = ih.next) {
00358 Instruction i = ih.instruction;
00359 Instruction c = i.copy();
00360
00361 map.put(ih, il.append(c));
00362 }
00363
00364
00365
00366 InstructionHandle ih=start;
00367 InstructionHandle ch=il.start;
00368
00369 while(ih != null) {
00370 Instruction i = ih.instruction;
00371 Instruction c = ch.instruction;
00372
00373 if(i instanceof BranchInstruction) {
00374 BranchInstruction bi = (BranchInstruction)i;
00375 BranchInstruction bc = (BranchInstruction)c;
00376 InstructionHandle itarget = bi.getTarget();
00377
00378
00379 bc.setTarget((InstructionHandle)map.get(itarget));
00380
00381 if(bi instanceof Select) {
00382 InstructionHandle[] itargets = ((Select)bi).getTargets();
00383 InstructionHandle[] ctargets = ((Select)bc).getTargets();
00384
00385 for(int j=0; j < itargets.length; j++) {
00386 ctargets[j] = (InstructionHandle)map.get(itargets[j]);
00387 }
00388 }
00389 }
00390
00391 ih = ih.next;
00392 ch = ch.next;
00393 }
00394
00395 return il;
00396 }
00397
00398
00399
00400
00401
00402
00403 public void delete(Instruction i) throws TargetLostException {
00404 InstructionHandle ih;
00405
00406 if((ih = findInstruction1(i)) == null)
00407 throw new ClassGenException("Instruction " + i +
00408 " is not contained in this list.");
00409 delete(ih);
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419 public void delete(Instruction from, Instruction to) throws TargetLostException {
00420 InstructionHandle from_ih, to_ih;
00421
00422 if((from_ih = findInstruction1(from)) == null)
00423 throw new ClassGenException("Instruction " + from +
00424 " is not contained in this list.");
00425
00426 if((to_ih = findInstruction2(to)) == null)
00427 throw new ClassGenException("Instruction " + to +
00428 " is not contained in this list.");
00429 delete(from_ih, to_ih);
00430 }
00431
00432
00433
00434
00435
00436
00437 public void delete(InstructionHandle ih) throws TargetLostException {
00438 remove(ih.prev, ih.next);
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448 public void delete(InstructionHandle from, InstructionHandle to)
00449 throws TargetLostException
00450 {
00451 remove(from.prev, to.next);
00452 }
00453
00454
00455
00456
00457
00458
00459 public void dispose() {
00460
00461 for(InstructionHandle ih=end; ih != null; ih = ih.prev)
00462
00463
00464
00465 ih.dispose();
00466
00467 clear();
00468 }
00469
00470
00471
00472 public Enumeration elements() {
00473 return new Enumeration() {
00474 private InstructionHandle ih = start;
00475
00476 public Object nextElement() {
00477 InstructionHandle i = ih;
00478 ih = ih.next;
00479 return i;
00480 }
00481
00482 public boolean hasMoreElements() { return ih != null; }
00483 };
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 public static InstructionHandle findHandle(InstructionHandle[] ihs,
00496 int[] pos, int count,
00497 int target) {
00498 int l=0, r = count - 1;
00499
00500
00501
00502 do {
00503 int i = (l + r) / 2;
00504 int j = pos[i];
00505
00506 if(j == target)
00507 return ihs[i];
00508 else if(target < j)
00509 r = i - 1;
00510 else
00511 l = i + 1;
00512 } while(l <= r);
00513
00514 return null;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524 public InstructionHandle findHandle(int pos) {
00525 InstructionHandle[] ihs = getInstructionHandles();
00526 return findHandle(ihs, byte_positions, length, pos);
00527 }
00528
00529
00530
00531
00532
00533
00534 private InstructionHandle findInstruction1(Instruction i) {
00535 for(InstructionHandle ih=start; ih != null; ih = ih.next)
00536 if(ih.instruction == i)
00537 return ih;
00538
00539 return null;
00540 }
00541
00542
00543
00544
00545
00546
00547 private InstructionHandle findInstruction2(Instruction i) {
00548 for(InstructionHandle ih=end; ih != null; ih = ih.prev)
00549 if(ih.instruction == i)
00550 return ih;
00551
00552 return null;
00553 }
00554
00555
00556
00557
00558
00559
00560 public byte[] getByteCode() {
00561
00562 setPositions();
00563
00564 ByteArrayOutputStream b = new ByteArrayOutputStream();
00565 DataOutputStream out = new DataOutputStream(b);
00566
00567 try {
00568 for(InstructionHandle ih=start; ih != null; ih = ih.next) {
00569 Instruction i = ih.instruction;
00570 i.dump(out);
00571 }
00572 } catch(IOException e) {
00573 System.err.println(e);
00574 return null;
00575 }
00576
00577 return b.toByteArray();
00578 }
00579
00580
00581
00582 public InstructionHandle getEnd() { return end; }
00583
00584
00585
00586 public InstructionHandle[] getInstructionHandles() {
00587 InstructionHandle[] ihs = new InstructionHandle[length];
00588 InstructionHandle ih = start;
00589
00590 for(int i=0; i < length; i++) {
00591 ihs[i] = ih;
00592 ih = ih.next;
00593 }
00594
00595 return ihs;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 public int[] getInstructionPositions() { return byte_positions; }
00605
00606
00607
00608 public Instruction[] getInstructions() {
00609 ByteSequence bytes = new ByteSequence(getByteCode());
00610 Vector instructions = new Vector();
00611
00612 try {
00613 while(bytes.available() > 0) {
00614 instructions.addElement(Instruction.readInstruction(bytes));
00615 }
00616 } catch(IOException e) { throw new ClassGenException(e.toString()); }
00617 Instruction[] result = new Instruction[instructions.size()];
00618 instructions.copyInto(result);
00619 return result;
00620 }
00621
00622
00623
00624 public int getLength() { return length; }
00625
00626
00627
00628 public InstructionHandle getStart() { return start; }
00629
00630
00631
00632
00633
00634
00635 public BranchHandle insert(BranchInstruction i) {
00636 BranchHandle ih = BranchHandle.getBranchHandle(i);
00637 insert(ih);
00638 return ih;
00639 }
00640
00641
00642
00643
00644
00645
00646 public InstructionHandle insert(CompoundInstruction c) {
00647 return insert(c.getInstructionList());
00648 }
00649
00650
00651
00652
00653
00654
00655 public InstructionHandle insert(Instruction i) {
00656 InstructionHandle ih = InstructionHandle.getInstructionHandle(i);
00657 insert(ih);
00658
00659 return ih;
00660 }
00661
00662
00663
00664
00665
00666
00667
00668 public InstructionHandle insert(Instruction i, CompoundInstruction c) {
00669 return insert(i, c.getInstructionList());
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679 public InstructionHandle insert(Instruction i, Instruction j) {
00680 return insert(i, new InstructionList(j));
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 public InstructionHandle insert(Instruction i, InstructionList il) {
00692 InstructionHandle ih;
00693
00694 if((ih = findInstruction1(i)) == null)
00695 throw new ClassGenException("Instruction " + i +
00696 " is not contained in this list.");
00697
00698 return insert(ih, il);
00699 }
00700
00701
00702
00703
00704
00705 private void insert(InstructionHandle ih) {
00706 if(isEmpty()) {
00707 start = end = ih;
00708 ih.next = ih.prev = null;
00709 } else {
00710 start.prev = ih;
00711 ih.next = start;
00712 ih.prev = null;
00713 start = ih;
00714 }
00715
00716 length++;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725 public BranchHandle insert(InstructionHandle ih, BranchInstruction i) {
00726 BranchHandle bh = BranchHandle.getBranchHandle(i);
00727 InstructionList il = new InstructionList();
00728 il.append(bh);
00729
00730 insert(ih, il);
00731
00732 return bh;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741 public InstructionHandle insert(InstructionHandle ih, CompoundInstruction c) {
00742 return insert(ih, c.getInstructionList());
00743 }
00744
00745
00746
00747
00748
00749
00750
00751 public InstructionHandle insert(InstructionHandle ih, Instruction i) {
00752 return insert(ih, new InstructionList(i));
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762 public InstructionHandle insert(InstructionHandle ih, InstructionList il) {
00763 if(il == null)
00764 throw new ClassGenException("Inserting null InstructionList");
00765
00766 if(il.isEmpty())
00767 return ih;
00768
00769 InstructionHandle prev = ih.prev, ret = il.start;
00770
00771 ih.prev = il.end;
00772 il.end.next = ih;
00773
00774 il.start.prev = prev;
00775
00776 if(prev != null)
00777 prev.next = il.start;
00778 else
00779 start = il.start;
00780
00781 length += il.length;
00782
00783 il.clear();
00784
00785 return ret;
00786 }
00787
00788
00789
00790
00791
00792
00793 public InstructionHandle insert(InstructionList il) {
00794 if(isEmpty()) {
00795 append(il);
00796 return start;
00797 }
00798 else
00799 return insert(start, il);
00800 }
00801
00802
00803
00804 public boolean isEmpty() { return start == null; }
00805
00806
00807
00808
00809
00810
00811 public void move(InstructionHandle ih, InstructionHandle target) {
00812 move(ih, ih, target);
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825 public void move(InstructionHandle start, InstructionHandle end, InstructionHandle target) {
00826
00827
00828 if((start == null) || (end == null))
00829 throw new ClassGenException("Invalid null handle: From " + start + " to " + end);
00830
00831 if((target == start) || (target == end))
00832 throw new ClassGenException("Invalid range: From " + start + " to " + end +
00833 " contains target " + target);
00834
00835 for(InstructionHandle ih = start; ih != end.next; ih = ih.next) {
00836 if(ih == null)
00837 throw new ClassGenException("Invalid range: From " + start + " to " + end);
00838 else if(ih == target)
00839 throw new ClassGenException("Invalid range: From " + start + " to " + end +
00840 " contains target " + target);
00841 }
00842
00843
00844
00845 InstructionHandle prev = start.prev, next = end.next;
00846
00847 if(prev != null)
00848 prev.next = next;
00849 else
00850 this.start = next;
00851
00852 if(next != null)
00853 next.prev = prev;
00854 else
00855 this.end = prev;
00856
00857 start.prev = end.next = null;
00858
00859
00860
00861 if(target == null) {
00862 end.next = this.start;
00863 this.start = start;
00864 } else {
00865 next = target.next;
00866
00867 target.next = start;
00868 start.prev = target;
00869 end.next = next;
00870
00871 if(next != null)
00872 next.prev = end;
00873 }
00874 }
00875
00876
00877
00878
00879
00880
00881
00882 public void redirectBranches(InstructionHandle old_target,
00883 InstructionHandle new_target) {
00884 for(InstructionHandle ih = start; ih != null; ih = ih.next) {
00885 Instruction i = ih.getInstruction();
00886
00887 if(i instanceof BranchInstruction) {
00888 BranchInstruction b = (BranchInstruction)i;
00889 InstructionHandle target = b.getTarget();
00890
00891 if(target == old_target)
00892 b.setTarget(new_target);
00893
00894 if(b instanceof Select) {
00895 InstructionHandle[] targets = ((Select)b).getTargets();
00896
00897 for(int j=0; j < targets.length; j++)
00898 if(targets[j] == old_target)
00899 ((Select)b).setTarget(j, new_target);
00900 }
00901 }
00902 }
00903 }
00904
00905
00906
00907
00908
00909
00910
00911
00912 public void redirectExceptionHandlers(CodeExceptionGen[] exceptions,
00913 InstructionHandle old_target,
00914 InstructionHandle new_target) {
00915 for(int i=0; i < exceptions.length; i++) {
00916 if(exceptions[i].getStartPC() == old_target)
00917 exceptions[i].setStartPC(new_target);
00918
00919 if(exceptions[i].getEndPC() == old_target)
00920 exceptions[i].setEndPC(new_target);
00921
00922 if(exceptions[i].getHandlerPC() == old_target)
00923 exceptions[i].setHandlerPC(new_target);
00924 }
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934 public void redirectLocalVariables(LocalVariableGen[] lg,
00935 InstructionHandle old_target,
00936 InstructionHandle new_target) {
00937 for(int i=0; i < lg.length; i++) {
00938 InstructionHandle start = lg[i].getStart();
00939 InstructionHandle end = lg[i].getEnd();
00940
00941 if(start == old_target)
00942 lg[i].setStart(new_target);
00943
00944 if(end == old_target)
00945 lg[i].setEnd(new_target);
00946 }
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956 private void remove(InstructionHandle prev, InstructionHandle next)
00957 throws TargetLostException
00958 {
00959 InstructionHandle first, last;
00960
00961 if((prev == null) && (next == null)) {
00962 first = last = start;
00963 start = end = null;
00964 } else {
00965 if(prev == null) {
00966 first = start;
00967 start = next;
00968 } else {
00969 first = prev.next;
00970 prev.next = next;
00971 }
00972
00973 if(next == null) {
00974 last = end;
00975 end = prev;
00976 } else {
00977 last = next.prev;
00978 next.prev = prev;
00979 }
00980 }
00981
00982 first.prev = null;
00983 last.next = null;
00984
00985 Vector target_vec = new Vector();
00986
00987 for(InstructionHandle ih=first; ih != null; ih = ih.next)
00988 ih.getInstruction().dispose();
00989
00990 StringBuffer buf = new StringBuffer("{ ");
00991 for(InstructionHandle ih=first; ih != null; ih = next) {
00992 next = ih.next;
00993 length--;
00994
00995 if(ih.hasTargeters()) {
00996 target_vec.addElement(ih);
00997 buf.append(ih.toString(true) + " ");
00998 ih.next = ih.prev = null;
00999 } else
01000 ih.dispose();
01001 }
01002
01003 buf.append("}");
01004
01005 if(!target_vec.isEmpty()) {
01006 InstructionHandle[] targeted = new InstructionHandle[target_vec.size()];
01007 target_vec.copyInto(targeted);
01008 throw new TargetLostException(targeted, buf.toString());
01009 }
01010 }
01011
01012
01013 public void removeObserver(InstructionListObserver o) {
01014 if(observers != null)
01015 observers.removeElement(o);
01016 }
01017 public void setPositions() {
01018 setPositions(false);
01019 }
01020
01021
01022
01023
01024
01025
01026
01027 public void setPositions(boolean check) {
01028 int max_additional_bytes = 0, additional_bytes = 0;
01029 int index = 0, count = 0;
01030 int[] pos = new int[length];
01031
01032
01033
01034 if(check) {
01035 for(InstructionHandle ih=start; ih != null; ih = ih.next) {
01036 Instruction i = ih.instruction;
01037
01038 if(i instanceof BranchInstruction) {
01039 Instruction inst = ((BranchInstruction)i).getTarget().instruction;
01040 if(!contains(inst))
01041 throw new ClassGenException("Branch target of " +
01042 Constants.OPCODE_NAMES[i.tag] + ":" +
01043 inst + " not in instruction list");
01044
01045 if(i instanceof Select) {
01046 InstructionHandle[] targets = ((Select)i).getTargets();
01047
01048 for(int j=0; j < targets.length; j++) {
01049 inst = targets[j].instruction;
01050 if(!contains(inst))
01051 throw new ClassGenException("Branch target of " +
01052 Constants.OPCODE_NAMES[i.tag] + ":" +
01053 inst + " not in instruction list");
01054 }
01055 }
01056
01057 if(!(ih instanceof BranchHandle))
01058 throw new ClassGenException("Branch instruction " +
01059 Constants.OPCODE_NAMES[i.tag] + ":" +
01060 inst + " not contained in BranchHandle.");
01061
01062 }
01063 }
01064 }
01065
01066
01067
01068
01069 for(InstructionHandle ih=start; ih != null; ih = ih.next) {
01070 Instruction i = ih.instruction;
01071
01072 ih.setPosition(index);
01073 pos[count++] = index;
01074
01075
01076
01077
01078
01079
01080 switch(i.getTag()) {
01081 case Constants.JSR: case Constants.GOTO:
01082 max_additional_bytes += 2;
01083 break;
01084
01085 case Constants.TABLESWITCH: case Constants.LOOKUPSWITCH:
01086 max_additional_bytes += 3;
01087 break;
01088 }
01089
01090 index += i.getLength();
01091 }
01092
01093
01094
01095
01096
01097 for(InstructionHandle ih=start; ih != null; ih = ih.next)
01098 additional_bytes += ih.updatePosition(additional_bytes, max_additional_bytes);
01099
01100
01101
01102
01103 index=count=0;
01104 for(InstructionHandle ih=start; ih != null; ih = ih.next) {
01105 Instruction i = ih.instruction;
01106
01107 ih.setPosition(index);
01108 pos[count++] = index;
01109 index += i.getLength();
01110 }
01111
01112 byte_positions = new int[count];
01113 System.arraycopy(pos, 0, byte_positions, 0, count);
01114 }
01115
01116
01117
01118 public int size() { return length; }
01119 public String toString() {
01120 return toString(true);
01121 }
01122
01123
01124
01125
01126 public String toString(boolean verbose) {
01127 StringBuffer buf = new StringBuffer();
01128
01129 for(InstructionHandle ih=start; ih != null; ih = ih.next) {
01130 buf.append(ih.toString(verbose) + "\n");
01131 }
01132
01133 return buf.toString();
01134 }
01135
01136
01137
01138
01139 public void update() {
01140 if(observers != null)
01141 for(Enumeration e = observers.elements(); e.hasMoreElements(); )
01142 ((InstructionListObserver)e.nextElement()).notify(this);
01143 }
01144 }