1 package org.sentrysoftware.jawk.intermediate; 2 3 /*- 4 * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ 5 * Jawk 6 * ჻჻჻჻჻჻ 7 * Copyright (C) 2006 - 2023 Sentry Software 8 * ჻჻჻჻჻჻ 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public License as 11 * published by the Free Software Foundation, either version 3 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Lesser Public License for more details. 18 * 19 * You should have received a copy of the GNU General Lesser Public 20 * License along with this program. If not, see 21 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 22 * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ 23 */ 24 25 import java.io.IOException; 26 import java.io.InvalidClassException; 27 import java.io.ObjectInputStream; 28 import java.io.ObjectOutputStream; 29 import java.io.PrintStream; 30 import java.io.Serializable; 31 import java.lang.reflect.Field; 32 import java.lang.reflect.Modifier; 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.HashSet; 36 import java.util.Map; 37 import java.util.Set; 38 39 import org.sentrysoftware.jawk.util.AwkLogger; 40 import org.sentrysoftware.jawk.util.LinkedListStackImpl; 41 import org.sentrysoftware.jawk.util.MyStack; 42 import org.slf4j.Logger; 43 44 /** 45 * <p>AwkTuples class.</p> 46 * 47 * @author Danny Daglas 48 */ 49 public class AwkTuples implements Serializable { 50 51 private static final long serialVersionUID = 2L; 52 53 /** Our logger */ 54 private static final Logger LOG = AwkLogger.getLogger(AwkTuples.class); 55 56 /** Version Manager */ 57 private VersionManager version_manager = new VersionManager(); 58 59 private static final class AddressImpl implements Address, Serializable { 60 61 /** 62 * 63 */ 64 private static final long serialVersionUID = 109610985341478678L; 65 private String lbl; 66 private int idx = -1; 67 68 private AddressImpl(String lbl) { 69 this.lbl = lbl; 70 } 71 72 @Override 73 public String label() { 74 return lbl; 75 } 76 77 @Override 78 public String toString() { 79 return label(); 80 } 81 82 @Override 83 public void assignIndex(int idx) { 84 this.idx = idx; 85 } 86 87 @Override 88 public int index() { 89 assert idx >= 0 : toString(); 90 return idx; 91 } 92 } 93 94 private class PositionImpl implements PositionForInterpretation, PositionForCompilation { 95 // index within the queue 96 97 private int idx = 0; 98 private Tuple tuple = queue.isEmpty() ? null : queue.get(idx); // current tuple 99 100 @Override 101 public int index() { 102 return idx; 103 } 104 105 @Override 106 public boolean isEOF() { 107 return idx >= queue.size(); 108 } 109 110 @Override 111 public void next() { 112 assert tuple != null; 113 ++idx; 114 tuple = tuple.getNext(); 115 assert queue.size() == idx || queue.get(idx) == tuple; 116 } 117 118 @Override 119 public void jump(Address address) { 120 tuple = queue.get(idx = address.index()); 121 } 122 123 @Override 124 public String toString() { 125 return "[" + idx + "]-->" + tuple.toString(); 126 } 127 128 @Override 129 public int opcode() { 130 return tuple.getOpcode(); 131 } 132 133 @Override 134 public long intArg(int arg_idx) { 135 Class<?> c = tuple.getTypes()[arg_idx]; 136 if (c == Long.class) { 137 return tuple.getInts()[arg_idx]; 138 } 139 throw new Error("Invalid arg type: " + c + ", arg_idx = " + arg_idx + ", tuple = " + tuple); 140 } 141 142 @Override 143 public boolean boolArg(int arg_idx) { 144 Class<?> c = tuple.getTypes()[arg_idx]; 145 if (c == Boolean.class) { 146 return tuple.getBools()[arg_idx]; 147 } 148 throw new Error("Invalid arg type: " + c + ", arg_idx = " + arg_idx + ", tuple = " + tuple); 149 } 150 151 @Override 152 public Object arg(int arg_idx) { 153 Class<?> c = tuple.getTypes()[arg_idx]; 154 if (c == Long.class) { 155 return tuple.getInts()[arg_idx]; 156 } 157 if (c == Double.class) { 158 return tuple.getDoubles()[arg_idx]; 159 } 160 if (c == String.class) { 161 return tuple.getStrings()[arg_idx]; 162 } 163 if (c == Address.class) { 164 assert arg_idx == 0; 165 return tuple.getAddress(); 166 } 167 throw new Error("Invalid arg type: " + c + ", arg_idx = " + arg_idx + ", tuple = " + tuple); 168 } 169 170 @Override 171 public Address addressArg() { 172 assert tuple.getAddress() != null || tuple.getHasFuncAddr() != null : "tuple.address = " + tuple.getAddress() + ", tuple.has_func_addr = " + tuple.getHasFuncAddr(); 173 if (tuple.getAddress() == null) { 174 tuple.setAddress(tuple.getHasFuncAddr().getFunctionAddress()); 175 } 176 return tuple.getAddress(); 177 } 178 179 @Override 180 public Class<?> classArg() { 181 //Tuple tuple = queue.get(idx); 182 assert tuple.getCls() != null; 183 return tuple.getCls(); 184 } 185 186 @Override 187 public int lineNumber() { 188 assert tuple.getLineno() != -1 : "The line number should have been set by queue.add(), but was not."; 189 return tuple.getLineno(); 190 } 191 192 @Override 193 public int current() { 194 return idx; 195 } 196 197 @Override 198 public void jump(int idx) { 199 tuple = queue.get(this.idx = idx); 200 } 201 } 202 203 // made public to access static members of AwkTuples via Java Reflection 204 private static final class Tuple implements Serializable { 205 206 /** 207 * 208 */ 209 private static final long serialVersionUID = 8105941219003992817L; 210 private int opcode; 211 private long[] ints = new long[4]; 212 private boolean[] bools = new boolean[4]; 213 private double[] doubles = new double[4]; 214 private String[] strings = new String[4]; 215 private Class<?>[] types = new Class[4]; 216 private Address address = null; 217 private Class<?> cls = null; 218 private transient HasFunctionAddress hasFuncAddr = null; 219 // to avoid polluting the constructors, 220 // setLineNumber(int) populates this field 221 // (called by an anonymous inner subclass of ArrayList, 222 // assigned to queue - see above) 223 private int lineno = -1; 224 private Tuple next = null; 225 226 private Tuple(int opcode) { 227 this.opcode = opcode; 228 } 229 230 private Tuple(int opcode, long i1) { 231 this(opcode); 232 ints[0] = i1; 233 types[0] = Long.class; 234 } 235 236 private Tuple(int opcode, long i1, long i2) { 237 this(opcode, i1); 238 ints[1] = i2; 239 types[1] = Long.class; 240 } 241 242 private Tuple(int opcode, long i1, boolean b2) { 243 this(opcode, i1); 244 bools[1] = b2; 245 types[1] = Boolean.class; 246 } 247 248 private Tuple(int opcode, long i1, boolean b2, boolean b3) { 249 this(opcode, i1, b2); 250 bools[2] = b3; 251 types[2] = Boolean.class; 252 } 253 254 private Tuple(int opcode, double d1) { 255 this(opcode); 256 doubles[0] = d1; 257 types[0] = Double.class; 258 } 259 260 private Tuple(int opcode, String s1) { 261 this(opcode); 262 strings[0] = s1; 263 types[0] = String.class; 264 } 265 266 private Tuple(int opcode, boolean b1) { 267 this(opcode); 268 bools[0] = b1; 269 types[0] = Boolean.class; 270 } 271 272 private Tuple(int opcode, String s1, long i2) { 273 this(opcode, s1); 274 ints[1] = i2; 275 types[1] = Long.class; 276 } 277 278 private Tuple(int opcode, Address address) { 279 this(opcode); 280 this.address = address; 281 types[0] = Address.class; 282 } 283 284 private Tuple(int opcode, String strarg, long intarg, boolean boolarg) { 285 this(opcode, strarg, intarg); 286 bools[2] = boolarg; 287 types[2] = Boolean.class; 288 } 289 290 private Tuple(int opcode, HasFunctionAddress has_func_addr, String s2, long i3, long i4) { 291 this(opcode); 292 this.hasFuncAddr = has_func_addr; 293 strings[1] = s2; 294 types[1] = String.class; 295 ints[2] = i3; 296 types[2] = Long.class; 297 ints[3] = i4; 298 types[3] = Long.class; 299 } 300 301 private Tuple(int opcode, Class<?> cls) { 302 this(opcode); 303 this.cls = cls; 304 types[0] = Class.class; 305 } 306 307 private Tuple(int opcode, String s1, String s2) { 308 this(opcode, s1); 309 strings[1] = s2; 310 types[1] = String.class; 311 } 312 313 private boolean hasNext() { 314 return (next != null); 315 } 316 317 private Tuple getNext() { 318 return next; 319 } 320 321 private void setNext(Tuple next) { 322 this.next = next; 323 } 324 325 private void setLineNumber(int lineno) { 326 assert this.lineno == -1 : "The line number was already set to " + this.lineno + ". Later lineno = " + lineno + "."; 327 this.lineno = lineno; 328 } 329 330 @Override 331 public String toString() { 332 StringBuilder sb = new StringBuilder(); 333 sb.append(toOpcodeString(opcode)); 334 int idx = 0; 335 while ((idx < types.length) && (types[idx] != null)) { 336 sb.append(", "); 337 Class<?> type = types[idx]; 338 if (type == Long.class) { 339 sb.append(ints[idx]); 340 } else if (type == Boolean.class) { 341 sb.append(bools[idx]); 342 } else if (type == Double.class) { 343 sb.append(doubles[idx]); 344 } else if (type == String.class) { 345 sb.append('"').append(strings[idx]).append('"'); 346 } else if (type == Address.class) { 347 assert (idx == 0); 348 sb.append(address); 349 } else if (type == Class.class) { 350 assert (idx == 0); 351 sb.append(cls); 352 } else if (type == HasFunctionAddress.class) { 353 assert (idx == 0); 354 sb.append(hasFuncAddr); 355 } else { 356 throw new Error("Unknown param type (" + idx + "): " + type); 357 } 358 ++idx; 359 } 360 return sb.toString(); 361 } 362 363 /** 364 * Update this tuple to populate the address argument value if necessary; 365 * and, check if address points to a proper element in the tuple queue. 366 * <p> 367 * The address will be updated only if there exists a HasFunctionAddress 368 * argument for this tuple. 369 * 370 * <p> 371 * This is executed after the tuples are constructed so that function address 372 * references can be resolved. Otherwise, forward declared functions will 373 * not be resolved in the Tuple list. 374 * 375 */ 376 public void touch(java.util.List<Tuple> queue) { 377 assert lineno != -1 : "The line number should have been set by queue.add(), but was not."; 378 if (hasFuncAddr != null) { 379 address = hasFuncAddr.getFunctionAddress(); 380 types[0] = Address.class; 381 } 382 if (address != null) { 383 if (address.index() == -1) { 384 throw new Error("address " + address + " is unresolved"); 385 } 386 if (address.index() >= queue.size()) { 387 throw new Error("address " + address + " doesn't resolve to an actual list element"); 388 } 389 } 390 } 391 392 private int getOpcode() { 393 return opcode; 394 } 395 396 private long[] getInts() { 397 return ints; 398 } 399 400 private boolean[] getBools() { 401 return bools; 402 } 403 404 private double[] getDoubles() { 405 return doubles; 406 } 407 408 private String[] getStrings() { 409 return strings; 410 } 411 412 private Class<?>[] getTypes() { 413 return types; 414 } 415 416 private void setAddress(Address address) { 417 this.address = address; 418 } 419 420 private Address getAddress() { 421 return address; 422 } 423 424 private int getLineno() { 425 return lineno; 426 } 427 428 @SuppressWarnings("unused") 429 private void setOpcode(int opcode) { 430 this.opcode = opcode; 431 } 432 433 private Class<?> getCls() { 434 return cls; 435 } 436 437 private HasFunctionAddress getHasFuncAddr() { 438 return hasFuncAddr; 439 } 440 } 441 442 // made public to be accessable via Java Reflection 443 // (see toOpcodeString() method below) 444 445 /** 446 * Pops an item off the operand stack. 447 * <p> 448 * Stack before: x ...<br/> 449 * Stack after: ... 450 * 451 */ 452 public static final int _POP_ = 257; // x -> 0 453 /** 454 * Pushes an item onto the operand stack. 455 * <p> 456 * Stack before: ...<br/> 457 * Stack after: x ... 458 * 459 */ 460 public static final int _PUSH_ = 258; // 0 -> x 461 /** 462 * Pops and evaluates the top-of-stack; if 463 * false, it jumps to a specified address. 464 * <p> 465 * Argument: address 466 * 467 * <p> 468 * Stack before: x ...<br/> 469 * Stack after: ... 470 * 471 */ 472 public static final int _IFFALSE_ = 259; // x -> 0 473 /** 474 * Converts the top-of-stack to a number. 475 * <p> 476 * Stack before: x ...<br/> 477 * Stack after: x (as a number) 478 * 479 */ 480 public static final int _TO_NUMBER_ = 260; // x1 -> x2 481 /** 482 * Pops and evaluates the top-of-stack; if 483 * true, it jumps to a specified address. 484 * <p> 485 * Argument: address 486 * 487 * <p> 488 * Stack before: x ...<br/> 489 * Stack after: ... 490 * 491 */ 492 public static final int _IFTRUE_ = 261; // x -> 0 493 /** 494 * Jumps to a specified address. The operand stack contents 495 * are unaffected. 496 */ 497 public static final int _GOTO_ = 262; // 0 -> 0 498 /** 499 * A no-operation. The operand stack contents are 500 * unaffected. 501 */ 502 public static final int _NOP_ = 263; // 0 -> 0 503 /** 504 * Prints N number of items that are on the operand stack. 505 * The number of items are passed in as a tuple argument. 506 * <p> 507 * Argument: # of items (N) 508 * 509 * <p> 510 * Stack before: x1 x2 x3 .. xN ...<br/> 511 * Stack after: ... 512 * 513 */ 514 public static final int _PRINT_ = 264; // x1, x2, ... xn -> 0 515 /** 516 * Prints N number of items that are on the operand stack to 517 * a specified file. The file is passed in on the stack. 518 * The number of items are passed in as a tuple argument, 519 * as well as whether to overwrite the file or not (append mode). 520 * <p> 521 * Argument 1: # of items (N)<br/> 522 * Argument 2: true = append, false = overwrite 523 * 524 * <p> 525 * Stack before: x1 x2 x3 .. xN filename ...<br/> 526 * Stack after: ... 527 * 528 */ 529 public static final int _PRINT_TO_FILE_ = 265; // x1, x2, ... xn -> 0 530 /** 531 * Prints N number of items that are on the operand stack to 532 * a process executing a specified command (via a pipe). 533 * The command string is passed in on the stack. 534 * The number of items are passed in as a tuple argument. 535 * <p> 536 * Argument: # of items (N) 537 * 538 * <p> 539 * Stack before: x1 x2 x3 .. xN command-string ...<br/> 540 * Stack after: ... 541 * 542 */ 543 public static final int _PRINT_TO_PIPE_ = 266; // x1, x2, ... xn -> 0 544 /** 545 * Performs a formatted print of N items that are on the operand stack. 546 * The number of items are passed in as a tuple argument. 547 * <p> 548 * Argument: # of items (N) 549 * 550 * <p> 551 * Stack before: x1 x2 x3 .. xN ...<br/> 552 * Stack after: ... 553 * 554 */ 555 public static final int _PRINTF_ = 267; // x1, x2, ... xn -> 0 556 /** 557 * Performs a formatted print of N items that are on the operand stack to 558 * a specified file. The file is passed in on the stack. 559 * The number of items are passed in as a tuple argument, 560 * as well as whether to overwrite the file or not (append mode). 561 * <p> 562 * Argument 1: # of items (N)<br/> 563 * Argument 2: true = append, false = overwrite 564 * 565 * <p> 566 * Stack before: x1 x2 x3 .. xN filename ...<br/> 567 * Stack after: ... 568 * 569 */ 570 public static final int _PRINTF_TO_FILE_ = 268; // x1, x2, ... xn -> 0 571 /** 572 * Performs a formatted print of N items that are on the operand stack to 573 * a process executing a specified command (via a pipe). 574 * The command string is passed in on the stack. 575 * The number of items are passed in as a tuple argument. 576 * <p> 577 * Argument: # of items (N) 578 * 579 * <p> 580 * Stack before: x1 x2 x3 .. xN command-string ...<br/> 581 * Stack after: ... 582 * 583 */ 584 public static final int _PRINTF_TO_PIPE_ = 269; // x1, x2, ... xn -> 0 585 /** Constant <code>_SPRINTF_=270</code> */ 586 public static final int _SPRINTF_ = 270; // x1, x2, ... xn -> 0 587 /** 588 * Depending on the argument, pop and evaluate the string length of the top-of-stack 589 * or evaluate the string length of $0; in either case, push the result onto 590 * the stack. 591 * <p> 592 * The input field length evaluation mode is provided to support backward 593 * compatibility with the deprecated usage of length (i.e., no arguments). 594 * 595 * <p> 596 * Argument: 0 to use $0, use top-of-stack otherwise 597 * 598 * <p> 599 * If argument is 0: 600 * <blockquote> 601 * Stack before: ...<br/> 602 * Stack after: length-of-$0 ... 603 * </blockquote> 604 * else 605 * <blockquote> 606 * Stack before: x ...<br/> 607 * Stack after: length-of-x ... 608 * </blockquote> 609 * 610 */ 611 public static final int _LENGTH_ = 271; // 0 -> x or x1 -> x2 612 /** 613 * Pop and concatenate two strings from the top-of-stack; push the result onto 614 * the stack. 615 * <p> 616 * Stack before: x y ...<br/> 617 * Stack after: x-concatenated-with-y ... 618 * 619 */ 620 public static final int _CONCAT_ = 272; // x2, x1 -> x1x2 621 /** 622 * Assigns the top-of-stack to a variable. The contents of the stack 623 * are unaffected. 624 * <p> 625 * Argument 1: offset of the particular variable into the variable manager<br/> 626 * Argument 2: whether the variable is global or local 627 * 628 * <p> 629 * Stack before: x ...<br/> 630 * Stack after: x ... 631 * 632 */ 633 public static final int _ASSIGN_ = 273; // x -> 0 634 /** 635 * Assigns an item to an array element. The item remains on the stack. 636 * <p> 637 * Argument 1: offset of the particular associative array into the variable manager<br/> 638 * Argument 2: whether the associative array is global or local 639 * 640 * <p> 641 * Stack before: index-into-array item ...<br/> 642 * Stack after: item ... 643 * 644 */ 645 public static final int _ASSIGN_ARRAY_ = 274; // x2, x1 -> 0 646 /** 647 * Assigns the top-of-stack to $0. The contents of the stack are unaffected. 648 * Upon assignment, individual field variables are recalculated. 649 * <p> 650 * Stack before: x ...<br/> 651 * Stack after: x ... 652 * 653 */ 654 public static final int _ASSIGN_AS_INPUT_ = 275; // x -> 0 655 /** 656 * Assigns an item as a particular input field; the field number can be 0. 657 * Upon assignment, associating input fields are affected. For example, if 658 * the following assignment were made: 659 * <blockquote> 660 * <pre> 661 * $3 = "hi" 662 * </pre> 663 * </blockquote> 664 * $0 would be recalculated. Likewise, if the following assignment were made: 665 * <blockquote> 666 * <pre> 667 * $0 = "hello there" 668 * </pre> 669 * </blockquote> 670 * $1, $2, ... would be recalculated. 671 * <p> 672 * Stack before: field-num x ...<br/> 673 * Stack after: x ... 674 * 675 */ 676 public static final int _ASSIGN_AS_INPUT_FIELD_ = 276; // x, y -> x 677 /** 678 * Obtains an item from the variable manager and push it onto the stack. 679 * <p> 680 * Argument 1: offset of the particular variable into the variable manager<br/> 681 * Argument 2: whether the variable is global or local 682 * 683 * <p> 684 * Stack before: ...<br/> 685 * Stack after: x ... 686 * 687 */ 688 public static final int _DEREFERENCE_ = 277; // 0 -> x 689 /** 690 * Increase the contents of the variable by an adjustment value; 691 * assigns the result to the variable and pushes the result onto the stack. 692 * <p> 693 * Argument 1: offset of the particular variable into the variable manager<br/> 694 * Argument 2: whether the variable is global or local 695 * 696 * <p> 697 * Stack before: n ...<br/> 698 * Stack after: x+n ... 699 * 700 */ 701 public static final int _PLUS_EQ_ = 278; // x -> x 702 /** 703 * Decreases the contents of the variable by an adjustment value; 704 * assigns the result to the variable and pushes the result onto the stack. 705 * <p> 706 * Argument 1: offset of the particular variable into the variable manager<br/> 707 * Argument 2: whether the variable is global or local 708 * 709 * <p> 710 * Stack before: n ...<br/> 711 * Stack after: x-n ... 712 * 713 */ 714 public static final int _MINUS_EQ_ = 279; // x -> x 715 /** 716 * Multiplies the contents of the variable by an adjustment value; 717 * assigns the result to the variable and pushes the result onto the stack. 718 * <p> 719 * Argument 1: offset of the particular variable into the variable manager<br/> 720 * Argument 2: whether the variable is global or local 721 * 722 * <p> 723 * Stack before: n ...<br/> 724 * Stack after: x*n ... 725 * 726 */ 727 public static final int _MULT_EQ_ = 280; // x -> x 728 /** 729 * Divides the contents of the variable by an adjustment value; 730 * assigns the result to the variable and pushes the result onto the stack. 731 * <p> 732 * Argument 1: offset of the particular variable into the variable manager<br/> 733 * Argument 2: whether the variable is global or local 734 * 735 * <p> 736 * Stack before: n ...<br/> 737 * Stack after: x/n ... 738 * 739 */ 740 public static final int _DIV_EQ_ = 281; // x -> x 741 /** 742 * Takes the modules of the contents of the variable by an adjustment value; 743 * assigns the result to the variable and pushes the result onto the stack. 744 * <p> 745 * Argument 1: offset of the particular variable into the variable manager<br/> 746 * Argument 2: whether the variable is global or local 747 * 748 * <p> 749 * Stack before: n ...<br/> 750 * Stack after: x%n ... 751 * 752 */ 753 public static final int _MOD_EQ_ = 282; // x -> x 754 /** 755 * Raises the contents of the variable to the power of the adjustment value; 756 * assigns the result to the variable and pushes the result onto the stack. 757 * <p> 758 * Argument 1: offset of the particular variable into the variable manager<br/> 759 * Argument 2: whether the variable is global or local 760 * 761 * <p> 762 * Stack before: n ...<br/> 763 * Stack after: x^n ... 764 * 765 */ 766 public static final int _POW_EQ_ = 283; // x -> x 767 /** 768 * Increase the contents of an indexed array by an adjustment value; 769 * assigns the result to the array and pushes the result onto the stack. 770 * <p> 771 * Argument 1: offset of the associative array into the variable manager<br/> 772 * Argument 2: whether the associative array is global or local 773 * 774 * <p> 775 * Stack before: array-idx n ...<br/> 776 * Stack after: x+n ... 777 * 778 */ 779 public static final int _PLUS_EQ_ARRAY_ = 284; // x -> x 780 /** 781 * Decreases the contents of an indexed array by an adjustment value; 782 * assigns the result to the array and pushes the result onto the stack. 783 * <p> 784 * Argument 1: offset of the associative array into the variable manager<br/> 785 * Argument 2: whether the associative array is global or local 786 * 787 * <p> 788 * Stack before: array-idx n ...<br/> 789 * Stack after: x-n ... 790 * 791 */ 792 public static final int _MINUS_EQ_ARRAY_ = 285; // x -> x 793 /** 794 * Multiplies the contents of an indexed array by an adjustment value; 795 * assigns the result to the array and pushes the result onto the stack. 796 * <p> 797 * Argument 1: offset of the associative array into the variable manager<br/> 798 * Argument 2: whether the associative array is global or local 799 * 800 * <p> 801 * Stack before: array-idx n ...<br/> 802 * Stack after: x*n ... 803 * 804 */ 805 public static final int _MULT_EQ_ARRAY_ = 286; // x -> x 806 /** 807 * Divides the contents of an indexed array by an adjustment value; 808 * assigns the result to the array and pushes the result onto the stack. 809 * <p> 810 * Argument 1: offset of the associative array into the variable manager<br/> 811 * Argument 2: whether the associative array is global or local 812 * 813 * <p> 814 * Stack before: array-idx n ...<br/> 815 * Stack after: x/n ... 816 * 817 */ 818 public static final int _DIV_EQ_ARRAY_ = 287; // x -> x 819 /** 820 * Takes the modulus of the contents of an indexed array by an adjustment value; 821 * assigns the result to the array and pushes the result onto the stack. 822 * <p> 823 * Argument 1: offset of the associative array into the variable manager<br/> 824 * Argument 2: whether the associative array is global or local 825 * 826 * <p> 827 * Stack before: array-idx n ...<br/> 828 * Stack after: x%n ... 829 * 830 */ 831 public static final int _MOD_EQ_ARRAY_ = 288; // x -> x 832 /** 833 * Raises the contents of an indexed array to the power of an adjustment value; 834 * assigns the result to the array and pushes the result onto the stack. 835 * <p> 836 * Argument 1: offset of the associative array into the variable manager<br/> 837 * Argument 2: whether the associative array is global or local 838 * 839 * <p> 840 * Stack before: array-idx n ...<br/> 841 * Stack after: x^n ... 842 * 843 */ 844 public static final int _POW_EQ_ARRAY_ = 289; // x -> x 845 /** 846 * Increases the contents of an input field by an adjustment value; 847 * assigns the result to the input field and pushes the result onto the stack. 848 * <p> 849 * Stack before: input-field_number n ...<br/> 850 * Stack after: x+n ... 851 * 852 */ 853 public static final int _PLUS_EQ_INPUT_FIELD_ = 290; // x1,x2 -> x 854 /** 855 * Decreases the contents of an input field by an adjustment value; 856 * assigns the result to the input field and pushes the result onto the stack. 857 * <p> 858 * Stack before: input-field_number n ...<br/> 859 * Stack after: x-n ... 860 * 861 */ 862 public static final int _MINUS_EQ_INPUT_FIELD_ = 291; // x1,x2 -> x 863 /** 864 * Multiplies the contents of an input field by an adjustment value; 865 * assigns the result to the input field and pushes the result onto the stack. 866 * <p> 867 * Stack before: input-field_number n ...<br/> 868 * Stack after: x*n ... 869 * 870 */ 871 public static final int _MULT_EQ_INPUT_FIELD_ = 292; // x1,x2 -> x 872 /** 873 * Divides the contents of an input field by an adjustment value; 874 * assigns the result to the input field and pushes the result onto the stack. 875 * <p> 876 * Stack before: input-field_number n ...<br/> 877 * Stack after: x/n ... 878 * 879 */ 880 public static final int _DIV_EQ_INPUT_FIELD_ = 293; // x1,x2 -> x 881 /** 882 * Takes the modulus of the contents of an input field by an adjustment value; 883 * assigns the result to the input field and pushes the result onto the stack. 884 * <p> 885 * Stack before: input-field_number n ...<br/> 886 * Stack after: x%n ... 887 * 888 */ 889 public static final int _MOD_EQ_INPUT_FIELD_ = 294; // x1,x2 -> x 890 /** 891 * Raises the contents of an input field to the power of an adjustment value; 892 * assigns the result to the input field and pushes the result onto the stack. 893 * <p> 894 * Stack before: input-field_number n ...<br/> 895 * Stack after: x^n ... 896 * 897 */ 898 public static final int _POW_EQ_INPUT_FIELD_ = 295; // x1,x2 -> x 899 900 /** 901 * Seeds the random number generator. If there are no arguments, the current 902 * time (as a long value) is used as the seed. Otherwise, the top-of-stack is 903 * popped and used as the seed value. 904 * <p> 905 * Argument: # of arguments 906 * 907 * <p> 908 * If # of arguments is 0: 909 * <blockquote> 910 * Stack before: ...<br/> 911 * Stack after: old-seed ... 912 * </blockquote> 913 * else 914 * <blockquote> 915 * Stack before: x ...<br/> 916 * Stack after: old-seed ... 917 * </blockquote> 918 * 919 */ 920 public static final int _SRAND_ = 296; // x2, x1 -> x1, x2 921 /** 922 * Obtains the next random number from the random number generator 923 * and push it onto the stack. 924 * <p> 925 * Stack before: ...<br/> 926 * Stack after: random-number ... 927 * 928 */ 929 public static final int _RAND_ = 297; // x2, x1 -> x1, x2 930 /** 931 * Built-in function that pops the top-of-stack, removes its fractional part, 932 * if any, and places the result onto the stack. 933 * <p> 934 * Stack before: x ...<br/> 935 * Stack after: (int)x ... 936 * 937 */ 938 public static final int _INTFUNC_ = 298; // x2, x1 -> x1, x2 939 /** 940 * Built-in function that pops the top-of-stack, takes its square root, 941 * and places the result onto the stack. 942 * <p> 943 * Stack before: x ...<br/> 944 * Stack after: sqrt(x) ... 945 * 946 */ 947 public static final int _SQRT_ = 299; // x2, x1 -> x1, x2 948 /** 949 * Built-in function that pops the top-of-stack, calls the java.lang.Math.log method 950 * with the top-of-stack as the argument, and places the result onto the stack. 951 * <p> 952 * Stack before: x ...<br/> 953 * Stack after: log(x) ... 954 * 955 */ 956 public static final int _LOG_ = 300; // x2, x1 -> x1, x2 957 /** 958 * Built-in function that pops the top-of-stack, calls the java.lang.Math.exp method 959 * with the top-of-stack as the argument, and places the result onto the stack. 960 * <p> 961 * Stack before: x ...<br/> 962 * Stack after: exp(x) ... 963 * 964 */ 965 public static final int _EXP_ = 301; // x2, x1 -> x1, x2 966 /** 967 * Built-in function that pops the top-of-stack, calls the java.lang.Math.sin method 968 * with the top-of-stack as the argument, and places the result onto the stack. 969 * <p> 970 * Stack before: x ...<br/> 971 * Stack after: sin(x) ... 972 * 973 */ 974 public static final int _SIN_ = 302; // x2, x1 -> x1, x2 975 /** 976 * Built-in function that pops the top-of-stack, calls the java.lang.Math.cos method 977 * with the top-of-stack as the argument, and places the result onto the stack. 978 * <p> 979 * Stack before: x ...<br/> 980 * Stack after: cos(x) ... 981 * 982 */ 983 public static final int _COS_ = 303; // x2, x1 -> x1, x2 984 /** 985 * Built-in function that pops the first two items off the stack, 986 * calls the java.lang.Math.atan2 method 987 * with these as arguments, and places the result onto the stack. 988 * <p> 989 * Stack before: x1 x2 ...<br/> 990 * Stack after: atan2(x1,x2) ... 991 * 992 */ 993 public static final int _ATAN2_ = 304; // x2, x1 -> x1, x2 994 /** 995 * Built-in function that searches a string as input to a regular expression, 996 * the location of the match is pushed onto the stack. 997 * The RSTART and RLENGTH variables are set as a side effect. 998 * If a match is found, RSTART and function return value are set 999 * to the location of the match and RLENGTH is set to the length 1000 * of the substring matched against the regular expression. 1001 * If no match is found, RSTART (and return value) is set to 1002 * 0 and RLENGTH is set to -1. 1003 * <p> 1004 * Stack before: string regexp ...<br/> 1005 * Stack after: RSTART ... 1006 * 1007 */ 1008 public static final int _MATCH_ = 305; // x1, x2 -> x 1009 /** 1010 * Built-in function that locates a substring within a source string 1011 * and pushes the location onto the stack. If the substring is 1012 * not found, 0 is pushed onto the stack. 1013 * <p> 1014 * Stack before: string substring ...<br/> 1015 * Stack after: location-index ... 1016 * 1017 */ 1018 public static final int _INDEX_ = 306; // x1, x2 -> x 1019 /** 1020 * Built-in function that substitutes an occurrence (or all occurrences) 1021 * of a string in $0 and replaces it with another. 1022 * <p> 1023 * Argument: true if global sub, false otherwise. 1024 * 1025 * <p> 1026 * Stack before: regexp replacement-string ...<br/> 1027 * Stack after: ... 1028 * 1029 */ 1030 public static final int _SUB_FOR_DOLLAR_0_ = 307; // x -> 0 1031 /** 1032 * Built-in function that substitutes an occurrence (or all occurrences) 1033 * of a string in a field reference and replaces it with another. 1034 * <p> 1035 * Argument: true if global sub, false otherwise. 1036 * 1037 * <p> 1038 * Stack before: field-num regexp replacement-string ...<br/> 1039 * Stack after: ... 1040 * 1041 */ 1042 public static final int _SUB_FOR_DOLLAR_REFERENCE_ = 308; // x -> 0 1043 /** 1044 * Built-in function that substitutes an occurrence (or all occurrences) 1045 * of a string in a particular variable and replaces it with another. 1046 * <p> 1047 * Argument 1: variable offset in variable manager<br/> 1048 * Argument 2: is global variable<br/> 1049 * Argument 3: is global sub 1050 * 1051 * <p> 1052 * Stack before: regexp replacement-string orig-string ...<br/> 1053 * Stack after: ... 1054 * 1055 */ 1056 public static final int _SUB_FOR_VARIABLE_ = 309; // x -> 0 1057 /** 1058 * Built-in function that substitutes an occurrence (or all occurrences) 1059 * of a string in a particular array cell and replaces it with another. 1060 * <p> 1061 * Argument 1: array map offset in variable manager<br/> 1062 * Argument 2: is global array map<br/> 1063 * Argument 3: is global sub 1064 * 1065 * <p> 1066 * Stack before: array-index regexp replacement-string orig-string ...<br/> 1067 * Stack after: ... 1068 * 1069 */ 1070 public static final int _SUB_FOR_ARRAY_REFERENCE_ = 310; // x -> 0 1071 /** 1072 * Built-in function to split a string by a regexp and put the 1073 * components into an array. 1074 * <p> 1075 * Argument: # of arguments (parameters on stack) 1076 * 1077 * <p> 1078 * If # of arguments is 2: 1079 * <blockquote> 1080 * Stack before: string array ...<br/> 1081 * Stack after: n ... 1082 * </blockquote> 1083 * else 1084 * <blockquote> 1085 * Stack before: string array regexp ...<br/> 1086 * Stack after: n ... 1087 * </blockquote> 1088 * 1089 */ 1090 public static final int _SPLIT_ = 311; // x1 -> x2 1091 /** 1092 * Built-in function that pushes a substring of the top-of-stack 1093 * onto the stack. 1094 * The tuple argument indicates whether to limit the substring 1095 * to a particular end position, or to take the substring 1096 * up to the end-of-string. 1097 * <p> 1098 * Argument: # of arguments 1099 * 1100 * <p> 1101 * If # of arguments is 2: 1102 * <blockquote> 1103 * Stack before: string start-pos ...<br/> 1104 * Stack after: substring ... 1105 * </blockquote> 1106 * else 1107 * <blockquote> 1108 * Stack before: string start-pos end-pos ...<br/> 1109 * Stack after: substring ... 1110 * </blockquote> 1111 * 1112 */ 1113 public static final int _SUBSTR_ = 312; // x1 -> x2 1114 /** 1115 * Built-in function that converts all the letters in the top-of-stack 1116 * to lower case and pushes the result onto the stack. 1117 * <p> 1118 * Stack before: STRING-ARGUMENT ...<br/> 1119 * Stack after: string-argument ... 1120 * 1121 */ 1122 public static final int _TOLOWER_ = 313; // x1 -> x2 1123 /** 1124 * Built-in function that converts all the letters in the top-of-stack 1125 * to upper case and pushes the result onto the stack. 1126 * <p> 1127 * Stack before: string-argument ...<br/> 1128 * Stack after: STRING-ARGUMENT ... 1129 * 1130 */ 1131 public static final int _TOUPPER_ = 314; // x1 -> x2 1132 /** 1133 * Built-in function that executes the top-of-stack as a system command 1134 * and pushes the return code onto the stack. 1135 * <p> 1136 * Stack before: cmd ...<br/> 1137 * Stack after: return-code ... 1138 * 1139 */ 1140 public static final int _SYSTEM_ = 315; // x1 -> x2 1141 1142 /** 1143 * Swaps the top two elements of the stack. 1144 * <p> 1145 * Stack before: x1 x2 ...<br/> 1146 * Stack after: x2 x1 ... 1147 * 1148 */ 1149 public static final int _SWAP_ = 316; // x2, x1 -> x1, x2 1150 1151 /** 1152 * Numerically adds the top two elements of the stack with the result 1153 * pushed onto the stack. 1154 * <p> 1155 * Stack before: x1 x2 ...<br/> 1156 * Stack after: x1+x2 ... 1157 * 1158 */ 1159 public static final int _ADD_ = 317; // x2, x1 -> x1+x2 1160 /** 1161 * Numerically subtracts the top two elements of the stack with the result 1162 * pushed onto the stack. 1163 * <p> 1164 * Stack before: x1 x2 ...<br/> 1165 * Stack after: x1-x2 ... 1166 * 1167 */ 1168 public static final int _SUBTRACT_ = 318; // x2, x1 -> x1-x2 1169 /** 1170 * Numerically multiplies the top two elements of the stack with the result 1171 * pushed onto the stack. 1172 * <p> 1173 * Stack before: x1 x2 ...<br/> 1174 * Stack after: x1*x2 ... 1175 * 1176 */ 1177 public static final int _MULTIPLY_ = 319; // x2, x1 -> x1*x2 1178 /** 1179 * Numerically divides the top two elements of the stack with the result 1180 * pushed onto the stack. 1181 * <p> 1182 * Stack before: x1 x2 ...<br/> 1183 * Stack after: x1/x2 ... 1184 * 1185 */ 1186 public static final int _DIVIDE_ = 320; // x2, x1 -> x1/x2 1187 /** 1188 * Numerically takes the modulus of the top two elements of the stack with the result 1189 * pushed onto the stack. 1190 * <p> 1191 * Stack before: x1 x2 ...<br/> 1192 * Stack after: x1%x2 ... 1193 * 1194 */ 1195 public static final int _MOD_ = 321; // x2, x1 -> x1/x2 1196 /** 1197 * Numerically raises the top element to the power of the next element with the result 1198 * pushed onto the stack. 1199 * <p> 1200 * Stack before: x1 x2 ...<br/> 1201 * Stack after: x1^x2 ... 1202 * 1203 */ 1204 public static final int _POW_ = 322; // x2, x1 -> x1/x2 1205 1206 /** 1207 * Increases the variable reference by one; pushes the result 1208 * onto the stack. 1209 * <p> 1210 * Argument 1: offset of the particular variable into the variable manager<br/> 1211 * Argument 2: whether the variable is global or local 1212 * 1213 * <p> 1214 * Stack before: ...<br/> 1215 * Stack after: x+1 ... 1216 * 1217 */ 1218 public static final int _INC_ = 323; // 0 -> x 1219 /** 1220 * Decreases the variable reference by one; pushes the result 1221 * onto the stack. 1222 * <p> 1223 * Argument 1: offset of the particular variable into the variable manager<br/> 1224 * Argument 2: whether the variable is global or local 1225 * 1226 * <p> 1227 * Stack before: ...<br/> 1228 * Stack after: x-1 ... 1229 * 1230 */ 1231 public static final int _DEC_ = 324; // 0 -> x 1232 /** 1233 * Increases the array element reference by one; pushes the result 1234 * onto the stack. 1235 * <p> 1236 * Argument 1: offset of the associative array into the variable manager<br/> 1237 * Argument 2: whether the associative array is global or local 1238 * 1239 * <p> 1240 * Stack before: array-idx ...<br/> 1241 * Stack after: x+1 ... 1242 * 1243 */ 1244 public static final int _INC_ARRAY_REF_ = 325; // x -> x 1245 /** 1246 * Decreases the array element reference by one; pushes the result 1247 * onto the stack. 1248 * <p> 1249 * Argument 1: offset of the associative array into the variable manager<br/> 1250 * Argument 2: whether the associative array is global or local 1251 * 1252 * <p> 1253 * Stack before: array-idx ...<br/> 1254 * Stack after: x-1 ... 1255 * 1256 */ 1257 public static final int _DEC_ARRAY_REF_ = 326; // x -> x 1258 /** 1259 * Increases the input field variable by one; pushes the result 1260 * onto the stack. 1261 * <p> 1262 * Stack before: field-idx ...<br/> 1263 * Stack after: x+1 1264 * 1265 */ 1266 public static final int _INC_DOLLAR_REF_ = 327; // x -> x 1267 /** 1268 * Decreases the input field variable by one; pushes the result 1269 * onto the stack. 1270 * <p> 1271 * Stack before: field-idx ...<br/> 1272 * Stack after: x-1 1273 * 1274 */ 1275 public static final int _DEC_DOLLAR_REF_ = 328; // x -> x 1276 1277 /** 1278 * Duplicates the top-of-stack on the stack. 1279 * <p> 1280 * Stack before: x ...<br/> 1281 * Stack after: x x ... 1282 * 1283 */ 1284 public static final int _DUP_ = 329; // x -> x, x 1285 /** 1286 * Evaluates the logical NOT of the top stack element; 1287 * pushes the result onto the stack. 1288 * <p> 1289 * Stack before: x ...<br/> 1290 * Stack after: !x ... 1291 * 1292 */ 1293 public static final int _NOT_ = 330; // x -> !x 1294 /** 1295 * Evaluates the numerical NEGATION of the top stack element; 1296 * pushes the result onto the stack. 1297 * <p> 1298 * Stack before: x ...<br/> 1299 * Stack after: -x ... 1300 * 1301 */ 1302 public static final int _NEGATE_ = 331; // x -> -x 1303 1304 /** 1305 * Compares the top two stack elements; pushes 1 onto the stack if equal, 0 if not equal. 1306 * <p> 1307 * Stack before: x1 x2 ...<br/> 1308 * Stack after: x1==x2 1309 * 1310 */ 1311 public static final int _CMP_EQ_ = 332; // x2, x1 -> x1 == x2 1312 /** 1313 * Compares the top two stack elements; pushes 1 onto the stack if x1 < x2, 0 if not equal. 1314 * <p> 1315 * Stack before: x1 x2 ...<br/> 1316 * Stack after: x1<x2 1317 * 1318 */ 1319 public static final int _CMP_LT_ = 333; // x2, x1 -> x1 < x2 1320 /** 1321 * Compares the top two stack elements; pushes 1 onto the stack if x1 > x2, 0 if not equal. 1322 * <p> 1323 * Stack before: x1 x2 ...<br/> 1324 * Stack after: x1>x2 1325 * 1326 */ 1327 public static final int _CMP_GT_ = 334; // x2, x1 -> x1 < x2 1328 /** 1329 * Applies a regular expression to the top stack element; pushes 1 if it matches, 1330 * 0 if it does not match. 1331 * <p> 1332 * Stack before: x1 x2 ...<br/> 1333 * Stack after: (x1 ~ /x2/) ... 1334 * 1335 */ 1336 public static final int _MATCHES_ = 335; // x2, x1 -> x1 ~ x2 1337 1338 /** 1339 * <strong>Extension:</strong> Pauses the execution thread by N number of seconds. 1340 * <p> 1341 * Stack before: N ...<br/> 1342 * Stack after: ... 1343 * 1344 */ 1345 public static final int _SLEEP_ = 336; // x -> 0 1346 /** Constant <code>_DUMP_=337</code> */ 1347 public static final int _DUMP_ = 337; // x -> 0 1348 1349 /** Constant <code>_DEREF_ARRAY_=338</code> */ 1350 public static final int _DEREF_ARRAY_ = 338; // x -> x 1351 1352 // for (x in y) {keyset} support 1353 /** 1354 * Retrieves and pushes a Set of keys from an associative array onto the stack. 1355 * The Set is tagged with a KeyList interface. 1356 * <p> 1357 * Stack before: associative-array ...<br/> 1358 * Stack after: key-list-set ... 1359 * 1360 */ 1361 public static final int _KEYLIST_ = 339; // 0 -> {keylist} 1362 /** 1363 * Tests whether the KeyList (set) is empty; jumps to the argument 1364 * address if empty, steps to the next instruction if not. 1365 * <p> 1366 * Argument: jump-address-if-empty 1367 * 1368 * <p> 1369 * Stack before: key-list ...<br/> 1370 * Stack after: ... 1371 * 1372 */ 1373 public static final int _IS_EMPTY_KEYLIST_ = 340; // {keylist} -> 0 1374 /** 1375 * Removes an item from the KeyList (set) and pushes it onto the operand stack. 1376 * <p> 1377 * Stack before: key-list ...<br/> 1378 * Stack after: 1st-item ... 1379 * 1380 */ 1381 public static final int _GET_FIRST_AND_REMOVE_FROM_KEYLIST_ = 341; // {keylist} -> x 1382 1383 // assertions 1384 /** 1385 * Checks whether the top-of-stack is of a particular class type; 1386 * if not, an AwkRuntimeException is thrown. 1387 * The stack remains unchanged upon a successful check. 1388 * <p> 1389 * Argument: class-type (i.e., KeyList.class) 1390 * 1391 * <p> 1392 * Stack before: obj ...<br/> 1393 * Stack after: obj ... 1394 * 1395 */ 1396 public static final int _CHECK_CLASS_ = 342; // {class} -> 0 1397 1398 // input 1399 //* Obtain an input string from stdin; push the result onto the stack. 1400 /** 1401 * Push an input field onto the stack. 1402 * <p> 1403 * Stack before: field-id ...<br/> 1404 * Stack after: x ... 1405 * 1406 */ 1407 public static final int _GET_INPUT_FIELD_ = 343; // 0 -> x 1408 /** 1409 * Consume next line of input; assigning $0 and recalculating $1, $2, etc. 1410 * The input can come from the following sources: 1411 * <ul> 1412 * <li>stdin 1413 * <li>filename arguments 1414 * </ul> 1415 * The operand stack is unaffected. 1416 */ 1417 public static final int _CONSUME_INPUT_ = 344; // 0 -> 0 1418 /** 1419 * Obtains input from stdin/filename-args and pushes 1420 * input line and status code onto the stack. 1421 * The input is partitioned into records based on the RS variable 1422 * assignment as a regular expression. 1423 * <p> 1424 * If there is input available, the input string and a return code 1425 * of 1 is pushed. If EOF is reached, a blank (null) string ("") 1426 * is pushed along with a 0 return code. Upon an IO error, 1427 * a blank string and a -1 is pushed onto the operand stack. 1428 * 1429 * <p> 1430 * Stack before: ...<br/> 1431 * Stack after: input-string return-code ... 1432 * 1433 */ 1434 public static final int _GETLINE_INPUT_ = 345; // 0 -> x 1435 /** 1436 * Obtains input from a file and pushes 1437 * input line and status code onto the stack. 1438 * The input is partitioned into records based on the RS variable 1439 * assignment as a regular expression. 1440 * <p> 1441 * Upon initial execution, the file is opened and the handle 1442 * is maintained until it is explicitly closed, or until 1443 * the VM exits. Subsequent calls will obtain subsequent 1444 * lines (records) of input until no more records are available. 1445 * 1446 * <p> 1447 * If there is input available, the input string and a return code 1448 * of 1 is pushed. If EOF is reached, a blank (null) string ("") 1449 * is pushed along with a 0 return code. Upon an IO error, 1450 * a blank string and a -1 is pushed onto the operand stack. 1451 * 1452 * <p> 1453 * Stack before: filename ...<br/> 1454 * Stack after: input-string return-code ... 1455 * 1456 */ 1457 public static final int _USE_AS_FILE_INPUT_ = 346; // x1 -> x2 1458 /** 1459 * Obtains input from a command (process) and pushes 1460 * input line and status code onto the stack. 1461 * The input is partitioned into records based on the RS variable 1462 * assignment as a regular expression. 1463 * <p> 1464 * Upon initial execution, the a process is spawned to execute 1465 * the specified command and the process reference 1466 * is maintained until it is explicitly closed, or until 1467 * the VM exits. Subsequent calls will obtain subsequent 1468 * lines (records) of input until no more records are available. 1469 * 1470 * <p> 1471 * If there is input available, the input string and a return code 1472 * of 1 is pushed. If EOF is reached, a blank (null) string ("") 1473 * is pushed along with a 0 return code. Upon an IO error, 1474 * a blank string and a -1 is pushed onto the operand stack. 1475 * 1476 * <p> 1477 * Stack before: command-line ...<br/> 1478 * Stack after: input-string return-code ... 1479 * 1480 */ 1481 public static final int _USE_AS_COMMAND_INPUT_ = 347; // x1 -> x2 1482 1483 // variable housekeeping 1484 /** 1485 * Assign the NF variable offset. This is important for the 1486 * AVM to set the variables as new input lines are processed. 1487 * <p> 1488 * The operand stack is unaffected. 1489 * 1490 */ 1491 public static final int _NF_OFFSET_ = 348; // 0 -> 0 1492 /** 1493 * Assign the NR variable offset. This is important for the 1494 * AVM to increase the record number as new input lines received. 1495 * <p> 1496 * The operand stack is unaffected. 1497 * 1498 */ 1499 public static final int _NR_OFFSET_ = 349; // 0 -> 0 1500 /** 1501 * Assign the FNR variable offset. This is important for the 1502 * AVM to increase the "file" record number as new input lines are received. 1503 * <p> 1504 * The operand stack is unaffected. 1505 * 1506 */ 1507 public static final int _FNR_OFFSET_ = 350; // 0 -> 0 1508 /** 1509 * Assign the FS variable offset. This is important for the 1510 * AVM to know how to split fields upon incoming records of input. 1511 * <p> 1512 * The operand stack is unaffected. 1513 * 1514 */ 1515 public static final int _FS_OFFSET_ = 351; // 0 -> 0 1516 /** 1517 * Assign the RS variable offset. This is important for the 1518 * AVM to know how to create records from the stream(s) of input. 1519 * <p> 1520 * The operand stack is unaffected. 1521 * 1522 */ 1523 public static final int _RS_OFFSET_ = 352; // 0 -> 0 1524 /** 1525 * Assign the OFS variable offset. This is important for the 1526 * AVM to use when outputting expressions via PRINT. 1527 * <p> 1528 * The operand stack is unaffected. 1529 * 1530 */ 1531 public static final int _OFS_OFFSET_ = 353; // 0 -> 0 1532 /** 1533 * Assign the RSTART variable offset. The AVM sets this variable while 1534 * executing the match() builtin function. 1535 * <p> 1536 * The operand stack is unaffected. 1537 * 1538 */ 1539 public static final int _RSTART_OFFSET_ = 354; // 0 -> 0 1540 /** 1541 * Assign the RLENGTH variable offset. The AVM sets this variable while 1542 * executing the match() builtin function. 1543 * <p> 1544 * The operand stack is unaffected. 1545 * 1546 */ 1547 public static final int _RLENGTH_OFFSET_ = 355; // 0 -> 0 1548 /** 1549 * Assign the FILENAME variable offset. The AVM sets this variable while 1550 * processing files from the command-line for input. 1551 * <p> 1552 * The operand stack is unaffected. 1553 * 1554 */ 1555 public static final int _FILENAME_OFFSET_ = 356; // 0 -> 0 1556 /** 1557 * Assign the SUBSEP variable offset. The AVM uses this variable while 1558 * building an index of a multi-dimensional array. 1559 * <p> 1560 * The operand stack is unaffected. 1561 * 1562 */ 1563 public static final int _SUBSEP_OFFSET_ = 357; // 0 -> 0 1564 /** 1565 * Assign the CONVFMT variable offset. The AVM uses this variable while 1566 * converting numbers to strings. 1567 * <p> 1568 * The operand stack is unaffected. 1569 * 1570 */ 1571 public static final int _CONVFMT_OFFSET_ = 358; // 0 -> 0 1572 /** 1573 * Assign the OFMT variable offset. The AVM uses this variable while 1574 * converting numbers to strings for printing. 1575 * <p> 1576 * The operand stack is unaffected. 1577 * 1578 */ 1579 public static final int _OFMT_OFFSET_ = 359; // 0 -> 0 1580 /** 1581 * Assign the ENVIRON variable offset. The AVM provides environment 1582 * variables through this array. 1583 * <p> 1584 * The operand stack is unaffected. 1585 * 1586 */ 1587 public static final int _ENVIRON_OFFSET_ = 360; // 0 -> 0 1588 /** 1589 * Assign the ARGC variable offset. The AVM provides the number of 1590 * arguments via this variable. 1591 * <p> 1592 * The operand stack is unaffected. 1593 * 1594 */ 1595 public static final int _ARGC_OFFSET_ = 361; // 0 -> 0 1596 /** 1597 * Assign the ARGV variable offset. The AVM provides command-line 1598 * arguments via this variable. 1599 * <p> 1600 * The operand stack is unaffected. 1601 * 1602 */ 1603 public static final int _ARGV_OFFSET_ = 362; // 0 -> 0 1604 1605 /** 1606 * Apply the RS variable by notifying the partitioning reader that 1607 * there is a new regular expression to use when partitioning input 1608 * records. 1609 * <p> 1610 * The stack remains unaffected. 1611 * 1612 */ 1613 public static final int _APPLY_RS_ = 363; // 0 -> 0 1614 1615 /** 1616 * Call a user function. 1617 * <p> 1618 * Stack before: x1, x2, ..., xn <br> 1619 * Stack after: f(x1, x2, ..., xn) 1620 */ 1621 public static final int _CALL_FUNCTION_ = 364; // x1,x2,...,xn -> x 1622 1623 /** 1624 * Define a user function. 1625 * <p> 1626 * Stack remains unchanged 1627 */ 1628 public static final int _FUNCTION_ = 365; // 0 -> 0 1629 1630 /** 1631 * Sets the return value of a user function. 1632 * <p> 1633 * Stack before: x <br> 1634 * Stack after: ... 1635 */ 1636 public static final int _SET_RETURN_RESULT_ = 366; // x -> 0 1637 1638 /** 1639 * Get the return value of the user function that was called 1640 * <p> 1641 * Stack before: ... <br> 1642 * Stack after: x 1643 */ 1644 public static final int _RETURN_FROM_FUNCTION_ = 367; // 0 -> x 1645 1646 /** 1647 * Internal: sets the number of global variables 1648 */ 1649 public static final int _SET_NUM_GLOBALS_ = 368; // 0 -> 0 1650 1651 /** 1652 * Close the specified file. 1653 * <p> 1654 * Stack before: file name <br> 1655 * Stack after: result of the close operation 1656 */ 1657 public static final int _CLOSE_ = 369; // x -> x 1658 1659 /** 1660 * Convert a list of array indices to a concatenated string with SUBSEP. 1661 * This is used for multidimensional arrays. 1662 * <p> 1663 * Stack before: i1, i2, ..., in <br> 1664 * Stack after: "i1SUBSEPi2SUBSEP...in" 1665 */ 1666 public static final int _APPLY_SUBSEP_ = 370; // x -> 0 1667 1668 /** 1669 * Deletes an entry in an array. 1670 * <p> 1671 * Stack before: i <br> 1672 * Stack after: ... 1673 */ 1674 public static final int _DELETE_ARRAY_ELEMENT_ = 371; // 0 -> 0 1675 1676 /** 1677 * Internal. 1678 * <p> 1679 * Stack remains unchanged. 1680 */ 1681 public static final int _SET_EXIT_ADDRESS_ = 372; // 0 -> 0 1682 1683 /** 1684 * Internal. 1685 * <p> 1686 * Stack remains unchanged. 1687 */ 1688 public static final int _SET_WITHIN_END_BLOCKS_ = 373; // 0 -> 0 1689 1690 /** 1691 * Terminates execution and returns specified exit code. 1692 * <p> 1693 * Stack before: integer <br> 1694 * Stack after: N/A 1695 */ 1696 public static final int _EXIT_WITH_CODE_ = 374; // 0 -> 0 1697 1698 /** 1699 * Returns a regex pattern. 1700 * <p> 1701 * Stack before: ... <br> 1702 * Stack after: the regex pattern object 1703 */ 1704 public static final int _REGEXP_ = 375; // 0 -> x 1705 1706 /** 1707 * Returns a pair of regex patterns. 1708 * <p> 1709 * Stack before: pattern1, pattern2 <br> 1710 * Stack after: regex pair object 1711 */ 1712 public static final int _CONDITION_PAIR_ = 376; // x, y -> x 1713 1714 /** 1715 * Returns whether the specified key is in the array. 1716 * <p> 1717 * Stack before: key, array <br> 1718 * Stack after: true|false 1719 */ 1720 public static final int _IS_IN_ = 377; // x,y -> x 1721 1722 /** 1723 * Cast to integer 1724 * <p> 1725 * Stack before: object <br> 1726 * Stack after: integer 1727 */ 1728 public static final int _CAST_INT_ = 378; // x -> (int)x 1729 1730 /** 1731 * Cast to double 1732 * <p> 1733 * Stack before: object <br> 1734 * Stack after: double 1735 */ 1736 public static final int _CAST_DOUBLE_ = 379; // x -> (double)x 1737 1738 /** 1739 * Cast to string 1740 * <p> 1741 * Stack before: object <br> 1742 * Stack after: string 1743 */ 1744 public static final int _CAST_STRING_ = 380; // x -> (string)x 1745 1746 /** 1747 * Deprecated. 1748 */ 1749 public static final int _THIS_ = 381; // 0 -> (this) 1750 1751 /** 1752 * Call a function from an extension 1753 * <p> 1754 * Stack before: x1, x2, ..., xn <br> 1755 * Stack after: f(x1, x2, ..., xn) 1756 */ 1757 public static final int _EXTENSION_ = 382; // x1,x2,...,xn -> x 1758 1759 /** 1760 * Execute the specified AWK code 1761 * <p> 1762 * Stack before: script <br> 1763 * Stack after: exit code of the script, or zero when successful, -1 when failed 1764 */ 1765 public static final int _EXEC_ = 383; // x1,x2,...,xn -> x 1766 1767 /** 1768 * Delete the specified array. 1769 * <p> 1770 * Stack remains unchanged. 1771 */ 1772 public static final int _DELETE_ARRAY_ = 384; // 0 -> 0 1773 1774 /** 1775 * Converts the top stack element to a number; 1776 * pushes the result onto the stack. 1777 * <p> 1778 * Stack before: x ...<br/> 1779 * Stack after: x ... (as a number) 1780 * 1781 */ 1782 public static final int _UNARY_PLUS_ = 385; // x -> -x 1783 1784 /** 1785 * Terminates execution without specifying an exit code. 1786 * <p> 1787 * Stack before: N/A <br> 1788 * Stack after: N/A 1789 */ 1790 public static final int _EXIT_WITHOUT_CODE_ = 386; // 0 -> 0 1791 1792 /** 1793 * Assign the ORS variable offset. This is important for the 1794 * AVM to use when outputting expressions via PRINT. 1795 * <p> 1796 * The operand stack is unaffected. 1797 * 1798 */ 1799 public static final int _ORS_OFFSET_ = 387; // 0 -> 0 1800 1801 /** 1802 * Increases the variable reference by one; pushes the original value 1803 * onto the stack. 1804 * <p> 1805 * Argument 1: offset of the particular variable into the variable manager<br/> 1806 * Argument 2: whether the variable is global or local 1807 * 1808 * <p> 1809 * Stack before: ...<br/> 1810 * Stack after: x ... or 0 if uninitialized 1811 * 1812 */ 1813 public static final int _POSTINC_ = 388; // 0 -> x 1814 1815 /** 1816 * Decreases the variable reference by one; pushes the original value 1817 * onto the stack. 1818 * <p> 1819 * Argument 1: offset of the particular variable into the variable manager<br/> 1820 * Argument 2: whether the variable is global or local 1821 * 1822 * <p> 1823 * Stack before: ...<br/> 1824 * Stack after: x ... or 0 if uninitialized 1825 * 1826 */ 1827 public static final int _POSTDEC_ = 389; // 0 -> x 1828 1829 /** 1830 * Override add() to populate the line number for each tuple, 1831 * rather than polluting all the constructors with this assignment. 1832 */ 1833 private java.util.List<Tuple> queue = new ArrayList<Tuple>(100) { 1834 1835 private static final long serialVersionUID = -6334362156408598578L; 1836 1837 @Override 1838 public boolean add(Tuple t) { 1839 t.setLineNumber(lineno_stack.peek()); 1840 return super.add(t); 1841 } 1842 }; 1843 1844 /** Unresolved addresses */ 1845 private Set<Address> unresolved_addresses = new HashSet<Address>(); 1846 1847 /** Needed only for dumping intermediate code to text such that address labels are provided. */ 1848 private Map<Integer, Address> address_indexes = new HashMap<Integer, Address>(); 1849 /** Needed only for dumping intermediate code to text such that address labels are provided. */ 1850 private Map<String, Integer> address_label_counts = new HashMap<String, Integer>(); 1851 1852 /** 1853 * <p>toOpcodeString.</p> 1854 * 1855 * @param opcode a int 1856 * @return a {@link java.lang.String} object 1857 */ 1858 public static String toOpcodeString(int opcode) { 1859 Class<?> c = AwkTuples.class; 1860 Field[] fields = c.getDeclaredFields(); 1861 try { 1862 for (Field field : fields) { 1863 if ((field.getModifiers() & Modifier.STATIC) > 0 && field.getType() == Long.TYPE && field.getLong(null) == opcode) { 1864 return field.getName(); 1865 } 1866 } 1867 } catch (IllegalAccessException iac) { 1868 LOG.error("Failed to create OP-Code string", iac); 1869 return "[" + opcode + ": " + iac + "]"; 1870 } 1871 return "{" + opcode + "}"; 1872 } 1873 1874 /** 1875 * <p>pop.</p> 1876 */ 1877 public void pop() { 1878 queue.add(new Tuple(_POP_)); 1879 } 1880 1881 /** 1882 * <p>push.</p> 1883 * 1884 * @param o a {@link java.lang.Object} object 1885 */ 1886 public void push(Object o) { 1887 assert (o instanceof String) || (o instanceof Long) || (o instanceof Integer) || (o instanceof Double); // || (o instanceof Pattern); 1888 if (o instanceof String) { 1889 queue.add(new Tuple(_PUSH_, o.toString())); 1890 } else if (o instanceof Integer) { 1891 queue.add(new Tuple(_PUSH_, (Integer) o)); 1892 } else if (o instanceof Long) { 1893 queue.add(new Tuple(_PUSH_, (Long) o)); 1894 } else if (o instanceof Double) { 1895 queue.add(new Tuple(_PUSH_, (Double) o)); 1896 } else { 1897 assert false : "Invalid type for " + o + ", "+o.getClass(); 1898 } 1899 } 1900 1901 /** 1902 * <p>ifFalse.</p> 1903 * 1904 * @param address a {@link org.sentrysoftware.jawk.intermediate.Address} object 1905 */ 1906 public void ifFalse(Address address) { 1907 queue.add(new Tuple(_IFFALSE_, address)); 1908 } 1909 1910 /** 1911 * <p>toNumber.</p> 1912 */ 1913 public void toNumber() { 1914 queue.add(new Tuple(_TO_NUMBER_)); 1915 } 1916 1917 /** 1918 * <p>ifTrue.</p> 1919 * 1920 * @param address a {@link org.sentrysoftware.jawk.intermediate.Address} object 1921 */ 1922 public void ifTrue(Address address) { 1923 queue.add(new Tuple(_IFTRUE_, address)); 1924 } 1925 1926 /** 1927 * <p>gotoAddress.</p> 1928 * 1929 * @param address a {@link org.sentrysoftware.jawk.intermediate.Address} object 1930 */ 1931 public void gotoAddress(Address address) { 1932 queue.add(new Tuple(_GOTO_, address)); 1933 } 1934 1935 /** 1936 * <p>createAddress.</p> 1937 * 1938 * @param label a {@link java.lang.String} object 1939 * @return a {@link org.sentrysoftware.jawk.intermediate.Address} object 1940 */ 1941 public Address createAddress(String label) { 1942 Integer I = address_label_counts.get(label); 1943 if (I == null) { 1944 I = 0; 1945 } else { 1946 //I = new Integer(I.intValue()+1); 1947 I = I + 1; 1948 } 1949 address_label_counts.put(label, I); 1950 Address address = new AddressImpl(label + "_" + I); 1951 unresolved_addresses.add(address); 1952 return address; 1953 } 1954 1955 /** 1956 * <p>address.</p> 1957 * 1958 * @param address a {@link org.sentrysoftware.jawk.intermediate.Address} object 1959 * @return a {@link org.sentrysoftware.jawk.intermediate.AwkTuples} object 1960 */ 1961 public AwkTuples address(Address address) { 1962 if (unresolved_addresses.contains(address)) { 1963 unresolved_addresses.remove(address); 1964 address.assignIndex(queue.size()); 1965 address_indexes.put(queue.size(), address); 1966 return this; 1967 } 1968 throw new Error(address.toString() + " is already resolved, or unresolved from another scope."); 1969 } 1970 1971 /** 1972 * <p>nop.</p> 1973 */ 1974 public void nop() { 1975 queue.add(new Tuple(_NOP_)); 1976 } 1977 1978 /** 1979 * <p>print.</p> 1980 * 1981 * @param num_exprs a int 1982 */ 1983 public void print(int num_exprs) { 1984 queue.add(new Tuple(_PRINT_, num_exprs)); 1985 } 1986 1987 /** 1988 * <p>printToFile.</p> 1989 * 1990 * @param num_exprs a int 1991 * @param append a boolean 1992 */ 1993 public void printToFile(int num_exprs, boolean append) { 1994 queue.add(new Tuple(_PRINT_TO_FILE_, num_exprs, append)); 1995 } 1996 1997 /** 1998 * <p>printToPipe.</p> 1999 * 2000 * @param num_exprs a int 2001 */ 2002 public void printToPipe(int num_exprs) { 2003 queue.add(new Tuple(_PRINT_TO_PIPE_, num_exprs)); 2004 } 2005 2006 /** 2007 * <p>printf.</p> 2008 * 2009 * @param num_exprs a int 2010 */ 2011 public void printf(int num_exprs) { 2012 queue.add(new Tuple(_PRINTF_, num_exprs)); 2013 } 2014 2015 /** 2016 * <p>printfToFile.</p> 2017 * 2018 * @param num_exprs a int 2019 * @param append a boolean 2020 */ 2021 public void printfToFile(int num_exprs, boolean append) { 2022 queue.add(new Tuple(_PRINTF_TO_FILE_, num_exprs, append)); 2023 } 2024 2025 /** 2026 * <p>printfToPipe.</p> 2027 * 2028 * @param num_exprs a int 2029 */ 2030 public void printfToPipe(int num_exprs) { 2031 queue.add(new Tuple(_PRINTF_TO_PIPE_, num_exprs)); 2032 } 2033 2034 /** 2035 * <p>sprintf.</p> 2036 * 2037 * @param num_exprs a int 2038 */ 2039 public void sprintf(int num_exprs) { 2040 queue.add(new Tuple(_SPRINTF_, num_exprs)); 2041 } 2042 2043 /** 2044 * <p>length.</p> 2045 * 2046 * @param num_exprs a int 2047 */ 2048 public void length(int num_exprs) { 2049 queue.add(new Tuple(_LENGTH_, num_exprs)); 2050 } 2051 2052 /** 2053 * <p>concat.</p> 2054 */ 2055 public void concat() { 2056 queue.add(new Tuple(_CONCAT_)); 2057 } 2058 2059 /** 2060 * <p>assign.</p> 2061 * 2062 * @param offset a int 2063 * @param is_global a boolean 2064 */ 2065 public void assign(int offset, boolean is_global) { 2066 queue.add(new Tuple(_ASSIGN_, offset, is_global)); 2067 } 2068 2069 /** 2070 * <p>assignArray.</p> 2071 * 2072 * @param offset a int 2073 * @param is_global a boolean 2074 */ 2075 public void assignArray(int offset, boolean is_global) { 2076 queue.add(new Tuple(_ASSIGN_ARRAY_, offset, is_global)); 2077 } 2078 2079 /** 2080 * <p>assignAsInput.</p> 2081 */ 2082 public void assignAsInput() { 2083 queue.add(new Tuple(_ASSIGN_AS_INPUT_)); 2084 } 2085 2086 /** 2087 * <p>assignAsInputField.</p> 2088 */ 2089 public void assignAsInputField() { 2090 queue.add(new Tuple(_ASSIGN_AS_INPUT_FIELD_)); 2091 } 2092 2093 /** 2094 * <p>dereference.</p> 2095 * 2096 * @param offset a int 2097 * @param is_array a boolean 2098 * @param is_global a boolean 2099 */ 2100 public void dereference(int offset, boolean is_array, boolean is_global) { 2101 queue.add(new Tuple(_DEREFERENCE_, offset, is_array, is_global)); 2102 } 2103 2104 /** 2105 * <p>plusEq.</p> 2106 * 2107 * @param offset a int 2108 * @param is_global a boolean 2109 */ 2110 public void plusEq(int offset, boolean is_global) { 2111 queue.add(new Tuple(_PLUS_EQ_, offset, is_global)); 2112 } 2113 2114 /** 2115 * <p>minusEq.</p> 2116 * 2117 * @param offset a int 2118 * @param is_global a boolean 2119 */ 2120 public void minusEq(int offset, boolean is_global) { 2121 queue.add(new Tuple(_MINUS_EQ_, offset, is_global)); 2122 } 2123 2124 /** 2125 * <p>multEq.</p> 2126 * 2127 * @param offset a int 2128 * @param is_global a boolean 2129 */ 2130 public void multEq(int offset, boolean is_global) { 2131 queue.add(new Tuple(_MULT_EQ_, offset, is_global)); 2132 } 2133 2134 /** 2135 * <p>divEq.</p> 2136 * 2137 * @param offset a int 2138 * @param is_global a boolean 2139 */ 2140 public void divEq(int offset, boolean is_global) { 2141 queue.add(new Tuple(_DIV_EQ_, offset, is_global)); 2142 } 2143 2144 /** 2145 * <p>modEq.</p> 2146 * 2147 * @param offset a int 2148 * @param is_global a boolean 2149 */ 2150 public void modEq(int offset, boolean is_global) { 2151 queue.add(new Tuple(_MOD_EQ_, offset, is_global)); 2152 } 2153 2154 /** 2155 * <p>powEq.</p> 2156 * 2157 * @param offset a int 2158 * @param is_global a boolean 2159 */ 2160 public void powEq(int offset, boolean is_global) { 2161 queue.add(new Tuple(_POW_EQ_, offset, is_global)); 2162 } 2163 2164 /** 2165 * <p>plusEqArray.</p> 2166 * 2167 * @param offset a int 2168 * @param is_global a boolean 2169 */ 2170 public void plusEqArray(int offset, boolean is_global) { 2171 queue.add(new Tuple(_PLUS_EQ_ARRAY_, offset, is_global)); 2172 } 2173 2174 /** 2175 * <p>minusEqArray.</p> 2176 * 2177 * @param offset a int 2178 * @param is_global a boolean 2179 */ 2180 public void minusEqArray(int offset, boolean is_global) { 2181 queue.add(new Tuple(_MINUS_EQ_ARRAY_, offset, is_global)); 2182 } 2183 2184 /** 2185 * <p>multEqArray.</p> 2186 * 2187 * @param offset a int 2188 * @param is_global a boolean 2189 */ 2190 public void multEqArray(int offset, boolean is_global) { 2191 queue.add(new Tuple(_MULT_EQ_ARRAY_, offset, is_global)); 2192 } 2193 2194 /** 2195 * <p>divEqArray.</p> 2196 * 2197 * @param offset a int 2198 * @param is_global a boolean 2199 */ 2200 public void divEqArray(int offset, boolean is_global) { 2201 queue.add(new Tuple(_DIV_EQ_ARRAY_, offset, is_global)); 2202 } 2203 2204 /** 2205 * <p>modEqArray.</p> 2206 * 2207 * @param offset a int 2208 * @param is_global a boolean 2209 */ 2210 public void modEqArray(int offset, boolean is_global) { 2211 queue.add(new Tuple(_MOD_EQ_ARRAY_, offset, is_global)); 2212 } 2213 2214 /** 2215 * <p>powEqArray.</p> 2216 * 2217 * @param offset a int 2218 * @param is_global a boolean 2219 */ 2220 public void powEqArray(int offset, boolean is_global) { 2221 queue.add(new Tuple(_POW_EQ_ARRAY_, offset, is_global)); 2222 } 2223 2224 /** 2225 * <p>plusEqInputField.</p> 2226 */ 2227 public void plusEqInputField() { 2228 queue.add(new Tuple(_PLUS_EQ_INPUT_FIELD_)); 2229 } 2230 2231 /** 2232 * <p>minusEqInputField.</p> 2233 */ 2234 public void minusEqInputField() { 2235 queue.add(new Tuple(_MINUS_EQ_INPUT_FIELD_)); 2236 } 2237 2238 /** 2239 * <p>multEqInputField.</p> 2240 */ 2241 public void multEqInputField() { 2242 queue.add(new Tuple(_MULT_EQ_INPUT_FIELD_)); 2243 } 2244 2245 /** 2246 * <p>divEqInputField.</p> 2247 */ 2248 public void divEqInputField() { 2249 queue.add(new Tuple(_DIV_EQ_INPUT_FIELD_)); 2250 } 2251 2252 /** 2253 * <p>modEqInputField.</p> 2254 */ 2255 public void modEqInputField() { 2256 queue.add(new Tuple(_MOD_EQ_INPUT_FIELD_)); 2257 } 2258 2259 /** 2260 * <p>powEqInputField.</p> 2261 */ 2262 public void powEqInputField() { 2263 queue.add(new Tuple(_POW_EQ_INPUT_FIELD_)); 2264 } 2265 2266 /** 2267 * <p>srand.</p> 2268 * 2269 * @param num a int 2270 */ 2271 public void srand(int num) { 2272 queue.add(new Tuple(_SRAND_, num)); 2273 } 2274 2275 /** 2276 * <p>rand.</p> 2277 */ 2278 public void rand() { 2279 queue.add(new Tuple(_RAND_)); 2280 } 2281 2282 /** 2283 * <p>intFunc.</p> 2284 */ 2285 public void intFunc() { 2286 queue.add(new Tuple(_INTFUNC_)); 2287 } 2288 2289 /** 2290 * <p>sqrt.</p> 2291 */ 2292 public void sqrt() { 2293 queue.add(new Tuple(_SQRT_)); 2294 } 2295 2296 /** 2297 * <p>log.</p> 2298 */ 2299 public void log() { 2300 queue.add(new Tuple(_LOG_)); 2301 } 2302 2303 /** 2304 * <p>exp.</p> 2305 */ 2306 public void exp() { 2307 queue.add(new Tuple(_EXP_)); 2308 } 2309 2310 /** 2311 * <p>sin.</p> 2312 */ 2313 public void sin() { 2314 queue.add(new Tuple(_SIN_)); 2315 } 2316 2317 /** 2318 * <p>cos.</p> 2319 */ 2320 public void cos() { 2321 queue.add(new Tuple(_COS_)); 2322 } 2323 2324 /** 2325 * <p>atan2.</p> 2326 */ 2327 public void atan2() { 2328 queue.add(new Tuple(_ATAN2_)); 2329 } 2330 2331 /** 2332 * <p>match.</p> 2333 */ 2334 public void match() { 2335 queue.add(new Tuple(_MATCH_)); 2336 } 2337 2338 /** 2339 * <p>index.</p> 2340 */ 2341 public void index() { 2342 queue.add(new Tuple(_INDEX_)); 2343 } 2344 2345 /** 2346 * <p>subForDollar0.</p> 2347 * 2348 * @param is_gsub a boolean 2349 */ 2350 public void subForDollar0(boolean is_gsub) { 2351 queue.add(new Tuple(_SUB_FOR_DOLLAR_0_, is_gsub)); 2352 } 2353 2354 /** 2355 * <p>subForDollarReference.</p> 2356 * 2357 * @param is_gsub a boolean 2358 */ 2359 public void subForDollarReference(boolean is_gsub) { 2360 queue.add(new Tuple(_SUB_FOR_DOLLAR_REFERENCE_, is_gsub)); 2361 } 2362 2363 /** 2364 * <p>subForVariable.</p> 2365 * 2366 * @param offset a int 2367 * @param is_global a boolean 2368 * @param is_gsub a boolean 2369 */ 2370 public void subForVariable(int offset, boolean is_global, boolean is_gsub) { 2371 queue.add(new Tuple(_SUB_FOR_VARIABLE_, offset, is_global, is_gsub)); 2372 } 2373 2374 /** 2375 * <p>subForArrayReference.</p> 2376 * 2377 * @param offset a int 2378 * @param is_global a boolean 2379 * @param is_gsub a boolean 2380 */ 2381 public void subForArrayReference(int offset, boolean is_global, boolean is_gsub) { 2382 queue.add(new Tuple(_SUB_FOR_ARRAY_REFERENCE_, offset, is_global, is_gsub)); 2383 } 2384 2385 /** 2386 * <p>split.</p> 2387 * 2388 * @param numargs a int 2389 */ 2390 public void split(int numargs) { 2391 queue.add(new Tuple(_SPLIT_, numargs)); 2392 } 2393 2394 /** 2395 * <p>substr.</p> 2396 * 2397 * @param numargs a int 2398 */ 2399 public void substr(int numargs) { 2400 queue.add(new Tuple(_SUBSTR_, numargs)); 2401 } 2402 2403 /** 2404 * <p>tolower.</p> 2405 */ 2406 public void tolower() { 2407 queue.add(new Tuple(_TOLOWER_)); 2408 } 2409 2410 /** 2411 * <p>toupper.</p> 2412 */ 2413 public void toupper() { 2414 queue.add(new Tuple(_TOUPPER_)); 2415 } 2416 2417 /** 2418 * <p>system.</p> 2419 */ 2420 public void system() { 2421 queue.add(new Tuple(_SYSTEM_)); 2422 } 2423 2424 /** 2425 * <p>exec.</p> 2426 */ 2427 public void exec() { 2428 queue.add(new Tuple(_EXEC_)); 2429 } 2430 2431 /** 2432 * <p>swap.</p> 2433 */ 2434 public void swap() { 2435 queue.add(new Tuple(_SWAP_)); 2436 } 2437 2438 /** 2439 * <p>add.</p> 2440 */ 2441 public void add() { 2442 queue.add(new Tuple(_ADD_)); 2443 } 2444 2445 /** 2446 * <p>subtract.</p> 2447 */ 2448 public void subtract() { 2449 queue.add(new Tuple(_SUBTRACT_)); 2450 } 2451 2452 /** 2453 * <p>multiply.</p> 2454 */ 2455 public void multiply() { 2456 queue.add(new Tuple(_MULTIPLY_)); 2457 } 2458 2459 /** 2460 * <p>divide.</p> 2461 */ 2462 public void divide() { 2463 queue.add(new Tuple(_DIVIDE_)); 2464 } 2465 2466 /** 2467 * <p>mod.</p> 2468 */ 2469 public void mod() { 2470 queue.add(new Tuple(_MOD_)); 2471 } 2472 2473 /** 2474 * <p>pow.</p> 2475 */ 2476 public void pow() { 2477 queue.add(new Tuple(_POW_)); 2478 } 2479 2480 /** 2481 * <p>inc.</p> 2482 * 2483 * @param offset a int 2484 * @param is_global a boolean 2485 */ 2486 public void inc(int offset, boolean is_global) { 2487 queue.add(new Tuple(_INC_, offset, is_global)); 2488 } 2489 2490 /** 2491 * <p>dec.</p> 2492 * 2493 * @param offset a int 2494 * @param is_global a boolean 2495 */ 2496 public void dec(int offset, boolean is_global) { 2497 queue.add(new Tuple(_DEC_, offset, is_global)); 2498 } 2499 2500 /** 2501 * <p>postInc.</p> 2502 * 2503 * @param offset a int 2504 * @param is_global a boolean 2505 */ 2506 public void postInc(int offset, boolean is_global) { 2507 queue.add(new Tuple(_POSTINC_, offset, is_global)); 2508 } 2509 2510 /** 2511 * <p>postDec.</p> 2512 * 2513 * @param offset a int 2514 * @param is_global a boolean 2515 */ 2516 public void postDec(int offset, boolean is_global) { 2517 queue.add(new Tuple(_POSTDEC_, offset, is_global)); 2518 } 2519 2520 /** 2521 * <p>incArrayRef.</p> 2522 * 2523 * @param offset a int 2524 * @param is_global a boolean 2525 */ 2526 public void incArrayRef(int offset, boolean is_global) { 2527 queue.add(new Tuple(_INC_ARRAY_REF_, offset, is_global)); 2528 } 2529 2530 /** 2531 * <p>decArrayRef.</p> 2532 * 2533 * @param offset a int 2534 * @param is_global a boolean 2535 */ 2536 public void decArrayRef(int offset, boolean is_global) { 2537 queue.add(new Tuple(_DEC_ARRAY_REF_, offset, is_global)); 2538 } 2539 2540 /** 2541 * <p>incDollarRef.</p> 2542 */ 2543 public void incDollarRef() { 2544 queue.add(new Tuple(_INC_DOLLAR_REF_)); 2545 } 2546 2547 /** 2548 * <p>decDollarRef.</p> 2549 */ 2550 public void decDollarRef() { 2551 queue.add(new Tuple(_DEC_DOLLAR_REF_)); 2552 } 2553 2554 /** 2555 * <p>dup.</p> 2556 */ 2557 public void dup() { 2558 queue.add(new Tuple(_DUP_)); 2559 } 2560 2561 /** 2562 * <p>not.</p> 2563 */ 2564 public void not() { 2565 queue.add(new Tuple(_NOT_)); 2566 } 2567 2568 /** 2569 * <p>negate.</p> 2570 */ 2571 public void negate() { 2572 queue.add(new Tuple(_NEGATE_)); 2573 } 2574 2575 /** 2576 * <p>unary plus.</p> 2577 */ 2578 public void unaryPlus() { 2579 queue.add(new Tuple(_UNARY_PLUS_)); 2580 } 2581 2582 /** 2583 * <p>cmpEq.</p> 2584 */ 2585 public void cmpEq() { 2586 queue.add(new Tuple(_CMP_EQ_)); 2587 } 2588 2589 /** 2590 * <p>cmpLt.</p> 2591 */ 2592 public void cmpLt() { 2593 queue.add(new Tuple(_CMP_LT_)); 2594 } 2595 2596 /** 2597 * <p>cmpGt.</p> 2598 */ 2599 public void cmpGt() { 2600 queue.add(new Tuple(_CMP_GT_)); 2601 } 2602 2603 /** 2604 * <p>matches.</p> 2605 */ 2606 public void matches() { 2607 queue.add(new Tuple(_MATCHES_)); 2608 } 2609 2610 /** 2611 * <p>sleep.</p> 2612 * 2613 * @param num_args a int 2614 */ 2615 public void sleep(int num_args) { 2616 queue.add(new Tuple(_SLEEP_, num_args)); 2617 } 2618 2619 /** 2620 * <p>dump.</p> 2621 * 2622 * @param num_args a int 2623 */ 2624 public void dump(int num_args) { 2625 queue.add(new Tuple(_DUMP_, num_args)); 2626 } 2627 2628 /** 2629 * <p>dereferenceArray.</p> 2630 */ 2631 public void dereferenceArray() { 2632 queue.add(new Tuple(_DEREF_ARRAY_)); 2633 } 2634 2635 /** 2636 * <p>keylist.</p> 2637 */ 2638 public void keylist() { 2639 queue.add(new Tuple(_KEYLIST_)); 2640 } 2641 2642 /** 2643 * <p>isEmptyList.</p> 2644 * 2645 * @param address a {@link org.sentrysoftware.jawk.intermediate.Address} object 2646 */ 2647 public void isEmptyList(Address address) { 2648 queue.add(new Tuple(_IS_EMPTY_KEYLIST_, address)); 2649 } 2650 2651 /** 2652 * <p>getFirstAndRemoveFromList.</p> 2653 */ 2654 public void getFirstAndRemoveFromList() { 2655 queue.add(new Tuple(_GET_FIRST_AND_REMOVE_FROM_KEYLIST_)); 2656 } 2657 2658 /** 2659 * <p>checkClass.</p> 2660 * 2661 * @param cls a {@link java.lang.Class} object 2662 * @return a boolean 2663 */ 2664 public boolean checkClass(Class<?> cls) { 2665 queue.add(new Tuple(_CHECK_CLASS_, cls)); 2666 return true; 2667 } 2668 2669 /** 2670 * <p>getInputField.</p> 2671 */ 2672 public void getInputField() { 2673 queue.add(new Tuple(_GET_INPUT_FIELD_)); 2674 } 2675 2676 /** 2677 * <p>consumeInput.</p> 2678 * 2679 * @param address a {@link org.sentrysoftware.jawk.intermediate.Address} object 2680 */ 2681 public void consumeInput(Address address) { 2682 queue.add(new Tuple(_CONSUME_INPUT_, address)); 2683 } 2684 2685 /** 2686 * <p>getlineInput.</p> 2687 */ 2688 public void getlineInput() { 2689 queue.add(new Tuple(_GETLINE_INPUT_)); 2690 } 2691 2692 /** 2693 * <p>useAsFileInput.</p> 2694 */ 2695 public void useAsFileInput() { 2696 queue.add(new Tuple(_USE_AS_FILE_INPUT_)); 2697 } 2698 2699 /** 2700 * <p>useAsCommandInput.</p> 2701 */ 2702 public void useAsCommandInput() { 2703 queue.add(new Tuple(_USE_AS_COMMAND_INPUT_)); 2704 } 2705 2706 /** 2707 * <p>nfOffset.</p> 2708 * 2709 * @param offset a int 2710 */ 2711 public void nfOffset(int offset) { 2712 queue.add(new Tuple(_NF_OFFSET_, offset)); 2713 } 2714 2715 /** 2716 * <p>nrOffset.</p> 2717 * 2718 * @param offset a int 2719 */ 2720 public void nrOffset(int offset) { 2721 queue.add(new Tuple(_NR_OFFSET_, offset)); 2722 } 2723 2724 /** 2725 * <p>fnrOffset.</p> 2726 * 2727 * @param offset a int 2728 */ 2729 public void fnrOffset(int offset) { 2730 queue.add(new Tuple(_FNR_OFFSET_, offset)); 2731 } 2732 2733 /** 2734 * <p>fsOffset.</p> 2735 * 2736 * @param offset a int 2737 */ 2738 public void fsOffset(int offset) { 2739 queue.add(new Tuple(_FS_OFFSET_, offset)); 2740 } 2741 2742 /** 2743 * <p>rsOffset.</p> 2744 * 2745 * @param offset a int 2746 */ 2747 public void rsOffset(int offset) { 2748 queue.add(new Tuple(_RS_OFFSET_, offset)); 2749 } 2750 2751 /** 2752 * <p>ofsOffset.</p> 2753 * 2754 * @param offset a int 2755 */ 2756 public void ofsOffset(int offset) { 2757 queue.add(new Tuple(_OFS_OFFSET_, offset)); 2758 } 2759 2760 /** 2761 * <p>orsOffset.</p> 2762 * 2763 * @param offset a int 2764 */ 2765 public void orsOffset(int offset) { 2766 queue.add(new Tuple(_ORS_OFFSET_, offset)); 2767 } 2768 2769 /** 2770 * <p>rstartOffset.</p> 2771 * 2772 * @param offset a int 2773 */ 2774 public void rstartOffset(int offset) { 2775 queue.add(new Tuple(_RSTART_OFFSET_, offset)); 2776 } 2777 2778 /** 2779 * <p>rlengthOffset.</p> 2780 * 2781 * @param offset a int 2782 */ 2783 public void rlengthOffset(int offset) { 2784 queue.add(new Tuple(_RLENGTH_OFFSET_, offset)); 2785 } 2786 2787 /** 2788 * <p>filenameOffset.</p> 2789 * 2790 * @param offset a int 2791 */ 2792 public void filenameOffset(int offset) { 2793 queue.add(new Tuple(_FILENAME_OFFSET_, offset)); 2794 } 2795 2796 /** 2797 * <p>subsepOffset.</p> 2798 * 2799 * @param offset a int 2800 */ 2801 public void subsepOffset(int offset) { 2802 queue.add(new Tuple(_SUBSEP_OFFSET_, offset)); 2803 } 2804 2805 /** 2806 * <p>convfmtOffset.</p> 2807 * 2808 * @param offset a int 2809 */ 2810 public void convfmtOffset(int offset) { 2811 queue.add(new Tuple(_CONVFMT_OFFSET_, offset)); 2812 } 2813 2814 /** 2815 * <p>ofmtOffset.</p> 2816 * 2817 * @param offset a int 2818 */ 2819 public void ofmtOffset(int offset) { 2820 queue.add(new Tuple(_OFMT_OFFSET_, offset)); 2821 } 2822 2823 /** 2824 * <p>environOffset.</p> 2825 * 2826 * @param offset a int 2827 */ 2828 public void environOffset(int offset) { 2829 queue.add(new Tuple(_ENVIRON_OFFSET_, offset)); 2830 } 2831 2832 /** 2833 * <p>argcOffset.</p> 2834 * 2835 * @param offset a int 2836 */ 2837 public void argcOffset(int offset) { 2838 queue.add(new Tuple(_ARGC_OFFSET_, offset)); 2839 } 2840 2841 /** 2842 * <p>argvOffset.</p> 2843 * 2844 * @param offset a int 2845 */ 2846 public void argvOffset(int offset) { 2847 queue.add(new Tuple(_ARGV_OFFSET_, offset)); 2848 } 2849 2850 /** 2851 * <p>applyRS.</p> 2852 */ 2853 public void applyRS() { 2854 queue.add(new Tuple(_APPLY_RS_)); 2855 } 2856 2857 /** 2858 * <p>function.</p> 2859 * 2860 * @param func_name a {@link java.lang.String} object 2861 * @param num_formal_params a int 2862 */ 2863 public void function(String func_name, int num_formal_params) { 2864 queue.add(new Tuple(_FUNCTION_, func_name, num_formal_params)); 2865 } 2866 //public void callFunction(Address addr, String func_name, int num_formal_params, int num_actual_params) { queue.add(new Tuple(_CALL_FUNCTION_, addr, func_name, num_formal_params, num_actual_params)); } 2867 2868 /** 2869 * <p>callFunction.</p> 2870 * 2871 * @param has_func_addr a {@link org.sentrysoftware.jawk.intermediate.HasFunctionAddress} object 2872 * @param func_name a {@link java.lang.String} object 2873 * @param num_formal_params a int 2874 * @param num_actual_params a int 2875 */ 2876 public void callFunction(HasFunctionAddress has_func_addr, String func_name, int num_formal_params, int num_actual_params) { 2877 queue.add(new Tuple(_CALL_FUNCTION_, has_func_addr, func_name, num_formal_params, num_actual_params)); 2878 } 2879 2880 /** 2881 * <p>setReturnResult.</p> 2882 */ 2883 public void setReturnResult() { 2884 queue.add(new Tuple(_SET_RETURN_RESULT_)); 2885 } 2886 2887 /** 2888 * <p>returnFromFunction.</p> 2889 */ 2890 public void returnFromFunction() { 2891 queue.add(new Tuple(_RETURN_FROM_FUNCTION_)); 2892 } 2893 2894 /** 2895 * <p>setNumGlobals.</p> 2896 * 2897 * @param num_globals a int 2898 */ 2899 public void setNumGlobals(int num_globals) { 2900 queue.add(new Tuple(_SET_NUM_GLOBALS_, num_globals)); 2901 } 2902 2903 /** 2904 * <p>close.</p> 2905 */ 2906 public void close() { 2907 queue.add(new Tuple(_CLOSE_)); 2908 } 2909 2910 /** 2911 * <p>applySubsep.</p> 2912 * 2913 * @param count a int 2914 */ 2915 public void applySubsep(int count) { 2916 queue.add(new Tuple(_APPLY_SUBSEP_, count)); 2917 } 2918 2919 /** 2920 * <p>deleteArrayElement.</p> 2921 * 2922 * @param offset a int 2923 * @param is_global a boolean 2924 */ 2925 public void deleteArrayElement(int offset, boolean is_global) { 2926 queue.add(new Tuple(_DELETE_ARRAY_ELEMENT_, offset, is_global)); 2927 } 2928 2929 /** 2930 * <p>deleteArray.</p> 2931 * 2932 * @param offset a int 2933 * @param is_global a boolean 2934 */ 2935 public void deleteArray(int offset, boolean is_global) { 2936 queue.add(new Tuple(_DELETE_ARRAY_, offset, is_global)); 2937 } 2938 2939 /** 2940 * <p>setExitAddress.</p> 2941 * 2942 * @param addr a {@link org.sentrysoftware.jawk.intermediate.Address} object 2943 */ 2944 public void setExitAddress(Address addr) { 2945 queue.add(new Tuple(_SET_EXIT_ADDRESS_, addr)); 2946 } 2947 2948 /** 2949 * <p>setWithinEndBlocks.</p> 2950 * 2951 * @param b a boolean 2952 */ 2953 public void setWithinEndBlocks(boolean b) { 2954 queue.add(new Tuple(_SET_WITHIN_END_BLOCKS_, b)); 2955 } 2956 2957 /** 2958 * <p>exitWithCode.</p> 2959 */ 2960 public void exitWithCode() { 2961 queue.add(new Tuple(_EXIT_WITH_CODE_)); 2962 } 2963 2964 /** 2965 * <p>exitWithCode.</p> 2966 */ 2967 public void exitWithoutCode() { 2968 queue.add(new Tuple(_EXIT_WITHOUT_CODE_)); 2969 } 2970 2971 /** 2972 * <p>regexp.</p> 2973 * 2974 * @param regexp_str a {@link java.lang.String} object 2975 */ 2976 public void regexp(String regexp_str) { 2977 queue.add(new Tuple(_REGEXP_, regexp_str)); 2978 } 2979 2980 /** 2981 * <p>regexpPair.</p> 2982 */ 2983 public void conditionPair() { 2984 queue.add(new Tuple(_CONDITION_PAIR_)); 2985 } 2986 2987 /** 2988 * <p>isIn.</p> 2989 */ 2990 public void isIn() { 2991 queue.add(new Tuple(_IS_IN_)); 2992 } 2993 2994 /** 2995 * <p>castInt.</p> 2996 */ 2997 public void castInt() { 2998 queue.add(new Tuple(_CAST_INT_)); 2999 } 3000 3001 /** 3002 * <p>castDouble.</p> 3003 */ 3004 public void castDouble() { 3005 queue.add(new Tuple(_CAST_DOUBLE_)); 3006 } 3007 3008 /** 3009 * <p>castString.</p> 3010 */ 3011 public void castString() { 3012 queue.add(new Tuple(_CAST_STRING_)); 3013 } 3014 3015 /** 3016 * <p>scriptThis.</p> 3017 */ 3018 public void scriptThis() { 3019 queue.add(new Tuple(_THIS_)); 3020 } 3021 3022 /** 3023 * <p>extension.</p> 3024 * 3025 * @param extension_keyword a {@link java.lang.String} object 3026 * @param param_count a int 3027 * @param is_initial a boolean 3028 */ 3029 public void extension(String extension_keyword, int param_count, boolean is_initial) { 3030 queue.add(new Tuple(_EXTENSION_, extension_keyword, param_count, is_initial)); 3031 } 3032 3033 /** 3034 * <p>dump.</p> 3035 * 3036 * @param ps a {@link java.io.PrintStream} object 3037 */ 3038 public void dump(PrintStream ps) { 3039 ps.println("(" + version_manager + ")"); 3040 ps.println(); 3041 for (int i = 0; i < queue.size(); i++) { 3042 Address address = address_indexes.get(i); 3043 if (address == null) { 3044 ps.println(i + " : " + queue.get(i)); 3045 } else { 3046 ps.println(i + " : [" + address + "] : " + queue.get(i)); 3047 } 3048 } 3049 } 3050 3051 /** 3052 * <p>top.</p> 3053 * 3054 * @return a {@link org.sentrysoftware.jawk.intermediate.Position} object 3055 */ 3056 public Position top() { 3057 return new PositionImpl(); 3058 } 3059 3060 /** 3061 * Executed after all tuples are entered in the queue. 3062 * Its main functions are: 3063 * <ul> 3064 * <li>Assign queue.next to the next element in the queue. 3065 * <li>Calls touch(...) per Tuple so that addresses can be normalized/assigned/allocated 3066 * properly. 3067 * </ul> 3068 */ 3069 public void postProcess() { 3070 assert queue.isEmpty() || !queue.get(0).hasNext() : "postProcess() already executed"; 3071 // allocate nexts 3072 for (int i = 0; i < queue.size() - 1; i++) { 3073 queue.get(i).setNext(queue.get(i + 1)); 3074 } 3075 // touch per element 3076 for (Tuple tuple : queue) { 3077 tuple.touch(queue); 3078 } 3079 } 3080 3081 /** Map of global variables offsets */ 3082 private Map<String, Integer> global_var_offset_map = new HashMap<String, Integer>(); 3083 3084 /** Map of global arrays */ 3085 private Map<String, Boolean> global_var_aarray_map = new HashMap<String, Boolean>(); 3086 3087 /** List of user function names */ 3088 private Set<String> function_names = null; 3089 3090 /** 3091 * Accept a {variable_name -> offset} mapping such that global variables can be 3092 * assigned while processing name=value and filename command-line arguments. 3093 * 3094 * @param varname Name of the global variable 3095 * @param offset What offset to use for the variable 3096 * @param is_array Whether the variable is actually an array 3097 */ 3098 public void addGlobalVariableNameToOffsetMapping(String varname, int offset, boolean is_array) { 3099 if (global_var_offset_map.get(varname) != null) { 3100 assert global_var_aarray_map.get(varname) != null; 3101 return; 3102 } 3103 global_var_offset_map.put(varname, offset); 3104 global_var_aarray_map.put(varname, is_array); 3105 } 3106 3107 /** 3108 * Accept a set of function names from the parser. This is 3109 * useful for invalidating name=value assignments from the 3110 * command line parameters, either via -v arguments or 3111 * passed into ARGV. 3112 * 3113 * @param function_names A set of function name strings. 3114 */ 3115 public void setFunctionNameSet(Set<String> function_names) { 3116 // setFunctionNameSet is called with a keySet from 3117 // a HashMap as a parameter, which is NOT 3118 // Serializable. Creating a new HashSet around 3119 // the parameter resolves the issue. 3120 // Otherwise, attempting to serialize this 3121 // object results in a NotSerializableEexception 3122 // being thrown because of function_names field 3123 // being a keyset from a HashMap. 3124 this.function_names = new HashSet<String>(function_names); 3125 } 3126 3127 /** 3128 * <p>getGlobalVariableOffsetMap.</p> 3129 * 3130 * @return a {@link java.util.Map} object 3131 */ 3132 public Map<String, Integer> getGlobalVariableOffsetMap() { 3133 return global_var_offset_map; 3134 } 3135 3136 /** 3137 * <p>getGlobalVariableAarrayMap.</p> 3138 * 3139 * @return a {@link java.util.Map} object 3140 */ 3141 public Map<String, Boolean> getGlobalVariableAarrayMap() { 3142 return global_var_aarray_map; 3143 } 3144 3145 /** 3146 * <p>getFunctionNameSet.</p> 3147 * 3148 * @return a {@link java.util.Set} object 3149 */ 3150 public Set<String> getFunctionNameSet() { 3151 assert function_names != null; 3152 return function_names; 3153 } 3154 3155 /** linenumber stack ... */ 3156 private MyStack<Integer> lineno_stack = new LinkedListStackImpl<Integer>(); 3157 3158 /** 3159 * Push the current line number onto the line number stack. 3160 * This is called by the parser to keep track of the 3161 * current source line number. Keeping track of line 3162 * numbers this way allows the runtime to report 3163 * more meaningful errors by providing source line numbers 3164 * within error reports. 3165 * 3166 * @param lineno The current source line number. 3167 */ 3168 public void pushSourceLineNumber(int lineno) { 3169 lineno_stack.push(lineno); 3170 } 3171 3172 /** 3173 * <p>popSourceLineNumber.</p> 3174 * 3175 * @param lineno a int 3176 */ 3177 public void popSourceLineNumber(int lineno) { 3178 int tos = lineno_stack.pop(); 3179 assert (lineno == tos); 3180 } 3181 3182 3183 /** 3184 * Intermediate file version manager. Ensures the AwkTuples 3185 * class version matches the version supported by the interpreter/compiler. 3186 */ 3187 private static class VersionManager implements Serializable { 3188 3189 private static final long serialVersionUID = -2015316238483923915L; 3190 3191 /** 3192 * Class version number. 3193 * This number is modified by the developer. 3194 * It should be modified only if modifications 3195 * to pre-existing tuple arguments are modified, 3196 * or if instruction codes are removed. 3197 * <p> 3198 * <ul> 3199 * <li> Version 1 - Initial release. 3200 * <li> Version 2 - Changes to support compilation to JVM. 3201 * </ul> 3202 * 3203 */ 3204 private static final int CLASS_VERSION = 2; 3205 3206 /** 3207 * Instance version number. 3208 * The only way it could be different from the 3209 * class version is only during deserialization. 3210 */ 3211 private int INSTANCE_VERSION = CLASS_VERSION; 3212 3213 /** 3214 * Upon deserialization, ensures the instance 3215 * version matches the class version. 3216 * @throws IOException upon an IO error 3217 * @throws ClassNotFoundException if the class 3218 * that is deserialized cannot be found 3219 * @throws InvalidClassException if the 3220 * instance version does not match 3221 * the class version 3222 */ 3223 private void readObject(ObjectInputStream ois) 3224 throws IOException, ClassNotFoundException 3225 { 3226 INSTANCE_VERSION = ois.readInt(); 3227 if (INSTANCE_VERSION != CLASS_VERSION) { 3228 throw new InvalidClassException("Invalid intermeidate file format (instance version " + INSTANCE_VERSION + " != class version " + CLASS_VERSION + ")"); 3229 } 3230 } 3231 3232 private void writeObject(ObjectOutputStream oos) 3233 throws IOException 3234 { 3235 oos.writeInt(INSTANCE_VERSION); 3236 } 3237 3238 @Override 3239 public String toString() { 3240 return "intermediate file format version = " + INSTANCE_VERSION; 3241 } 3242 } 3243 }