[
  {
    "path": ".gitignore",
    "content": "# Ignore the build and lib dirs\nbuild\ndep/*\n\n# Ignore any executables\nbin/*\n\n# Ignore Mac specific files\n.DS_Store \n\n# Ignore valgrind dumps\nvgcore.*\n\n# Ignore OpenJDK classes\njava/*\n\n# Ignore Class Files\ntest/*.class\n\n# Ignore test outputs\ntest/*.out\n\n.vscode/*"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "README.md",
    "content": "# ToyJVM\n\nExperimental Java Bytecode Interpreter written in C to understand Java concepts better.\n\n## Getting Started\n\nThese instructions will get you a copy of the project up and running on your local machine for development and testing purposes.\n\n## Prerequisites\n\n\n```Javac``` is required to compile Java codes into Java bytecodes.\n\n## Running the tests\n\nYou can run the tests with the ```test.sh``` script. As the project grows up, new tests will be added.\n\n## Running the software\n\nYou need to give the class name without extension to the executable. For example ```./bin/main test/HelloWorld``` will run the test/HelloWorld.class file.\n"
  },
  {
    "path": "include/attribute.h",
    "content": "#ifndef ATTRIBUTE_H_\n#define ATTRIBUTE_H_\n#include <inttypes.h>\n#include <stdio.h>\n\ntypedef struct attribute_info {\n    uint16_t attribute_name_index;\n    uint32_t attribute_length;\n    uint8_t* info;\n}attribute_info;\n\ntypedef struct exception_table{ // aligned.\n    uint16_t start_pc;\n    uint16_t end_pc;\n    uint16_t handler_pc;\n    uint16_t catch_type;\n} exception_table;\n\n//If the method is either native or abstract, its method_info structure must not have a \n//Code attribute in its attributes table. Otherwise, its method_info structure must have\n//exactly one Code attribute in its attributes table\ntypedef struct Code_attribute {\n    uint16_t attribute_name_index;\n    uint32_t attribute_length;\n    uint16_t max_stack;\n    uint16_t max_locals;\n    uint32_t code_length;\n    uint8_t* code;\n    uint16_t exception_table_lenght;\n    exception_table* exceptionTable;\n    uint16_t attributes_count;\n    attribute_info* attributes;\n}Code_attribute;\n\nattribute_info getAttribute_Info(FILE* fd);\nCode_attribute getCode_AttributeFromAttribute_info(attribute_info fd);\n\nvoid destroyAttribute_Info(attribute_info* attribute);\n#endif"
  },
  {
    "path": "include/classFile.h",
    "content": "#ifndef CLASSFILE_H_\n#define CLASSFILE_H_\n#include <inttypes.h>\n#include \"machine.h\"\n#include \"constantPool.h\"\n#include \"field.h\"\n#include \"method.h\"\n\ntypedef struct field_info field_info;\n\ntypedef struct ClassFile{\n    uint32_t       magic;\n    uint16_t       minor_version;\n    uint16_t       major_version;\n    uint16_t       constant_pool_count;\n    cp_info*       constant_pool; //[constant_pool_count-1]\n    uint16_t       access_flags;\n    uint16_t       this_class;\n    uint16_t       super_class;\n    uint16_t       interfaces_count;\n    uint16_t*      interfaces;\n    uint16_t       fields_count;\n    field_info*    fields;\n    uint16_t       methods_count;\n    method_info*   methods;\n    uint16_t       attributes_count;\n    attribute_info* attributes;\n    uint8_t initalized;\n}ClassFile;\n\nClassFile classFromFile(const char* filename);\n\nClassFile* getClassFromUtf8(CONSTANT_Utf8_info className_utf8, Machine* machine);\nClassFile* getClassFromName(const char* className, Machine* machine);\n\nint getNumArgs(ClassFile* cf, CONSTANT_Ref_info methodOrInterfaceRef);\n\nint isUtf8Equal(CONSTANT_Utf8_info s1, CONSTANT_Utf8_info s2);\nint isUtf8EqualsToString(CONSTANT_Utf8_info s1, const char* s2);\n\nvoid initClass(ClassFile* cf, Frame* frame);\nvoid destroyClass(ClassFile* cf);\n\nmethod_info* getMethodByName(ClassFile* cf, const char* name, const char* desc);\nmethod_info* canClassHandleMethod(ClassFile* cf, CONSTANT_Utf8_info name_utf8, CONSTANT_Utf8_info descriptor_utf8);\nint checkFormat(ClassFile* cf);\n/*\nReturns 1 if the class file passes the test. Anything else if not.\n\n1-The first four bytes must contain the right magic number.+\n2-All recognized attributes must be of the proper length.?\n3-The class file must not be truncated or have extra bytes at the end.-\n4-The constant pool must satisfy the constraints documented throughout §4.4.?\nFor example, each CONSTANT_Class_info structure in the constant pool \nmust contain in its name_index item a valid constant pool index for a CONSTANT_Utf8_info structure.\n6-All field references and method references in the constant pool must \nhave valid names, valid classes, and valid descriptors (§4.3).\n7-Format checking does not ensure that the given field or method actually \nexists in the given class, nor that the descriptors given refer to real classes. \nFormat checking ensures only that these items are well formed. More detailed \nchecking is performed when the bytecodes themselves are verified, and during resolution.\n*/\n#endif"
  },
  {
    "path": "include/constantPool.h",
    "content": "#ifndef CONSTANTPOOL_H_\n#define CONSTANTPOOL_H_\n#include <inttypes.h>\n#include <stdio.h>\n\ntypedef enum cp_tags{\n    CONSTANT_Class=7,\n\n    CONSTANT_Fieldref=9,\n\n    CONSTANT_Methodref=10,\n\n    CONSTANT_InterfaceMethodref=11,\n    CONSTANT_String=8,\n\n    CONSTANT_Integer=3,\n    CONSTANT_Float=4,\n    CONSTANT_Long=5,\n    CONSTANT_Double=6,\n    CONSTANT_NameAndType=12,\n    \n    CONSTANT_Utf8=1,\n\n    CONSTANT_MethodHandle=15,\n    CONSTANT_MethodType=16,\n    CONSTANT_InvokeDynamic=18\n}cp_tags;\n\n\n//////////////////////////////\n// CONSTANT INFO STRUCTURES //\n//////////////////////////////\n\n// the data written directly into the structures.\n// padding across the platforms should be\n// checked.\ntypedef struct CONSTANT_Class_info {\n    uint16_t name_index;\n}CONSTANT_Class_info;\n\ntypedef struct CONSTANT_Ref_info{\n    // also applies for The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures\n    uint16_t class_index;\n    uint16_t name_and_type_index;\n}CONSTANT_Ref_info;\n\n\ntypedef struct CONSTANT_String_info {\n    uint16_t string_index;\n}CONSTANT_String_info;\n\ntypedef struct CONSTANT_4BYTES_info {\n    uint32_t bytes;\n}CONSTANT_4BYTES_info;\n\ntypedef struct CONSTANT_8BYTES_info {\n    uint64_t bytes;\n}CONSTANT_8BYTES_info;\n\ntypedef struct CONSTANT_NameAndType_info {\n    uint16_t name_index;\n    uint16_t descriptor_index;\n}CONSTANT_NameAndType_info;\n\ntypedef struct CONSTANT_Utf8_info {  // not aligned\n    uint16_t length;\n    // 6 bytes padding\n    uint8_t* bytes;\n}CONSTANT_Utf8_info;\n\ntypedef struct CONSTANT_MethodHandle_info { // not aligned\n    uint8_t reference_kind; // ref to method handle.\n    // 1 byte compiler padding\n    uint16_t reference_index; \n}CONSTANT_MethodHandle_info;\n\ntypedef struct CONSTANT_MethodType_info {\n    uint16_t descriptor_index;\n    //The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) \n    //representing a method descriptor (§4.3.3). \n}CONSTANT_MethodType_info;\n\ntypedef struct CONSTANT_InvokeDynamic_info {\n    uint16_t bootstrap_method_attr_index;\n    uint16_t name_and_type_index;\n}CONSTANT_InvokeDynamic_info;\n\ntypedef enum array_type{\n    T_BOOLEAN =4,\n    T_CHAR    =5,\n    T_FLOAT   =6,\n    T_DOUBLE  =7,\n    T_BYTE \t  =8,\n    T_SHORT   =9,\n    T_INT \t  =10,\n    T_LONG \t  =11\n}array_type;\n\ntypedef struct CONSTANT_Array_info{  // custom\n    int32_t size; // array size is signed 32 bit int.\n    array_type atype;\n    uint8_t* ref;\n}CONSTANT_Array_info;\n\nunion CONSTANT_INFO {\n    CONSTANT_Class_info class_info;\n    CONSTANT_Ref_info   ref_info;\n    CONSTANT_String_info    string_info;\n    CONSTANT_4BYTES_info   _4BYTES_info;\n    CONSTANT_8BYTES_info  _8BYTES_info;\n    CONSTANT_NameAndType_info   nameAndType_info;\n    CONSTANT_Utf8_info  utf8_info;\n    CONSTANT_MethodHandle_info  methodHandle_info;\n    CONSTANT_MethodType_info  methodType_info;\n    CONSTANT_InvokeDynamic_info invodeDynamic_info;\n}; // unified for runtime constant pool\n\ntypedef struct cp_info {\n    uint8_t tag;\n    union CONSTANT_INFO info;\n}cp_info;\n\n\ncp_info cp_infoFromFile(FILE* fd);\nvoid destroyCp_Info(cp_info* info);\n\n\n#endif"
  },
  {
    "path": "include/debug.h",
    "content": "#ifdef DEBUG\n# define DEBUG_PRINT(x) printf x\n#else\n# define DEBUG_PRINT(x) do {} while(0)\n#endif"
  },
  {
    "path": "include/endianness.h",
    "content": "#ifndef ENDIAN_H_\n#define ENDIAN_H_\n\n// endian.h was not cross platform and was under a different\n// name in different OS'es. Assuming most of the desktop cpu's \n// are little endian, I forged these functions into internal swap\n// functions in gcc and clang. The visual studio users may use\n// the _byteswap_ushort, _byteswap_ulong, _byteswap_uint64 functions\n// respectively. \n#define be16toh(x) __builtin_bswap16(x)\n#define be32toh(x) __builtin_bswap32(x)\n#define be64toh(x) __builtin_bswap64(x)\n\n#endif"
  },
  {
    "path": "include/field.h",
    "content": "#ifndef FIELD_H_\n#define FIELD_H_\n#include <inttypes.h>\n#include \"attribute.h\"\n#include <stdio.h>\n#include \"classFile.h\"\n#include \"constantPool.h\"\n\ntypedef struct JavaClass JavaClass;\ntypedef enum field_access_flags{\n    F_ACC_PUBLIC \t    = 0x0001, // Declared public; may be accessed from outside its package.\n    F_ACC_PRIVATE \t    = 0x0002, // Declared private; usable only within the defining class.\n    F_ACC_PROTECTED \t= 0x0004, // Declared protected; may be accessed within subclasses.\n    F_ACC_STATIC \t    = 0x0008, // Declared static.\n    F_ACC_FINAL \t    = 0x0010, // Declared final; never directly assigned to after object construction (JLS §17.5).\n    F_ACC_VOLATILE \t    = 0x0040, // Declared volatile; cannot be cached.\n    F_ACC_TRANSIENT \t= 0x0080, // Declared transient; not written or read by a persistent object manager.\n    F_ACC_SYNTHETIC \t= 0x1000, // Declared synthetic; not present in the source code.\n    F_ACC_ENUM \t        = 0x4000  // Declared as an element of an enum. \n}access_flags;\n\ntypedef struct field_info {\n    uint16_t access_flags;\n    uint16_t name_index;\n    uint16_t descriptor_index;\n    uint16_t attributes_count;\n    attribute_info* attributes;\n    uint64_t value;\n}field_info;\n\nfield_info getField_Info(FILE* fd);\n\nfield_info* getStaticField(ClassFile* cf, CONSTANT_Utf8_info fieldName, CONSTANT_Utf8_info fieldDesc);\nfield_info* getField(JavaClass* jc, CONSTANT_Utf8_info fieldName, CONSTANT_Utf8_info fieldDesc);\nvoid putField(JavaClass* instance, CONSTANT_Utf8_info fieldName, CONSTANT_Utf8_info fieldDesc, uint64_t val);\n\nvoid destroyField_Info(field_info* field);\n#endif"
  },
  {
    "path": "include/frame.h",
    "content": "#ifndef FRAME_H_\n#define FRAME_H_\n#include <inttypes.h>\n//#include \"stack.h\"\n#include \"attribute.h\"\n#include \"constantPool.h\"\n\ntypedef struct ClassFile ClassFile;\ntypedef struct Machine Machine;\ntypedef uint64_t LocalVariable;\n// A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. \n// A pair of local variables can hold a value of type long or double. \n// But we wont implement this, instead a local variable in our jvm can hold up to 64 bits.\ntypedef uint64_t Operand;\n// Each entry on the operand stack can hold a value of any Java Virtual Machine type, including a value of type long or type double. \n\ntypedef struct Frame{\n    LocalVariable* localVariables;\n    struct Stack* operandStack;\n    struct Machine* machine;\n    struct ClassFile* classRef;\n    uint32_t pc; // program counter\n    Code_attribute* code;\n    //A run-time constant pool is a per-class or per-interface run-time representation of the constant_pool table in a class file (§4.4).\n    //It contains several kinds of constants, ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time.\n} Frame;\n\nFrame createNewFrame (Code_attribute code, ClassFile* cf, Machine* machine);\nvoid destroyFrame (Frame* frame);\n#endif"
  },
  {
    "path": "include/heap.h",
    "content": "#ifndef HEAP_H_\n#define HEAP_H_\n#include <inttypes.h>\n#include <stdlib.h>\n\ntypedef struct HeapObject{\n    void* addr;\n    size_t size;\n    uint8_t isUsed;\n}HeapObject;\n\ntypedef struct Heap{\n    uint64_t size;\n    uint64_t top;\n    HeapObject* heap;\n}Heap;\n\nHeap initHeap(size_t size);\nvoid* hGet(uint64_t addr, Heap* heap);\nuint64_t hAlloc(size_t size, Heap* heap);\nuint64_t hExtend(uint64_t addr, size_t size, Heap* heap);\nvoid* hFree(uint64_t addr, Heap* heap);\n\nvoid destroyHeap(Heap* heap);\n#endif"
  },
  {
    "path": "include/javaClass.h",
    "content": "#ifndef JAVACLASS_H_\n#define JAVACLASS_H_\n#include \"classFile.h\"\n\ntypedef struct JavaClass{\n    ClassFile* classFile;\n    field_info* fields;\n}JavaClass;\n\nvoid initInstanceFields(JavaClass* instance);\n\n#endif"
  },
  {
    "path": "include/machine.h",
    "content": "#ifndef MACHINE_H_\n#define MACHINE_H_\n#include \"opcode.h\"\n#include \"stack.h\"\n#include \"heap.h\"\n\ntypedef struct Machine{\n    struct ClassFile* classFiles;\n    uint64_t numClasses;\n    Stack* JVMSTACK;\n    Heap* heap;\n}Machine;\n\nvoid* executeCode(Machine* machine, OPCODE** opcodes);\nvoid destroyMachine(Machine* machine);\n\n#endif"
  },
  {
    "path": "include/method.h",
    "content": "#ifndef METHOD_H_\n#define METHOD_H_\n#include \"attribute.h\"\n#include \"field.h\"\n\ntypedef struct field_info method_info; // same as field info\n\ntypedef enum method_access_flags{\n    M_ACC_PUBLIC \t      = 0x0001, // Declared public; may be accessed from outside its package.\n    M_ACC_PRIVATE \t      = 0x0002, // Declared private; accessible only within the defining class.\n    M_ACC_PROTECTED \t  = 0x0004, // Declared protected; may be accessed within subclasses.\n    M_ACC_STATIC  \t      = 0x0008, // Declared static.\n    M_ACC_FINAL   \t      = 0x0010, // Declared final; must not be overridden (§5.4.5).\n    M_ACC_SYNCHRONIZED    = 0x0020, // Declared synchronized; invocation is wrapped by a monitor use.\n    M_ACC_BRIDGE  \t      = 0x0040, // A bridge method, generated by the compiler.\n    M_ACC_VARARGS \t      = 0x0080, // Declared with variable number of arguments.\n    M_ACC_NATIVE  \t      = 0x0100, // Declared native; implemented in a language other than Java.\n    M_ACC_ABSTRACT \t      = 0x0400, // Declared abstract; no implementation is provided.\n    M_ACC_STRICT  \t      = 0x0800, // Declared strictfp; floating-point mode is FP-strict.\n    M_ACC_SYNTHETIC \t  = 0x1000 \t// Declared synthetic; not present in the source code. \n}method_access_flags;\n\n#define getMethod_Info(fd) getField_Info(fd) // same too, no need to reimplement\n#define destroyMethod_Info(info) destroyField_Info(info)\n\n#endif\n"
  },
  {
    "path": "include/opcode.h",
    "content": "#ifndef OPCODE_H_\n#define OPCODE_H_\n#include <inttypes.h>\n#include \"frame.h\"\n\ntypedef void* OPCODE(struct Frame*);\n\nOPCODE** initOpcodes();\n\n\ntypedef enum OPCODENAMES{\n    ICONST_M1     = 0x02,\n    ICONST_0      = 0x03,\n    ICONST_1      = 0x04,\n    ICONST_2      = 0x05,\n    ICONST_3      = 0x06,\n    ICONST_4      = 0x07,\n    ICONST_5      = 0x08,\n    LCONST_0      = 0x09,\n    LCONST_1      = 0x0A,\n    DCONST_0      = 0x0E,\n    DCONST_1      = 0x0F,\n    BIPUSH        = 0x10,\n    SIPUSH        = 0x11,\n    LDC           = 0x12,\n    LDC2_W        = 0x14,\n    ILOAD         = 0x15,\n    LLOAD         = 0x16,\n    DLOAD         = 0x18,\n    ILOAD_0       = 0x1A,\n    ILOAD_1       = 0x1B,\n    ILOAD_2       = 0x1C,\n    ILOAD_3       = 0x1D,\n    LLOAD_0       = 0x1E,\n    LLOAD_1       = 0x1F,\n    LLOAD_2       = 0x20,\n    LLOAD_3       = 0x21,\n    DLOAD_3       = 0x29,\n    ALOAD_0       = 0x2A,\n    ALOAD_1       = 0x2B,\n    ALOAD_2       = 0x2C,\n    ALOAD_3       = 0x2D,\n    IALOAD        = 0x2E,\n    AALOAD        = 0x32,\n    ISTORE        = 0x36,\n    LSTORE        = 0x37,\n    DSTORE        = 0x39,\n    ISTORE_0      = 0x3B,\n    ISTORE_1      = 0x3C,\n    ISTORE_2      = 0x3D,\n    ISTORE_3      = 0x3E,\n    LSTORE_0      = 0x3F,\n    LSTORE_1      = 0x40,\n    LSTORE_2      = 0x41,\n    LSTORE_3      = 0x42,\n    DSTORE_3      = 0x4A,\n    ASTORE_0      = 0x4B,\n    ASTORE_1      = 0x4C,\n    ASTORE_2      = 0x4D,\n    ASTORE_3      = 0x4E,\n    IASTORE       = 0x4F,\n    AASTORE       = 0x53,\n    POP           = 0x57,\n    DUP           = 0x59,\n    IADD          = 0x60,\n    LADD          = 0x61,\n    DADD          = 0x63,\n    ISUB          = 0x64,\n    DSUB          = 0x67,\n    IMUL          = 0x68,\n    DMUL          = 0x6B,\n    DDIV          = 0x6F,\n    IREM          = 0x70,\n    IINC          = 0x84,\n    I2D           = 0x87,\n    I2C           = 0x92,\n    DCMPG         = 0x98,\n    IFNE          = 0x9A,\n    IFLT          = 0x9B,\n    IFGE          = 0x9C,\n    IFLE          = 0x9E,\n    IF_ICMPLT     = 0xA1,\n    IF_ICMPGE     = 0xA2,\n    IF_ICMPGT     = 0xA3,\n    IF_ICMPLE     = 0xA4,\n    GOTO          = 0xA7,\n    IRET          = 0xAC,\n    LRET          = 0xAD,\n    DRETURN       = 0xAF,\n    ARETURN       = 0xB0,\n    RETURN        = 0xB1,\n    GETSTATIC     = 0xB2,\n    PUTSTATIC     = 0xB3,\n    GETFIELD      = 0xB4,\n    PUTFIELD      = 0xB5,\n    INVOKEVIRTUAL = 0xB6,\n    INVOKESPECIAL = 0xB7,\n    INVOKESTATIC  = 0xB8,\n    NEW           = 0xBB,\n    NEWARRAY      = 0xBC,\n    ANEWARRAY     = 0xBD,\n    ARRAYLENGTH   = 0xBE\n}OPCODENAMES;\n\n\n#endif"
  },
  {
    "path": "include/printStream.h",
    "content": "#ifndef PRINTSTREAM_H_\n#define PRINTSTREAM_H_\n#include <inttypes.h>\n#include \"frame.h\"\n#include \"classFile.h\"\n\nvoid handlePrintStream(uint64_t* localVariables, Frame* frame, CONSTANT_Utf8_info name_utf8, CONSTANT_Utf8_info desc_utf8);\n \n#endif"
  },
  {
    "path": "include/stack.h",
    "content": "#ifndef STACK_H_\n#define STACK_H_\n#include <stdint.h>\n#include \"frame.h\"\n\ntypedef enum StackType{\n    TYPE_OPERANDSTACK = sizeof(uint64_t),\n    TYPE_JVMSTACK = sizeof(struct Frame)\n}StackType;\n\ntypedef struct Stack{\n    unsigned char* stack;\n    StackType stackType;\n    uint64_t top;\n    uint64_t maxSize;\n}Stack;\n\nStack initStack(uint64_t numItems, StackType stackType);\n// size is given as numItems here\n\nvoid* popStack(Stack* stack);\nvoid pushStack(void* val, Stack* stack);\nvoid* peekStack(Stack* stack);\n\nvoid destroyStack(Stack* stack);\n#endif "
  },
  {
    "path": "include/stringBuilder.h",
    "content": "#ifndef STRINGBUILDER_H_\n#define STRINGBUILDER_H_\n#include <inttypes.h>\n#include \"frame.h\"\n#include \"classFile.h\"\n\n\nvoid handleStringBuilder(uint64_t* localVariables, Frame* frame, CONSTANT_Utf8_info name_utf8, CONSTANT_Utf8_info desc_utf8);\n \n#endif"
  },
  {
    "path": "makefile",
    "content": "SRCDIR\t= src\nHDRDIR  = include\nOBJDIR\t= build\nBINDIR\t= bin\nDEPDIR\t= dep\n\nCC\t= gcc\nTARGET\t= main\nCFLAGS\t= -g -O0 -std=c99 -I$(HDRDIR) #-DDEBUG=1\nLFLAGS\t= -lm\n\nSOURCES\t:= $(wildcard $(SRCDIR)/*.c)\nHEADERS := $(wildcard $(HDRDIR)/*.h)\nOBJECTS\t:= $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)\nDEPS\t:= $(OBJECTS:$(OBJDIR)/%.o=$(DEPDIR)/%.d)\n\nREMOVE\t:= rm -rf\n\n# Linking\n$(BINDIR)/$(TARGET): $(OBJECTS) $(CMN_OBJ)\n\tmkdir -p $(BINDIR)\n\t$(CC) $(LFLAGS) -o $@ $(OBJECTS) $(CMN_OBJ)\n\t@echo \"Linking complete\"\n\n-include $(DEPS)\n\n# Compilation\n$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c\n\tmkdir -p $(OBJDIR)\n\tmkdir -p $(DEPDIR)\n\t$(CC) -c $(CFLAGS) $< -o $@\n\t$(CC) -I$(HDRDIR) -MM -MT '$(OBJDIR)/$*.o' $(SRCDIR)/$*.c > $(DEPDIR)/$*.d\n\t@echo \"Compiled $<\"\n\n# Generate file list for cscope\ncscope.files: $(SOURCES) $(HEADERS)\n\techo $(SOURCES) $(HEADERS) > cscope.files\n\n# Generate cscope database\ncscope.out: cscope.files\n\tcscope -q -R -b -i cscope.files\n\n.PHONY: clean\nclean:\n\t$(REMOVE) $(OBJECTS) $(OBJDIR) $(BINDIR) $(DEPDIR)\n\t@echo \"Deleted $<\"\n\n.PHONY: remove\nremove:\n\t$(REMOVE) $(BINDIR)/$(TARGET)\n\t$(REMOVE) $(OBJECTS)\n\t$(REMOVE) $(DEPS)\n\t$(REMOVE) cscope.*\n\t@echo \"Deleted $<\"\n\n.PHONY: cscope\ncscope: cscope.out\n\n.PHONY: all\nall: $(BINDIR)/$(TARGET)\n"
  },
  {
    "path": "readme.md",
    "content": "# ToyJVM\n\nExperimental Java Bytecode Interpreter written in C to understand Java concepts better.\n\n## Getting Started\n\nThese instructions will get you a copy of the project up and running on your local machine for development and testing purposes.\n\n## Prerequisites\n\n\n```Javac``` is required to compile Java codes into Java bytecodes.\n\n## Running the tests\n\nYou can run the tests with the ```test.sh``` script. As the project grows up, new tests will be added.\n\n## Running the software\n\nYou need to give the class name without extension to the executable. For example ```./bin/main test/HelloWorld``` will run the HelloWorld.class file."
  },
  {
    "path": "src/attribute.c",
    "content": "#include \"attribute.h\"\n#include <stdlib.h>\n#include \"endianness.h\"\n#include <string.h>\nattribute_info getAttribute_Info(FILE* fd){\n    attribute_info attribute;\n    fread(&attribute.attribute_name_index,sizeof(attribute.attribute_name_index),1,fd);\n    attribute.attribute_name_index = be16toh(attribute.attribute_name_index);\n\n    fread(&attribute.attribute_length,sizeof(attribute.attribute_length),1,fd);\n    attribute.attribute_length = be32toh(attribute.attribute_length);\n\n    attribute.info = malloc(attribute.attribute_length); // leak\n    fread(attribute.info,attribute.attribute_length,1,fd);\n    return attribute;\n}\n\nvoid destroyAttribute_Info(attribute_info* attribute){\n    free(attribute->info);\n}\n\nCode_attribute getCode_AttributeFromAttribute_info(attribute_info attributeInfo){\n    Code_attribute attribute;\n    /*\n    uint16_t attribute_name_index;\n    uint32_t attribute_length;\n    uint16_t max_stack;\n    uint16_t max_locals;\n    uint32_t code_length;\n    uint8_t* code;\n    uint16_t exception_table_lenght;\n    exception_table* exceptionTable;\n    uint16_t attributes_count;\n    attribute_info* attributes;\n    */\n    attribute.attribute_name_index = attributeInfo.attribute_name_index;\n    attribute.attribute_length = attributeInfo.attribute_length;\n\n    int memOffset=0;\n    memcpy(&attribute.max_stack, attributeInfo.info+memOffset,sizeof(attribute.max_stack));\n    attribute.max_stack = be16toh(attribute.max_stack);\n    memOffset +=sizeof(attribute.max_stack);\n\n    memcpy(&attribute.max_locals, attributeInfo.info+memOffset,sizeof(attribute.max_locals));\n    attribute.max_locals = be16toh(attribute.max_locals);\n    memOffset +=sizeof(attribute.max_locals);\n\n    memcpy(&attribute.code_length, attributeInfo.info+memOffset,sizeof(attribute.code_length));\n    attribute.code_length = be32toh(attribute.code_length);\n    memOffset +=sizeof(attribute.code_length);\n\n    attribute.code = attributeInfo.info+memOffset; // leak\n    memOffset +=attribute.code_length;\n\n    // remainings will be implemented later. \n    return attribute;\n}\n"
  },
  {
    "path": "src/classFile.c",
    "content": "#include \"classFile.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include \"endianness.h\"\n#include \"field.h\"\n#include \"method.h\"\n#include \"constantPool.h\"\n#include \"string.h\"\n#include \"debug.h\"\n\nClassFile classFromFile(const char* filename){\n    FILE *fd;\n    fd = fopen(filename, \"r\");\n\n    if (fd == NULL){\n        printf(\"File: %s\\n\",filename);\n        perror(\"Error while opening the file.\\n\");\n        exit(EXIT_FAILURE);\n    }\n\n    /*\n    uint32_t       magic;\n    uint16_t       minor_version;\n    uint16_t       major_version;\n    uint16_t       constant_pool_count;\n    cp_info        constant_pool[constant_pool_count-1];\n    */\n    ClassFile classFile;\n    fread(&classFile.magic,sizeof(classFile.magic),1,fd);\n    classFile.magic = be32toh(classFile.magic); // 0xCAFEBABE\n\n    fread(&classFile.minor_version,sizeof(classFile.minor_version),1,fd);\n    classFile.minor_version = be16toh(classFile.minor_version);\n\n    fread(&classFile.major_version,sizeof(classFile.major_version),1,fd);\n    classFile.major_version = be16toh(classFile.major_version);\n\n    fread(&classFile.constant_pool_count,sizeof(classFile.constant_pool_count),1,fd);\n    classFile.constant_pool_count = be16toh(classFile.constant_pool_count);\n\n    classFile.constant_pool = malloc (sizeof(cp_info) * (classFile.constant_pool_count-1)); // leak\n    // The value of the constant_pool_count item is equal to the number of entries in the constant_pool table plus one.\n    //A constant_pool index is considered valid if it is greater than zero and less than constant_pool_count, \n    //with the exception for constants of type long and double noted in §4.4.5.\n\n    for (int poolCount=0; poolCount < classFile.constant_pool_count-1; poolCount++){ // -1 same reason above\n        classFile.constant_pool[poolCount] = cp_infoFromFile(fd); // leak \n        if (classFile.constant_pool[poolCount].tag == CONSTANT_Long || classFile.constant_pool[poolCount].tag == CONSTANT_Double){\n            // all 8 byte types in cp takes two indexes. So increase extra.\n            classFile.constant_pool[++poolCount].tag=0;\n        } \n    }\n\n    /*\n    u2             access_flags;\n    u2             this_class;\n    u2             super_class;\n    u2             interfaces_count;\n    u2             interfaces[interfaces_count];\n    u2             fields_count;\n    field_info     fields[fields_count];\n    */\n\n    fread(&classFile.access_flags,sizeof(classFile.access_flags),1,fd);\n    classFile.access_flags = be16toh(classFile.access_flags);\n\n    fread(&classFile.this_class,sizeof(classFile.this_class),1,fd);\n    classFile.this_class = be16toh(classFile.this_class);\n\n    fread(&classFile.super_class,sizeof(classFile.super_class),1,fd);\n    classFile.super_class = be16toh(classFile.super_class);\n\n    fread(&classFile.interfaces_count,sizeof(classFile.interfaces_count),1,fd);\n    classFile.interfaces_count = be16toh(classFile.interfaces_count);\n\n    classFile.interfaces = malloc(classFile.interfaces_count * sizeof (uint16_t)); // leak\n    for (int interfaceCount=0; interfaceCount < classFile.interfaces_count; interfaceCount++){\n        uint16_t interface;\n        fread(&interface,sizeof(interface),1,fd);\n        classFile.interfaces[interfaceCount] = be16toh(interface);\n    }\n    \n    fread(&classFile.fields_count,sizeof(classFile.fields_count),1,fd);\n    classFile.fields_count = be16toh(classFile.fields_count);\n\n    classFile.fields = malloc(sizeof(field_info) * classFile.fields_count); // leak\n    for (int fieldCount=0; fieldCount < classFile.fields_count; fieldCount++){\n        classFile.fields[fieldCount] = getField_Info(fd); // leak\n    }\n\n    /*\n    u2             methods_count;\n    method_info    methods[methods_count];\n    u2             attributes_count;\n    attribute_info attributes[attributes_count];\n    */\n\n    fread(&classFile.methods_count,sizeof(classFile.methods_count),1,fd);\n    classFile.methods_count = be16toh(classFile.methods_count);\n\n    classFile.methods = malloc (sizeof(method_info) * classFile.methods_count); // leak\n    for (int methodCount = 0; methodCount<classFile.methods_count; methodCount++){\n        classFile.methods[methodCount] = getMethod_Info(fd); // leak\n    }\n\n    fread(&classFile.attributes_count,sizeof(classFile.attributes_count),1,fd);\n    classFile.attributes_count = be16toh(classFile.attributes_count);\n\n    classFile.attributes = malloc (sizeof(attribute_info) * classFile.attributes_count); // leak\n    for (int attributeCount = 0; attributeCount<classFile.attributes_count; attributeCount++){\n        classFile.attributes[attributeCount] = getAttribute_Info(fd); // leak\n    }\n\n    classFile.initalized = 0; // false\n\n    fclose(fd);\n    return classFile;\n}\n\nint isUtf8EqualsToString(CONSTANT_Utf8_info s1, const char* s2){\n    if (s1.length != strlen(s2))\n        return 0;\n    return !strncmp(s1.bytes,s2,s1.length);    \n}\n\nint isUtf8Equal(CONSTANT_Utf8_info s1, CONSTANT_Utf8_info s2){\n    if (s1.length != s2.length)\n        return 0; // false\n    return !strncmp(s1.bytes,s2.bytes,s1.length);\n}\n\nint getNumArgs(ClassFile* cf, CONSTANT_Ref_info methodOrInterfaceRef){\n    CONSTANT_NameAndType_info* nameAndType = &cf->constant_pool[methodOrInterfaceRef.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info descriptor_utf8 = cf->constant_pool[nameAndType->descriptor_index-1].info.utf8_info;\n    int numArgs = 0;\n    for (int index=0; index < descriptor_utf8.length; index++){\n        switch (descriptor_utf8.bytes[index]){\n            // todo check for array types\n            case 'L':\n                for (; descriptor_utf8.bytes[index] != ';'; index++){\n                }\n                numArgs++;\n                break;\n            case '(':\n                break;\n            case ')':\n                return numArgs;\n            default:\n                numArgs++;\n                break;\n        }\n    }\n    return numArgs;\n}\n\nClassFile* getClassFromUtf8(CONSTANT_Utf8_info className_utf8, Machine* machine){\n    // to C string\n    char className[className_utf8.length+1];\n    memcpy(&className,className_utf8.bytes,className_utf8.length);\n    className[className_utf8.length] = '\\0';\n\n    return getClassFromName(className, machine);\n}\n\nClassFile* getClassFromName(const char* className, Machine* machine){\n    // todo BTree\n    for (int classId=0; classId<machine->numClasses; classId++){\n        ClassFile* class = &machine->classFiles[classId];\n        CONSTANT_Class_info classInfo = class->constant_pool[class->this_class - 1].info.class_info;\n        CONSTANT_Utf8_info _className = class->constant_pool[classInfo.name_index-1].info.utf8_info;\n        if (isUtf8EqualsToString(_className, className)){\n            return class;\n        }\n        //printf(\"checked a class, id: %d : %.*s\\n\",class->this_class,class->constant_pool[class->this_class-1].info.utf8_info.length,class->constant_pool[class->this_class-1].info.utf8_info.bytes);\n        // todo\n        \n    }\n    // This is a hack in order to run System.out.println()\n    // check if its a native class\n    if (!strcmp(className, \"java/lang/System\") || !strcmp(className, \"java/io/PrintStream\") || !strcmp(className, \"java/lang/StringBuilder\"))\n        return NULL;\n    // create if not exists\n    char buf[strlen(className)+strlen(\".class\")+1];\n    strcpy(buf, className);\n    strcat(buf, \".class\");\n    machine->classFiles[machine->numClasses++] = classFromFile(buf);\n    return &machine->classFiles[machine->numClasses-1];\n}\n\nmethod_info* getMethodByName(ClassFile* cf, const char* name, const char* desc){\n    for (int methodId=0; methodId < cf->methods_count; methodId++){\n        CONSTANT_Utf8_info classMethodName_utf8 = cf->constant_pool[cf->methods[methodId].name_index-1].info.utf8_info; // todo possibly optimize this func\n        CONSTANT_Utf8_info classMethodDesc_utf8 = cf->constant_pool[cf->methods[methodId].descriptor_index-1].info.utf8_info; // todo possibly optimize this func\n        if (isUtf8EqualsToString(classMethodName_utf8, name) && isUtf8EqualsToString(classMethodDesc_utf8, desc)){\n            DEBUG_PRINT( (\"Found Method Name: %.*s\\n\",classMethodName_utf8.length,classMethodName_utf8.bytes));\n            return &cf->methods[methodId];\n        }\n    }\n    return NULL;\n}\n\nvoid initClass(ClassFile* cf, Frame* frame){\n    if (!cf->initalized){\n        method_info* method = getMethodByName(cf, \"<clinit>\",\"()V\");\n        //DEBUG_PRINT( (\"Method's Class Name: %.*s\\n\",name_utf8.length,name_utf8.bytes));\n        Code_attribute code;\n        if (method != NULL){ \n            code = getCode_AttributeFromAttribute_info(method->attributes[0]);\n            //method->attributes[0]\n            cf->initalized = 1;\n            Frame newFrame = createNewFrame(code, cf, frame->machine);\n            pushStack(&newFrame, frame->machine->JVMSTACK);\n            frame->pc++;\n        }else{\n            // todo method not found\n            DEBUG_PRINT((\"<clinit> method not found \\n\"));\n        }\n    }\n}\n\nvoid destroyClass(ClassFile* cf){\n    for (--cf->constant_pool_count; cf->constant_pool_count>0; cf->constant_pool_count--)\n        destroyCp_Info(&cf->constant_pool[cf->constant_pool_count-1]);\n\n    free(cf->constant_pool);\n\n    free(cf->interfaces);\n\n    for (; cf->fields_count>0; cf->fields_count--)\n        destroyField_Info(&cf->fields[cf->fields_count-1]);\n    free(cf->fields);\n\n    for (; cf->methods_count>0; cf->methods_count--)\n        destroyMethod_Info(&cf->methods[cf->methods_count-1]);\n    free(cf->methods);\n\n    for (; cf->attributes_count>0; cf->attributes_count--)\n        destroyAttribute_Info(&cf->attributes[cf->attributes_count-1]);\n    free(cf->attributes);\n}\n\nmethod_info* canClassHandleMethod(ClassFile* cf, CONSTANT_Utf8_info name_utf8, CONSTANT_Utf8_info descriptor_utf8){\n    DEBUG_PRINT( (\"Invoked Method Name: %.*s, %.*s\\n\",name_utf8.length,name_utf8.bytes, descriptor_utf8.length,descriptor_utf8.bytes));\n    for (int methodId=0; methodId < cf->methods_count; methodId++){\n        CONSTANT_Utf8_info classMethodName_utf8 = cf->constant_pool[cf->methods[methodId].name_index-1].info.utf8_info; // todo possibly optimize this func\n        CONSTANT_Utf8_info classMethodDesc_utf8 = cf->constant_pool[cf->methods[methodId].descriptor_index-1].info.utf8_info; // todo possibly optimize this func\n        if (isUtf8Equal(name_utf8, classMethodName_utf8) && isUtf8Equal(descriptor_utf8, classMethodDesc_utf8)){\n            DEBUG_PRINT( (\"Found Method Name: %.*s\\n\",classMethodName_utf8.length,classMethodName_utf8.bytes));\n            return &cf->methods[methodId];\n        }\n    }\n    return NULL; // method is not in this class\n}\n\nint checkFormat(ClassFile* cf){\n    //1\n    if (cf->magic != 0xCAFEBABE)\n        return 0;\n    \n    //2\n    for (int attributeCount=0; attributeCount<cf->attributes_count; attributeCount++){\n        uint16_t utf8Index = cf->attributes[attributeCount].attribute_name_index;\n        if (cf->constant_pool[utf8Index-1].tag != CONSTANT_Utf8){ // constant pool starts from 1 (lol, bcz oracle said)\n            //The constant_pool entry at attribute_name_index must be a CONSTANT_Utf8_info structure\n            return 0;\n        }\n    }\n    //4\n    for (int constantPoolCount=0; constantPoolCount < cf->constant_pool_count-1; constantPoolCount++){\n        switch (cf->constant_pool[constantPoolCount].tag){\n            case CONSTANT_Double:\n            case CONSTANT_Long:\n                // oracle's stupid ideas. see double_info in constantpool.c\n                constantPoolCount++;\n                break;\n            case CONSTANT_Class:; // empty statement ;\n                uint16_t utf8Index = cf->constant_pool[constantPoolCount].info.class_info.name_index;\n                if (cf->constant_pool[utf8Index-1].tag != CONSTANT_Utf8)\n                    return 0;\n                break;\n            case CONSTANT_Fieldref:;\n                // The class_index item of a CONSTANT_Fieldref_info structure may be either a class type or an interface type. \n                CONSTANT_Ref_info fieldref = cf->constant_pool[constantPoolCount].info.ref_info;\n                if (!(cf->constant_pool[fieldref.class_index-1].tag == CONSTANT_Class || cf->constant_pool[fieldref.class_index-1].tag == CONSTANT_InterfaceMethodref))\n                    return 0;\n                break;\n            case CONSTANT_InterfaceMethodref:;\n                CONSTANT_Ref_info interfaceMethodref = cf->constant_pool[constantPoolCount].info.ref_info;\n                if (cf->constant_pool[interfaceMethodref.class_index-1].tag != CONSTANT_InterfaceMethodref)\n                    return 0;\n                break;\n            case CONSTANT_Methodref:;\n                // The class_index item of a CONSTANT_Fieldref_info structure may be either a class type or an interface type. \n                CONSTANT_Ref_info methodref = cf->constant_pool[constantPoolCount].info.ref_info;\n                if (cf->constant_pool[methodref.class_index-1].tag != CONSTANT_Class)\n                    return 0;\n                break;\n            default:\n                break;\n        }\n    }\n    return 1;\n}"
  },
  {
    "path": "src/constantPool.c",
    "content": "#include \"constantPool.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include \"endianness.h\"\n/*\nConstant Pool Indexes written in the class file starts from 1; \nto access a constant, please get the (index - 1)th value.\n*/\ncp_info cp_infoFromFile(FILE* fd){\n    cp_info info;\n    fread(&info.tag,1,1,fd); // tag len is 1\n    switch (info.tag){\n        case CONSTANT_Class:\n            fread(&info.info.class_info.name_index,sizeof(info.info.class_info.name_index),1,fd);\n            info.info.class_info.name_index = be16toh(info.info.class_info.name_index); // big order to host\n            break;\n        case CONSTANT_Fieldref:\n        case CONSTANT_Methodref:\n        case CONSTANT_InterfaceMethodref:\n            fread(&info.info.ref_info.class_index,sizeof(info.info.ref_info.class_index),1,fd);\n            fread(&info.info.ref_info.name_and_type_index,sizeof(info.info.ref_info.name_and_type_index),1,fd);\n            info.info.ref_info.class_index = be16toh(info.info.ref_info.class_index);\n            info.info.ref_info.name_and_type_index = be16toh(info.info.ref_info.name_and_type_index);\n            break;\n        case CONSTANT_String:\n            fread(&info.info.string_info.string_index,sizeof(info.info.string_info.string_index),1,fd);\n            info.info.string_info.string_index = be16toh(info.info.string_info.string_index);\n            break;\n        case CONSTANT_Integer:\n        case CONSTANT_Float:\n            fread(&info.info._4BYTES_info.bytes,sizeof(info.info._4BYTES_info.bytes),1,fd);\n            info.info._4BYTES_info.bytes = be32toh(info.info._4BYTES_info.bytes);\n            break;\n        case CONSTANT_Long:\n        case CONSTANT_Double:\n            // 8 byte types takes two indexes in constant pool. So increase the counter by one extra.\n            fread(&info.info._8BYTES_info.bytes,sizeof(info.info._8BYTES_info.bytes),1,fd);\n            info.info._8BYTES_info.bytes = be64toh(info.info._8BYTES_info.bytes);\n            break;\n        case CONSTANT_NameAndType:\n            fread(&info.info.nameAndType_info.name_index,sizeof(info.info.nameAndType_info.name_index),1,fd);\n            fread(&info.info.nameAndType_info.descriptor_index,sizeof(info.info.nameAndType_info.descriptor_index),1,fd);\n            info.info.nameAndType_info.name_index = be16toh(info.info.nameAndType_info.name_index);\n            info.info.nameAndType_info.descriptor_index = be16toh(info.info.nameAndType_info.descriptor_index);\n            break;\n        case CONSTANT_Utf8:; // compiler wants a statement after label.\n            fread(&info.info.utf8_info.length,sizeof(info.info.utf8_info.length),1,fd); // len\n            info.info.utf8_info.length = be16toh(info.info.utf8_info.length);\n            info.info.utf8_info.bytes = malloc(info.info.utf8_info.length); //leak\n            fread(info.info.utf8_info.bytes,info.info.utf8_info.length,1,fd); // offsetting 2 bytes + reading utf8\n            //printf(\"len: %d, s: %.*s\\n\",info.info.utf8_info.length,info.info.utf8_info.length, info.info.utf8_info.bytes);\n            break;\n        case CONSTANT_MethodHandle:; // compiler wants a statement after label.\n            fread(&info.info.methodHandle_info.reference_kind,sizeof(info.info.methodHandle_info.reference_kind),1,fd); // reference kind\n            fread(&info.info.methodHandle_info.reference_index,sizeof(info.info.methodHandle_info.reference_index),1,fd); // ref index\n            info.info.methodHandle_info.reference_index = be16toh(info.info.methodHandle_info.reference_index);\n            break;\n        case CONSTANT_MethodType:\n            fread(&info.info.methodType_info.descriptor_index,sizeof(info.info.methodType_info.descriptor_index),1,fd);\n            info.info.methodType_info.descriptor_index = be16toh(info.info.methodType_info.descriptor_index);\n            break;\n        case CONSTANT_InvokeDynamic:\n            fread(&info.info.invodeDynamic_info.bootstrap_method_attr_index,sizeof(info.info.invodeDynamic_info.bootstrap_method_attr_index),1,fd);\n            fread(&info.info.invodeDynamic_info.name_and_type_index,sizeof(info.info.invodeDynamic_info.name_and_type_index),1,fd);\n            info.info.invodeDynamic_info.bootstrap_method_attr_index = be16toh(info.info.invodeDynamic_info.bootstrap_method_attr_index);\n            info.info.invodeDynamic_info.name_and_type_index = be16toh(info.info.invodeDynamic_info.name_and_type_index);\n            break;\n\n        default:\n            //tag err\n            break;\n    }\n    return info;\n\n}\n\nvoid destroyCp_Info(cp_info* info){\n    if (info->tag == CONSTANT_Utf8)\n        free(info->info.utf8_info.bytes);\n}"
  },
  {
    "path": "src/field.c",
    "content": "#include \"field.h\"\n#include <stdio.h>\n#include \"endianness.h\"\n#include <stdlib.h>\n#include \"classFile.h\"\n#include \"constantPool.h\"\n#include \"javaClass.h\"\n\nfield_info getField_Info(FILE* fd){\n    field_info field;\n    fread(&field.access_flags,sizeof(field.access_flags),1,fd);\n    field.access_flags = be16toh(field.access_flags);\n\n    fread(&field.name_index,sizeof(field.name_index),1,fd);\n    field.name_index = be16toh(field.name_index);\n\n    fread(&field.descriptor_index,sizeof(field.descriptor_index),1,fd);\n    field.descriptor_index = be16toh(field.descriptor_index);\n\n    fread(&field.attributes_count,sizeof(field.attributes_count),1,fd);\n    field.attributes_count = be16toh(field.attributes_count);\n\n    field.attributes = malloc (sizeof(attribute_info) * field.attributes_count);\n    for (int attributeCount=0; attributeCount<field.attributes_count; attributeCount++){\n        field.attributes[attributeCount] = getAttribute_Info(fd); // leak\n    }\n    field.value = 0;\n    return field;\n\n}\n\nvoid destroyField_Info(field_info* field){\n    for (; field->attributes_count > 0; field->attributes_count--)\n        destroyAttribute_Info(&field->attributes[field->attributes_count-1]);\n    free(field->attributes);\n}\n\nvoid putField(JavaClass* instance, CONSTANT_Utf8_info fieldName, CONSTANT_Utf8_info fieldDesc, uint64_t val){\n    field_info* field = getField(instance, fieldName, fieldDesc);\n    field->value = val;\n}\n\n\nfield_info* getField(JavaClass* jc, CONSTANT_Utf8_info fieldName, CONSTANT_Utf8_info fieldDesc){\n    for (uint16_t fieldId=0; fieldId<jc->classFile->fields_count; fieldId++){\n        field_info* field = &jc->fields[fieldId];\n        CONSTANT_Utf8_info _fieldName = jc->classFile->constant_pool[field->name_index-1].info.utf8_info;\n        CONSTANT_Utf8_info _fieldDesc = jc->classFile->constant_pool[field->descriptor_index-1].info.utf8_info;\n        if (isUtf8Equal(fieldName,_fieldName) && isUtf8Equal(fieldDesc,_fieldDesc)){\n            return field;\n        }\n    }\n    return NULL;\n}\n\nfield_info* getStaticField(ClassFile* cf, CONSTANT_Utf8_info fieldName, CONSTANT_Utf8_info fieldDesc){\n    for (uint16_t fieldId=0; fieldId<cf->fields_count; fieldId++){\n        field_info* field = &cf->fields[fieldId];\n        CONSTANT_Utf8_info _fieldName = cf->constant_pool[field->name_index-1].info.utf8_info;\n        CONSTANT_Utf8_info _fieldDesc = cf->constant_pool[field->descriptor_index-1].info.utf8_info;\n        if (isUtf8Equal(fieldName,_fieldName) && isUtf8Equal(fieldDesc,_fieldDesc)){\n            return field;\n        }\n    }\n    return NULL;\n}"
  },
  {
    "path": "src/frame.c",
    "content": "#include \"frame.h\"\n#include <stdlib.h>\n#include \"classFile.h\"\n#include \"attribute.h\"\n\nFrame createNewFrame (Code_attribute code, ClassFile* cf, Machine* machine){\n    Frame newFrame;\n    newFrame.code = malloc (sizeof(Code_attribute));\n    *newFrame.code = code;\n\n    newFrame.localVariables = malloc (sizeof(LocalVariable) * newFrame.code->max_locals);\n\n    newFrame.operandStack = malloc (sizeof(Stack));\n    *newFrame.operandStack = initStack(newFrame.code->max_stack, TYPE_OPERANDSTACK);\n\n    newFrame.pc = 0;\n    newFrame.classRef = cf;\n    newFrame.machine = machine;\n    return newFrame;\n}\n\nvoid destroyFrame (Frame* frame){\n    free(frame->localVariables);\n    free(frame->code);\n    destroyStack(frame->operandStack);\n    // dont free the frame struct itself. It contains an address into JVMStack.\n    // JVMStack is responsible for freeing or overwriting it.\n}"
  },
  {
    "path": "src/heap.c",
    "content": "#include \"heap.h\"\n\nHeap initHeap(size_t size){\n    Heap heap;\n    heap.heap = calloc(size,sizeof(HeapObject));\n    heap.size = size;\n    heap.top = 1; // 0 is for null object refs. \n    return heap;\n}\n\nvoid* hGet(uint64_t addr, Heap* heap){\n    return heap->heap[addr].addr;\n}\n\nuint64_t hAlloc(size_t size, Heap* heap){\n    for (size_t mem=0; mem<heap->top; mem++){\n        // this gets slower and sloooower as the number of object in heap increases.\n        if (!heap->heap[mem].isUsed){\n            heap->heap[mem].isUsed=1;\n            heap->heap[mem].size = size;\n            free(heap->heap[mem].addr);\n            heap->heap[mem].addr = malloc(heap->heap[mem].size);\n            return (mem);\n        }\n    }\n    if(heap->top + 1 > heap->size){\n        heap->heap = realloc(heap->heap,heap->size+=1024); // realloc 1024 more\n    }\n    heap->heap[heap->top].isUsed = 1;\n    heap->heap[heap->top].size = size;\n    heap->heap[heap->top].addr = malloc(size);\n    return (heap->top++);\n}\n\nuint64_t hExtend(uint64_t addr, size_t size, Heap* heap){\n    heap->heap[addr].size += size;\n    heap->heap[addr].addr = realloc(heap->heap[addr].addr,heap->heap[addr].size);\n    return addr;\n}\n\nvoid* hFree(uint64_t addr, Heap* heap){\n    heap->heap[addr].isUsed = 0;\n    return NULL;\n}\n\nvoid destroyHeap(Heap* heap){\n    for(;heap->top > 0; heap->top--)\n        free(heap->heap[heap->top -1].addr);\n    free(heap->heap);\n    free(heap);\n}"
  },
  {
    "path": "src/javaClass.c",
    "content": "#include \"javaClass.h\"\n#include <stdlib.h>\n#include \"heap.h\"\n#include <string.h>\n\nvoid initInstanceFields(JavaClass* instance){\n    instance->fields = malloc(instance->classFile->fields_count * sizeof(field_info));\n    memcpy(instance->fields, instance->classFile->fields, instance->classFile->fields_count * sizeof(field_info));\n}"
  },
  {
    "path": "src/machine.c",
    "content": "#include \"machine.h\"\n#include \"frame.h\"\n#include \"opcode.h\"\n#include \"stack.h\"\n#include \"debug.h\"\n#include \"classFile.h\"\n\nvoid* executeCode(Machine* JVM, OPCODE** opcodes){ // anything can be returned from an execution\n\n    Frame* frame;\n    void* retCode;\n    while (1){\n        frame = (Frame*)peekStack(JVM->JVMSTACK);\n        DEBUG_PRINT((\"---------------\\n\"));\n        DEBUG_PRINT((\"peeked stack is %p\\n\",frame));\n\n        #ifdef DEBUG\n        printf(\"---Code Dump---\\n\");\n        for (int qq=0; qq<frame->code->code_length; qq++)\n            printf(\"%d: 0x%1x\\n\", qq,frame->code->code[qq]);\n        printf(\"-----DUMP------\\n\");\n        #endif\n\n        for (; frame->pc < frame->code->code_length; frame->pc++){\n            retCode = NULL;\n            DEBUG_PRINT((\"pc: %d -> 0x%1x, opStackTop: %d\\n\",frame->pc , frame->code->code[frame->pc],frame->operandStack->top));\n            retCode = opcodes[frame->code->code[frame->pc]](frame);\n            if (retCode != NULL){\n                // the opcode returned something to push\n                // to the invoker operand stack\n                //DEBUG_PRINT((\"retcode is not null\\n\"));\n                break;\n            }\n            if (frame != (Frame*)peekStack(JVM->JVMSTACK)){\n                break; // frame changed, break!\n            }\n        }\n        if (retCode != NULL){\n            DEBUG_PRINT((\"returned something, in num: %d\\n\", *(uint64_t*) retCode));\n            destroyFrame((Frame*)popStack(JVM->JVMSTACK)); //destroy completely\n            Frame* frameInvoker = (Frame*)peekStack(JVM->JVMSTACK);\n            pushStack(retCode,frameInvoker->operandStack); // frame returned something to push\n            free(retCode); // iret mallocs it.\n            // into previous frames operand stack\n        }else if (frame->pc > frame->code->code_length){\n            DEBUG_PRINT((\"no code left to execute in this frame pc: %d, codelen: %d\\n\", frame->pc, frame->code->code_length));\n            destroyFrame((Frame*)popStack(JVM->JVMSTACK)); //destroy completely\n            // this frame finished without returning anything\n        }\n        if (peekStack(JVM->JVMSTACK) == NULL){\n            DEBUG_PRINT((\"no frame left to execute\\n\"));\n            free(opcodes);\n            return NULL;\n        }\n    }\n}\n\nvoid destroyMachine(Machine* machine){\n    for (;machine->numClasses>0; machine->numClasses--)\n        destroyClass(&machine->classFiles[machine->numClasses-1]);\n\n    free(machine->classFiles);\n    destroyStack(machine->JVMSTACK);\n    destroyHeap(machine->heap);\n}"
  },
  {
    "path": "src/main.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include \"machine.h\"\n#include \"classFile.h\"\n#include <assert.h>\n#include \"opcode.h\" // gecici\n#include \"stack.h\"\n#include \"attribute.h\"\n#include \"constantPool.h\"\n#include \"machine.h\"\n#include \"heap.h\"\n#include \"debug.h\"\n\nvoid main(int argc, char* argv[]){\n    Machine JVM;\n    JVM.numClasses = 0;\n    JVM.classFiles = malloc(sizeof(ClassFile) * 255);\n    ClassFile* mainClass = getClassFromName(argv[1], &JVM);\n\n    assert(checkFormat(mainClass)); // file format check\n    //DEBUG_PRINT((\"%x\\n\",mainClass->magic));\n    DEBUG_PRINT((\"Minor: %d, Major: %d\\n\", mainClass->minor_version,mainClass->major_version));\n    DEBUG_PRINT((\"constant_pool_count: %d\\n\",mainClass->constant_pool_count));\n    DEBUG_PRINT((\"access_flags: %d\\n\",mainClass->access_flags));\n    DEBUG_PRINT((\"this_class: %d\\n\",mainClass->this_class));\n    DEBUG_PRINT((\"super_class: %d\\n\",mainClass->super_class));\n    DEBUG_PRINT((\"interfaces_count: %d\\n\",mainClass->interfaces_count));\n    DEBUG_PRINT((\"fields_count: %d\\n\",mainClass->fields_count));\n    DEBUG_PRINT((\"methods_count: %d\\n\",mainClass->methods_count));\n    DEBUG_PRINT((\"attributes_count: %d\\n\",mainClass->attributes_count));\n\n    cp_info info = mainClass->constant_pool[mainClass->this_class-1];\n    CONSTANT_Class_info classInfo = info.info.class_info;\n\n    if (info.tag == CONSTANT_Class){\n        CONSTANT_Utf8_info utf8 = mainClass->constant_pool[classInfo.name_index-1].info.utf8_info;\n        DEBUG_PRINT( (\"This Class Name: %.*s\\n\",utf8.length,utf8.bytes));\n    }\n\n    JVM.heap = malloc(sizeof(Heap));\n    *JVM.heap = initHeap(512);\n\n    JVM.JVMSTACK = malloc(sizeof(Stack));\n    *JVM.JVMSTACK = initStack(255,TYPE_JVMSTACK);\n\n    Frame newFrame;\n\n    method_info* method = getMethodByName(mainClass, \"main\",\"([Ljava/lang/String;)V\");\n    Code_attribute* code = malloc(sizeof(Code_attribute));\n    if (method != NULL){\n        *code = getCode_AttributeFromAttribute_info(method->attributes[0]);\n        //method->attributes[0]\n    }else{\n        printf(\"main method not found \\n\");\n        return;\n    }\n\n    newFrame.code = code;\n    newFrame.localVariables = malloc (sizeof(LocalVariable) * code->max_locals);\n\n    //Stack* operandStack = ;\n    newFrame.operandStack = malloc(sizeof(Stack));\n    *newFrame.operandStack = initStack(code->max_stack, TYPE_OPERANDSTACK);\n\n    newFrame.pc = 0;\n    newFrame.classRef = mainClass;\n    newFrame.machine = &JVM;\n\n    pushStack(&newFrame, JVM.JVMSTACK);\n    void* retCode = executeCode(&JVM, initOpcodes());\n    if (retCode == NULL){\n        DEBUG_PRINT((\"Execution Stack Finished\\n\"));\n    }\n    destroyMachine(&JVM);\n}"
  },
  {
    "path": "src/opcode.c",
    "content": "#include \"opcode.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include \"stack.h\"\n#include \"endianness.h\"\n#include \"constantPool.h\"\n#include \"frame.h\"\n#include \"classFile.h\"\n#include <string.h>\n#include \"javaClass.h\"\n#include \"debug.h\"\n#include \"printStream.h\"\n#include \"stringBuilder.h\"\n#include <math.h>\n\nuint8_t read1Byte(Frame* frame){\n    return *(uint8_t*)&frame->code->code[++frame->pc]; // to get the first arg. of the opcode\n}\nuint16_t read2Bytes(Frame* frame){\n    /*\n    OP  A1  A2\n    00  01  02\n    ^\n    */\n    uint16_t val=be16toh(*(uint16_t*)&frame->code->code[frame->pc+1]);\n    frame->pc += 2;\n    return val;\n}\nuint32_t read4Bytes(Frame* frame){\n    uint32_t val=be32toh(*(uint32_t*)&frame->code->code[frame->pc+1]);\n    frame->pc += 4;\n    return val;\n}\nuint64_t read8Bytes(Frame* frame){\n    uint64_t val=be64toh(*(uint64_t*)&frame->code->code[frame->pc+1]);\n    frame->pc += 8;\n    return val;\n}\nvoid* OPCODE_ICONST_M1(Frame* frame){\n    uint64_t val = -1;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ICONST_0(Frame* frame){\n    uint64_t val = 0;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ICONST_1(Frame* frame){\n    uint64_t val = 1;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ICONST_2(Frame* frame){\n    uint64_t val = 2;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ICONST_3(Frame* frame){\n    uint64_t val = 3;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ICONST_4(Frame* frame){\n    uint64_t val = 4;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ICONST_5(Frame* frame){\n    uint64_t val = 5;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DCONST_0(Frame* frame){\n    double val = 0.0;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DCONST_1(Frame* frame){\n    double val = 1.0;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DCONST_2(Frame* frame){\n    double val = 2.0;\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_BIPUSH(Frame* frame){\n    uint64_t val = read1Byte(frame);\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_SIPUSH(Frame* frame){\n    uint64_t val = read2Bytes(frame);\n    pushStack(&val,frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_LDC(Frame* frame){\n    uint8_t index = read1Byte(frame);\n    cp_info* aConstant = &frame->classRef->constant_pool[index-1];\n    if (aConstant->tag == CONSTANT_Integer || aConstant->tag == CONSTANT_Float){\n        uint64_t val;\n        val = aConstant->info._4BYTES_info.bytes;\n        pushStack(&val, frame->operandStack);\n    }else{\n        pushStack(&aConstant, frame->operandStack);\n        /*\n        Otherwise, if the run-time constant pool entry is a reference to an instance of class \n        String representing a string literal (§5.1), then a reference to that instance, value,\n        is pushed onto the operand stack.\n        \n        Otherwise, if the run-time constant pool entry is a symbolic reference to a class (§5.1),\n        then the named class is resolved (§5.4.3.1) and a reference to the Class object \n        representing that class, value, is pushed onto the operand stack.\n\n        Otherwise, the run-time constant pool entry must be a symbolic reference to a method type\n        or a method handle (§5.1). The method type or method handle is resolved (§5.4.3.5) and a\n        reference to the resulting instance of java.lang.invoke.MethodType or \n        java.lang.invoke.MethodHandle, value, is pushed onto the operand stack. \n        */\n    }\n    return NULL;\n}\nvoid* OPCODE_LDC_W(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n    cp_info* aConstant = &frame->classRef->constant_pool[index-1];\n    if (aConstant->tag == CONSTANT_Integer || aConstant->tag == CONSTANT_Float){\n        uint64_t val;\n        val = aConstant->info._4BYTES_info.bytes;\n        pushStack(&val, frame->operandStack);\n    }else if(aConstant->tag == CONSTANT_Long || aConstant->tag == CONSTANT_Double){\n        uint64_t val;\n        val = aConstant->info._8BYTES_info.bytes;\n        pushStack(&val, frame->operandStack);\n    }else{\n        pushStack(&aConstant, frame->operandStack);\n    }\n\treturn NULL;\n}\nvoid* OPCODE_NLOAD(Frame* frame){ // N represents I,L or D\n    uint8_t index = read1Byte(frame);\n    pushStack(&frame->localVariables[index], frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_NLOAD_0(Frame* frame){\n    pushStack(&frame->localVariables[0], frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_NLOAD_1(Frame* frame){\n    pushStack(&frame->localVariables[1], frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_NLOAD_2(Frame* frame){\n    pushStack(&frame->localVariables[2], frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_NLOAD_3(Frame* frame){\n    pushStack(&frame->localVariables[3], frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_NSTORE(Frame* frame){\n    uint8_t index = read1Byte(frame);\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    frame->localVariables[index] = val;\n\treturn NULL;\n}\nvoid* OPCODE_NSTORE_0(Frame* frame){\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    frame->localVariables[0] = val;\n\treturn NULL;\n}\nvoid* OPCODE_NSTORE_1(Frame* frame){\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    frame->localVariables[1] = val;\n\treturn NULL;\n}\nvoid* OPCODE_NSTORE_2(Frame* frame){\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    frame->localVariables[2] = val;\n\treturn NULL;\n}\nvoid* OPCODE_NSTORE_3(Frame* frame){\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    frame->localVariables[3] = val;\n\treturn NULL;\n}\nvoid* OPCODE_POP(Frame* frame){\n    //popStack(frame->operandStack);\n    int64_t discardedRetVal = *(int64_t*) popStack(frame->operandStack);\n    DEBUG_PRINT((\"Discarded Return Value is %d\\n\",discardedRetVal));\n\treturn NULL;\n}\nvoid* OPCODE_DUP(Frame* frame){\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DUP_X1(Frame* frame){\n    uint64_t val1 = *(uint64_t*)popStack(frame->operandStack);\n    uint64_t val2 = *(uint64_t*)popStack(frame->operandStack);\n    pushStack(&val1, frame->operandStack);\n    pushStack(&val2, frame->operandStack);\n    pushStack(&val1, frame->operandStack);\n\treturn NULL;\n}\n\n/////////////\n// INTEGER //\n/////////////\nvoid* OPCODE_IADD(Frame* frame){\n    int64_t val = (int32_t)*(int64_t*)popStack(frame->operandStack) + (int32_t)*(int64_t*)popStack(frame->operandStack); // java has no unsigned types, lol\n    // the stacks are 64 bit but the int size is 32 bit\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_ISUB(Frame* frame){\n    int32_t val2 = *(int64_t*) popStack(frame->operandStack);\n    int32_t val1 = *(int64_t*) popStack(frame->operandStack);\n    int64_t val = val1 - val2;\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_IMUL(Frame* frame){\n    int64_t val = (int32_t)*(int64_t*)popStack(frame->operandStack) * (int32_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_IDIV(Frame* frame){\n    int32_t val2 = *(int64_t*) popStack(frame->operandStack);\n    int32_t val1 = *(int64_t*) popStack(frame->operandStack);\n    int64_t val = val1 / val2;\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n/////////////\n///  LONG ///\n/////////////\nvoid* OPCODE_LADD(Frame* frame){\n    int64_t val = *(int64_t*)popStack(frame->operandStack) + *(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_LSUB(Frame* frame){\n    int64_t val2 = *(int64_t*) popStack(frame->operandStack);\n    int64_t val1 = *(int64_t*) popStack(frame->operandStack);\n    int64_t val = val1-val2;\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_LMUL(Frame* frame){\n    int64_t val = *(int64_t*)popStack(frame->operandStack) * *(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_LDIV(Frame* frame){\n    int64_t val2 = *(int64_t*) popStack(frame->operandStack);\n    int64_t val1 = *(int64_t*) popStack(frame->operandStack);\n    int64_t val = val1 / val2;\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n/////////////\n/// DOUBLE //\n/////////////\nvoid* OPCODE_DADD(Frame* frame){\n    double val = *(double*)popStack(frame->operandStack) + *(double*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DSUB(Frame* frame){\n    double val2 = *(double*) popStack(frame->operandStack);\n    double val1 = *(double*) popStack(frame->operandStack);\n    double val = val1-val2;\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DMUL(Frame* frame){\n    double val = *(double*)popStack(frame->operandStack) * *(double*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DDIV(Frame* frame){\n    double val2 = *(double*) popStack(frame->operandStack);\n    double val1 = *(double*) popStack(frame->operandStack);\n    double val = val1 / val2;\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_D2F(Frame* frame){\n    float val = (float)*(double*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_D2I(Frame* frame){\n    int64_t val = (int32_t)*(double*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_D2L(Frame* frame){\n    int64_t val = (int64_t)*(double*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DNEG(Frame* frame){\n    double val = -*(double*) popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\nvoid* OPCODE_DREM(Frame* frame){\n    double val2 = *(double*) popStack(frame->operandStack);\n    double val1 = *(double*) popStack(frame->operandStack);\n    double val = fmod(val1,val2);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\n///////////////\n\nvoid* OPCODE_I2D(Frame* frame){\n    double val = (double)(int32_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_I2F(Frame* frame){\n    float val = (float)(int32_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_I2B(Frame* frame){\n    int64_t val = (int8_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_I2C(Frame* frame){\n    //char, whose values are 16-bit unsigned integers representing Unicode code points ...\n    uint64_t val = (uint16_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_I2L(Frame* frame){\n    uint64_t val = (int32_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_I2S(Frame* frame){\n    uint64_t val = (int16_t)*(int64_t*)popStack(frame->operandStack);\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\n///////////////\n\nvoid* OPCODE_LCMP(Frame* frame){\n    uint64_t val2 = *(uint64_t*) popStack(frame->operandStack);\n    uint64_t val1 = *(uint64_t*) popStack(frame->operandStack);\n    int64_t val = 0;\n    if (val1 > val2){\n        val = 1;\n    }else if (val1 == val2){\n        val = 0;\n    }else {\n        val = -1;\n    }\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_IFEQ(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 == 0){\n        frame->pc += offset - 3;\n    }\n    return NULL;\n}\nvoid* OPCODE_IFNE(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 != 0){\n        frame->pc += offset - 3;\n    }\n    return NULL;\n}\nvoid* OPCODE_IFLT(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 < 0){\n        frame->pc += offset - 3;\n    }\n    return NULL;\n}\nvoid* OPCODE_IFLE(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 <= 0){\n        frame->pc += offset - 3;\n    }\n    return NULL;\n}\nvoid* OPCODE_IFGT(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 > 0){\n        frame->pc += offset - 3;\n    }\n    return NULL;\n}\nvoid* OPCODE_IFGE(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 >= 0){\n        frame->pc += offset - 3;\n    }\n    return NULL;\n}\n\nvoid* OPCODE_DCMPG(Frame* frame){\n    double val2 = *(double*) popStack(frame->operandStack);\n    double val1 = *(double*) popStack(frame->operandStack);\n    int64_t val = 0;\n    if (val1 > val2){\n        val = 1;\n    }else if (val1 == val2){\n        val = 0;\n    }else {\n        val = -1;\n    }\n    pushStack(&val, frame->operandStack);\n\treturn NULL;\n}\n\nvoid* OPCODE_IF_ICMPGE(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val2 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 >= val2){\n        frame->pc += offset - 3;\n        // -1 because the main loop will increase 1 after this opcode to\n        // get the next opcode. Extra -2 because we moved 2 more bytes while\n        // reading the offset\n    }\n\treturn NULL;\n}\n\nvoid* OPCODE_IF_ICMPGT(Frame* frame){\n    uint16_t offset = read2Bytes(frame);\n    int64_t val2 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    int64_t val1 = (int32_t)*(int64_t*) popStack(frame->operandStack);\n    if (val1 > val2){\n        frame->pc += offset - 3;\n        // -1 because the main loop will increase 1 after this opcode to\n        // get the next opcode. Extra -2 because we moved 2 more bytes while\n        // reading the offset\n    }\n\treturn NULL;\n}\n\nvoid* OPCODE_IINC(Frame* frame){\n    uint8_t index = read1Byte(frame);\n    uint8_t incrementAmount = read1Byte(frame);\n    *(int64_t*)&frame->localVariables[index] = (int32_t)(*(int64_t*)&frame->localVariables[index] + *(int8_t*)&incrementAmount);\n    return NULL;\n}\n\nvoid* OPCODE_GOTO(Frame* frame){\n    uint16_t offset = read2Bytes(frame); // branch offset\n    frame->pc += *(int16_t*)&offset - 3;\n    // -1 because the main loop will increase 1 after this opcode to\n    // get the next opcode Extra -2 because we moved 2 more bytes while\n    // reading the offset\n    return NULL;\n}\n\nvoid* OPCODE_GETSTATIC(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n    CONSTANT_Ref_info fieldRefInfo = frame->classRef->constant_pool[index-1].info.ref_info;\n\n    CONSTANT_NameAndType_info nameAndType = frame->classRef->constant_pool[fieldRefInfo.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info name_utf8 = frame->classRef->constant_pool[nameAndType.name_index-1].info.utf8_info;\n    CONSTANT_Utf8_info desc_utf8 = frame->classRef->constant_pool[nameAndType.descriptor_index-1].info.utf8_info;\n\n    CONSTANT_Class_info class = frame->classRef->constant_pool[fieldRefInfo.class_index -1].info.class_info;\n    CONSTANT_Utf8_info className_utf8 = frame->classRef->constant_pool[class.name_index-1].info.utf8_info;\n    \n    ClassFile* cf = getClassFromUtf8(className_utf8,frame->machine);\n    if (cf != NULL){\n        initClass(cf, frame);\n        field_info* field = getStaticField(cf, name_utf8, desc_utf8);\n        pushStack(&field->value, frame->operandStack);\n    }else{\n        uint64_t val = 0;\n        pushStack(&val, frame->operandStack);\n    }\n    return NULL;\n}\n\nvoid* OPCODE_NEW(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n    CONSTANT_Class_info class = frame->classRef->constant_pool[index-1].info.class_info; // class or interface ref info\n\n    CONSTANT_Utf8_info className_utf8 = frame->classRef->constant_pool[class.name_index-1].info.utf8_info;\n    ClassFile* cf = getClassFromUtf8(className_utf8,frame->machine);\n    uint64_t objectRef;\n    if (cf != NULL){\n        objectRef = hAlloc(sizeof(JavaClass),frame->machine->heap);\n        JavaClass* newObject = hGet(objectRef,frame->machine->heap);\n        newObject->classFile = cf;\n        initClass(cf, frame);\n        initInstanceFields(newObject);\n        pushStack(&objectRef, frame->operandStack);\n    }else{\n        uint64_t objectRef = (uint64_t)NULL;\n        if (isUtf8EqualsToString(className_utf8,\"java/lang/StringBuilder\")){\n            objectRef = hAlloc(sizeof(cp_info), frame->machine->heap);\n            cp_info* str = hGet(objectRef, frame->machine->heap);\n            str->tag = CONSTANT_Utf8;\n            uint64_t bytesRef = hAlloc(1,frame->machine->heap);\n            str->info.utf8_info.bytes=(char*)bytesRef;\n            char* bytes = hGet(bytesRef, frame->machine->heap);\n            bytes[0]='\\0';\n            str->info.utf8_info.length=1;\n        }\n        pushStack(&objectRef, frame->operandStack);\n    }\n    \n    return NULL;\n}\n\nvoid* OPCODE_PUTFIELD(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n    CONSTANT_Ref_info fieldRefInfo = frame->classRef->constant_pool[index-1].info.ref_info;\n\n    CONSTANT_NameAndType_info nameAndType = frame->classRef->constant_pool[fieldRefInfo.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info name_utf8 = frame->classRef->constant_pool[nameAndType.name_index-1].info.utf8_info;\n    CONSTANT_Utf8_info desc_utf8 = frame->classRef->constant_pool[nameAndType.descriptor_index-1].info.utf8_info;\n\n    uint64_t val = *(uint64_t*)popStack(frame->operandStack);\n    JavaClass* obj = (JavaClass*)hGet(*(uint64_t*)popStack(frame->operandStack),frame->machine->heap);\n\n    DEBUG_PRINT((\"%x, put val is %d, objRef is %p \\n\", obj->classFile->magic, val, obj));\n    putField(obj, name_utf8, desc_utf8, val);\n\n    return NULL;\n}\n\nvoid* OPCODE_NRETURN(Frame* frame){\n    uint64_t* val = malloc(sizeof(val)); // freed later\n    *val = *(uint64_t*)popStack(frame->operandStack);\n    DEBUG_PRINT((\"iret val : %d, stackTop: %d\\n\", *val, frame->operandStack->top));\n    return val;\n}\nvoid* OPCODE_RETURN(Frame* frame){\n    frame->pc = frame->code->code_length;\n    // current frame is discarded\n    return NULL;\n}\n\nvoid* OPCODE_GETFIELD(Frame* frame){\n    \n    JavaClass* obj = (JavaClass*)hGet(*(uint64_t*)popStack(frame->operandStack),frame->machine->heap);\n    uint16_t index = read2Bytes(frame);\n    CONSTANT_Ref_info fieldRef = frame->classRef->constant_pool[index-1].info.ref_info;\n\n    CONSTANT_NameAndType_info* nameAndType = &frame->classRef->constant_pool[fieldRef.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info name_utf8 = frame->classRef->constant_pool[nameAndType->name_index-1].info.utf8_info;\n    CONSTANT_Utf8_info desc_utf8 = frame->classRef->constant_pool[nameAndType->descriptor_index-1].info.utf8_info;\n\n    // different type fields can have the same name in bytecode but not in java.\n    field_info* field = getField(obj,name_utf8, desc_utf8);\n    pushStack(&field->value, frame->operandStack);\n    return NULL;\n}\n\nvoid* OPCODE_INVOKEVIRTUAL(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n    if (!(frame->classRef->constant_pool[index-1].tag == CONSTANT_Methodref || frame->classRef->constant_pool[index-1].tag == CONSTANT_InterfaceMethodref)){\n        printf(\"invoked method ref is invalid, index is %d\\n\",index);\n    }\n    CONSTANT_Ref_info methodOrInterfaceRef = frame->classRef->constant_pool[index-1].info.ref_info;\n    \n    CONSTANT_NameAndType_info* nameAndType = &frame->classRef->constant_pool[methodOrInterfaceRef.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info name_utf8 = frame->classRef->constant_pool[nameAndType->name_index-1].info.utf8_info;\n    CONSTANT_Utf8_info desc_utf8 = frame->classRef->constant_pool[nameAndType->descriptor_index-1].info.utf8_info;\n    DEBUG_PRINT( (\"Method's Name: %.*s\\n\",name_utf8.length,name_utf8.bytes));\n\n    CONSTANT_Class_info methodClass = frame->classRef->constant_pool[methodOrInterfaceRef.class_index - 1].info.class_info;\n    CONSTANT_Utf8_info className_utf8 = frame->classRef->constant_pool[methodClass.name_index-1].info.utf8_info;\n    DEBUG_PRINT( (\"Class's Name: %.*s\\n\",className_utf8.length,className_utf8.bytes));\n    ClassFile* cf = getClassFromUtf8(className_utf8, frame->machine);\n\n\n    method_info* method = NULL;\n\n    int numArgs = getNumArgs(frame->classRef, methodOrInterfaceRef) + 1; // +1 for ObjectRef which will be at localVars[0]\n\n    uint64_t tempLocalVars[numArgs];\n    for (int argId = numArgs-1; argId >= 0; argId--){\n        tempLocalVars[argId] = *(uint64_t*) popStack(frame->operandStack);\n    }\n \n\n    // hack to run Println\n    if (isUtf8EqualsToString(className_utf8,\"java/io/PrintStream\") && isUtf8EqualsToString(name_utf8,\"println\")){\n        handlePrintStream(tempLocalVars, frame, name_utf8, desc_utf8);\n        return NULL;\n    }\n    if (isUtf8EqualsToString(className_utf8,\"java/lang/StringBuilder\")){\n        handleStringBuilder(tempLocalVars,frame, name_utf8, desc_utf8);\n        return NULL;\n    }\n\n    ////  Let C be the class of objectref. The actual method to be invoked\n    //// is selected by the following lookup procedure:\n    \n    // If C contains a declaration for an instance method m that overrides (§5.4.5)\n    // the resolved method, then m is the method to be invoked.\n    JavaClass* obj = (JavaClass*)hGet(tempLocalVars[0],frame->machine->heap);\n    method_info* mPointer = canClassHandleMethod(obj->classFile, name_utf8, desc_utf8);\n\n    if (mPointer){\n        method = (mPointer)?(mPointer):method;\n        DEBUG_PRINT((\"first overrider runned\\n\"));\n    }else{\n\n        // Otherwise, if C has a superclass, a search for a declaration of an instance\n        // method that overrides the resolved method is performed, starting with the\n        // direct superclass of C and continuing with the direct superclass of that\n        // class, and so forth, until an overriding method is found or no further\n        // superclasses exist. If an overriding method is found, it is the method to be invoked. \n        ClassFile* superClass = obj->classFile;\n        mPointer = NULL;\n        while (superClass->super_class != 0){\n            CONSTANT_Class_info superClassInfo = superClass -> constant_pool [superClass->super_class-1].info.class_info;\n            CONSTANT_Utf8_info superClassName = superClass -> constant_pool [superClassInfo.name_index-1].info.utf8_info;\n            superClass = getClassFromUtf8 (superClassName, frame->machine);\n            mPointer = canClassHandleMethod(superClass, name_utf8, desc_utf8);\n            if (mPointer){\n                method = (mPointer)?(mPointer):method;\n                DEBUG_PRINT((\"found in superclass runned\\n\"));\n                break;\n            }\n        }\n        if (mPointer == NULL){\n            DEBUG_PRINT((\"fallBack runned\\n\"));\n            mPointer = canClassHandleMethod(cf, name_utf8, desc_utf8);\n            method = (mPointer)?(mPointer):method;\n        }\n    }\n\n    if (method->access_flags != M_ACC_NATIVE){\n        // todo: error? \n    }\n\n    Code_attribute code;\n    if (method != NULL){\n        code = getCode_AttributeFromAttribute_info(method->attributes[0]);\n    }else{\n        printf(\"method not found \\n\");\n    }\n    Frame newFrame = createNewFrame(code, cf, frame->machine);\n\n    memcpy(newFrame.localVariables, tempLocalVars, numArgs * sizeof(tempLocalVars[0]));\n\n    pushStack(&newFrame, frame->machine->JVMSTACK);\n\n    frame->pc++;\n    return NULL;\n}\n\nvoid* OPCODE_INVOKESPECIAL(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n    if (!(frame->classRef->constant_pool[index-1].tag == CONSTANT_Methodref || frame->classRef->constant_pool[index-1].tag == CONSTANT_InterfaceMethodref)){\n        printf(\"invoked method ref is invalid, index is %d\\n\",index);\n    }\n    CONSTANT_Ref_info methodOrInterfaceRef = frame->classRef->constant_pool[index-1].info.ref_info;\n    \n    CONSTANT_NameAndType_info* nameAndType = &frame->classRef->constant_pool[methodOrInterfaceRef.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info name_utf8 = frame->classRef->constant_pool[nameAndType->name_index-1].info.utf8_info;\n    CONSTANT_Utf8_info desc_utf8 = frame->classRef->constant_pool[nameAndType->descriptor_index-1].info.utf8_info;\n    DEBUG_PRINT( (\"Method's Name: %.*s\\n\",name_utf8.length,name_utf8.bytes));\n\n    CONSTANT_Class_info methodClass = frame->classRef->constant_pool[methodOrInterfaceRef.class_index - 1].info.class_info;\n    CONSTANT_Utf8_info className_utf8 = frame->classRef->constant_pool[methodClass.name_index-1].info.utf8_info;\n    DEBUG_PRINT( (\"Class's Name: %.*s\\n\",className_utf8.length,className_utf8.bytes));\n    ClassFile* cf = getClassFromUtf8(className_utf8, frame->machine);\n    int numArgs = getNumArgs(frame->classRef, methodOrInterfaceRef) + 1; // +1 for ObjectRef which will be at localVars[0]\n\n    if (cf == NULL){\n        // clear stack for special methods of native classes.\n        for (int i=0; i<numArgs; i++)\n            popStack(frame->operandStack); // pop numArgs times\n        return NULL;\n    }\n\n    method_info* method = canClassHandleMethod(cf, name_utf8, desc_utf8);\n    Code_attribute code;\n    if (method != NULL){\n        code = getCode_AttributeFromAttribute_info(method->attributes[0]);\n    }else{\n        printf(\"method not found \\n\");\n    }\n    Frame newFrame = createNewFrame(code, cf, frame->machine);\n\n    if (method->access_flags != M_ACC_NATIVE){\n        for (int argId = numArgs-1; argId >= 0; argId--){\n            newFrame.localVariables[argId] = *(uint64_t*) popStack(frame->operandStack);\n        }\n\n    }\n\n    pushStack(&newFrame, frame->machine->JVMSTACK);\n\n    frame->pc++;\n    return NULL;\n}\n\nvoid* OPCODE_INVOKESTATIC(Frame* frame){\n    uint16_t index = read2Bytes(frame);\n\n    if (!(frame->classRef->constant_pool[index-1].tag == CONSTANT_Methodref || frame->classRef->constant_pool[index-1].tag == CONSTANT_InterfaceMethodref)){\n        // index must be a symbolic reference to a method or an interface method\n        // if the resolved method is an instance method, the invokestatic instruction throws an IncompatibleClassChangeError. \n        printf(\"invoked method ref is invalid, index is %d\\n\",index);\n    }\n    CONSTANT_Ref_info methodOrInterfaceRef = frame->classRef->constant_pool[index-1].info.ref_info;\n    //DEBUG_PRINT( (\"Method's Class Name: %.*s\\n\",name_utf8.length,name_utf8.bytes));\n\n    CONSTANT_Class_info methodClass = frame->classRef->constant_pool[methodOrInterfaceRef.class_index - 1].info.class_info;\n    CONSTANT_Utf8_info className_utf8 = frame->classRef->constant_pool[methodClass.name_index-1].info.utf8_info;\n    DEBUG_PRINT( (\"Class's Name: %.*s\\n\",className_utf8.length,className_utf8.bytes));\n    ClassFile* cf = getClassFromUtf8(className_utf8, frame->machine);\n\n    CONSTANT_NameAndType_info* nameAndType = &frame->classRef->constant_pool[methodOrInterfaceRef.name_and_type_index-1].info.nameAndType_info;\n    CONSTANT_Utf8_info name_utf8 = frame->classRef->constant_pool[nameAndType->name_index-1].info.utf8_info;\n    CONSTANT_Utf8_info desc_utf8 = frame->classRef->constant_pool[nameAndType->descriptor_index-1].info.utf8_info;\n\n    method_info* method = canClassHandleMethod(cf, name_utf8, desc_utf8);\n    Code_attribute code;\n    if (method != NULL){\n        code = getCode_AttributeFromAttribute_info(method->attributes[0]);\n        //method->attributes[0]\n    }else{\n        // todo method not found\n        printf(\"method not found \\n\");\n    }\n    Frame newFrame = createNewFrame(code, cf, frame->machine);\n\n\n    if (method->access_flags != M_ACC_NATIVE){\n        // On successful resolution of the method, the class or interface that declared the resolved method is initialized (§5.5) if that class or interface has not already been initialized. \n        int numArgs = getNumArgs(frame->classRef, methodOrInterfaceRef);\n        for (int argId = numArgs-1; argId >= 0; argId--){\n            newFrame.localVariables[argId] = *(uint64_t*) popStack(frame->operandStack);\n        }\n\n    }\n\n    pushStack(&newFrame, frame->machine->JVMSTACK);\n\n    frame->pc++;\n    return NULL;\n}\nOPCODE** initOpcodes(){\n    // jumptable\n    OPCODE** opcodes = malloc (sizeof(OPCODE*) * 255); // leak, consider static\n\n    opcodes[0x1] = OPCODE_ICONST_0; // null\n    opcodes[0x2] = OPCODE_ICONST_M1;\n    opcodes[0x3] = OPCODE_ICONST_0;\n    opcodes[0x4] = OPCODE_ICONST_1;\n    opcodes[0x5] = OPCODE_ICONST_2;\n    opcodes[0x6] = OPCODE_ICONST_3;\n    opcodes[0x7] = OPCODE_ICONST_4;\n    opcodes[0x8] = OPCODE_ICONST_5;\n    opcodes[0x9] = OPCODE_ICONST_0;\n    opcodes[0xa] = OPCODE_ICONST_1;\n\n    opcodes[0xb] = OPCODE_DCONST_0;\n    opcodes[0xc] = OPCODE_DCONST_1;\n    opcodes[0xd] = OPCODE_DCONST_2;\n    opcodes[0xe] = OPCODE_DCONST_0; // double\n    opcodes[0xf] = OPCODE_DCONST_1;\n\n    opcodes[0x10] = OPCODE_BIPUSH;\n    opcodes[0x11] = OPCODE_SIPUSH;\n    \n    opcodes[0x12] = OPCODE_LDC;\n    opcodes[0x13] = OPCODE_LDC_W;\n    opcodes[0x14] = OPCODE_LDC_W; // same but for 8 bytes. \n\n    opcodes[0x15] = OPCODE_NLOAD; //iload\n    opcodes[0x16] = OPCODE_NLOAD; //lload\n    opcodes[0x18] = OPCODE_NLOAD; //dload\n    opcodes[0x19] = OPCODE_NLOAD; //aload\n    \n    // iload\n    opcodes[0x1a] = OPCODE_NLOAD_0;\n    opcodes[0x1b] = OPCODE_NLOAD_1;\n    opcodes[0x1c] = OPCODE_NLOAD_2;\n    opcodes[0x1d] = OPCODE_NLOAD_3;\n    // lload\n    opcodes[0x1e] = OPCODE_NLOAD_0;\n    opcodes[0x1f] = OPCODE_NLOAD_1;\n    opcodes[0x20] = OPCODE_NLOAD_2;\n    opcodes[0x21] = OPCODE_NLOAD_3;\n    // dload\n    opcodes[0x26] = OPCODE_NLOAD_0;\n    opcodes[0x27] = OPCODE_NLOAD_1;\n    opcodes[0x28] = OPCODE_NLOAD_2;\n    opcodes[0x29] = OPCODE_NLOAD_3;\n    // aload\n    opcodes[0x2a] = OPCODE_NLOAD_0;\n    opcodes[0x2b] = OPCODE_NLOAD_1;\n    opcodes[0x2c] = OPCODE_NLOAD_2;\n    opcodes[0x2d] = OPCODE_NLOAD_3;\n\n\n    opcodes[0x36] = OPCODE_NSTORE; // istore\n    opcodes[0x37] = OPCODE_NSTORE; // lstore\n\n    opcodes[0x3a] = OPCODE_NSTORE; // astore\n\n    // istore\n    opcodes[0x3b] = OPCODE_NSTORE_0;\n    opcodes[0x3c] = OPCODE_NSTORE_1;\n    opcodes[0x3d] = OPCODE_NSTORE_2;\n    opcodes[0x3e] = OPCODE_NSTORE_3;\n\n    // lstore\n    opcodes[0x3f] = OPCODE_NSTORE_0;\n\n    opcodes[0x39] = OPCODE_NSTORE; // dstore\n\n    opcodes[0x40] = OPCODE_NSTORE_1;\n    opcodes[0x41] = OPCODE_NSTORE_2;\n    opcodes[0x42] = OPCODE_NSTORE_3;\n\n    // dstore\n    opcodes[0x47] = OPCODE_NSTORE_0;\n    opcodes[0x48] = OPCODE_NSTORE_1;\n    opcodes[0x49] = OPCODE_NSTORE_2;\n    opcodes[0x4a] = OPCODE_NSTORE_3;\n\n    // astore\n    opcodes[0x4b] = OPCODE_NSTORE_0;\n    opcodes[0x4c] = OPCODE_NSTORE_1;\n    opcodes[0x4d] = OPCODE_NSTORE_2;\n    opcodes[0x4e] = OPCODE_NSTORE_3;\n\n    opcodes[0x57] = OPCODE_POP;\n    opcodes[0x59] = OPCODE_DUP;\n    \n    opcodes[0x61] = OPCODE_LADD;\n\n    opcodes[0x67] = OPCODE_DSUB;\n\n    opcodes[0x68] = OPCODE_IMUL;\n\n    opcodes[0x6b] = OPCODE_DMUL;\n    opcodes[0x6d] = OPCODE_LDIV;\n    opcodes[0x6f] = OPCODE_DDIV;\n\n    opcodes[0x73] = OPCODE_DREM;\n    opcodes[0x77] = OPCODE_DNEG;\n\n    opcodes[0x84] = OPCODE_IINC;\n    opcodes[0x85] = OPCODE_I2L;\n\n    opcodes[0x8e] = OPCODE_D2I;\n    opcodes[0x8f] = OPCODE_D2L;\n\n    opcodes[0x90] = OPCODE_D2F;\n\n    opcodes[0x94] = OPCODE_LCMP;\n\n    opcodes[0x97] = OPCODE_DCMPG; //dcmpl\n    opcodes[0x98] = OPCODE_DCMPG; //dcmpg\n\n    opcodes[0x99] = OPCODE_IFEQ;\n    opcodes[0x9a] = OPCODE_IFNE;\n    opcodes[0x9b] = OPCODE_IFLT;\n    opcodes[0x9c] = OPCODE_IFGE;\n    opcodes[0x9d] = OPCODE_IFGT;\n    opcodes[0x9e] = OPCODE_IFLE;\n\n\n    opcodes[0xa2] = OPCODE_IF_ICMPGE;\n    opcodes[0xa3] = OPCODE_IF_ICMPGT;\n    opcodes[0xa7] = OPCODE_GOTO;\n        \n    opcodes[0xaf] = OPCODE_NRETURN; // d\n\n    opcodes[0xb0] = OPCODE_NRETURN;\n    opcodes[0xb1] = OPCODE_RETURN;\n    opcodes[0xb2] = OPCODE_GETSTATIC;\n    opcodes[0xb4] = OPCODE_GETFIELD;\n    opcodes[0xb5] = OPCODE_PUTFIELD;\n    opcodes[0xb6] = OPCODE_INVOKEVIRTUAL;\n    opcodes[0xb7] = OPCODE_INVOKESPECIAL;\n    opcodes[0xb8] = OPCODE_INVOKESTATIC;\n\n    opcodes[0xbb] = OPCODE_NEW;\n    \n    opcodes[0x60] = OPCODE_IADD;\n    opcodes[0xac] = OPCODE_NRETURN;\n    return opcodes;\n}"
  },
  {
    "path": "src/printStream.c",
    "content": "#include \"printStream.h\"\n#include <inttypes.h>\n#include \"constantPool.h\"\n#include \"frame.h\"\n#include <stdlib.h>\n\n\nvoid handlePrintStream(uint64_t* localVariables, Frame* frame, CONSTANT_Utf8_info name_utf8, CONSTANT_Utf8_info desc_utf8){\n    if (isUtf8EqualsToString(desc_utf8,\"(I)V\")){\n        printf(\"%d\\n\",localVariables[1]);\n        return;\n    }\n    cp_info* printArg = (cp_info*)localVariables[1]; // 0 is ref, 1 is arg1\n    switch (printArg->tag)\n    {\n        case CONSTANT_Utf8: // created from native toStrings, needs to be freed after use.\n            printf(\"%.*s\\n\",printArg->info.utf8_info.length,printArg->info.utf8_info.bytes);\n            free(printArg);\n            break;\n        case CONSTANT_String:;\n            CONSTANT_Utf8_info str = frame->classRef->constant_pool[printArg->info.string_info.string_index-1].info.utf8_info;\n            printf(\"%.*s\\n\",str.length,str.bytes);\n            break;\n        default:\n            printf(\"OBJECT, TYPE: %d, @ %p\\n\", printArg->tag, printArg);\n            break;\n    }\n}"
  },
  {
    "path": "src/stack.c",
    "content": "#include \"stack.h\"\n#include \"frame.h\"\n#include <inttypes.h>\n#include <stdlib.h>\n#include \"javaClass.h\"\nStack initStack(uint64_t numItems, StackType stackType){ // size is in operands\n    //The maximum depth of the operand stack of a frame is determined at compile-time and \n    //is supplied along with the code for the method associated with the frame\n    Stack stack;\n    stack.maxSize = stackType * numItems; // in bytes\n    stack.top = 0; // in bytes, again\n    stack.stackType = stackType;\n    stack.stack = malloc(stackType * numItems); // afaik all stacks in here are frame sized. leak\n    return stack;\n}\n \nvoid pushStack(void* val, Stack* stack){\n    if (stack->top + stack->stackType <= stack->maxSize){\n        if (stack->stackType == TYPE_JVMSTACK){\n            *(Frame*)(&stack->stack[stack->top])=*(Frame*)val;\n        }else if(stack->stackType == TYPE_OPERANDSTACK){\n            *(uint64_t*)(&stack->stack[stack->top])=*(uint64_t*)val; \n            // this stack is implemented at DWORD size on 32 bit machines\n            // QWORD size on 64 bit machines. On the other hand, the values we \n            // push on operand stack always 16 bit.\n        } \n        stack->top += stack->stackType;\n    }else{\n        // todo stackoverflow err\n        printf(\"StackOverFlow Error\\n\");\n    }\n}\n\nvoid* popStack(Stack* stack){\n    if ((int64_t)stack->top - stack->stackType >= 0){\n        void* val;\n        stack->top -= stack->stackType;\n        if (stack->stackType == TYPE_JVMSTACK){\n            val = (Frame*)(&stack->stack[stack->top]);\n        }else if(stack->stackType == TYPE_OPERANDSTACK){\n            val = (uint64_t*)(&stack->stack[stack->top]);\n        }\n        return val;\n    }else{\n        // todo stack empty\n        return NULL;\n    }\n}\n\nvoid* peekStack(Stack* stack){\n    return (stack->top > 0)?(Stack*)(stack->stack + stack->top - stack->stackType):(NULL);\n}\n\nvoid destroyStack(Stack* stack){\n    free(stack->stack);\n    free(stack);\n}"
  },
  {
    "path": "src/stringBuilder.c",
    "content": "#include \"stringBuilder.h\"\n#include <inttypes.h>\n#include \"constantPool.h\"\n#include \"frame.h\"\n#include <stdlib.h>\n#include <math.h>\n#include <string.h>\n#include \"debug.h\"\n\nvoid handleStringBuilder(uint64_t* localVariables, Frame* frame, CONSTANT_Utf8_info name_utf8, CONSTANT_Utf8_info desc_utf8){\n    cp_info* strRef = (cp_info*)hGet(localVariables[0],frame->machine->heap);\n    if (isUtf8EqualsToString(name_utf8,\"append\")){\n        if (isUtf8EqualsToString(desc_utf8,\"(I)Ljava/lang/StringBuilder;\") || isUtf8EqualsToString(desc_utf8,\"(J)Ljava/lang/StringBuilder;\")){\n            int stringLength = floor((*(int64_t*)&localVariables[1]==0)?0:log10(abs(*(int64_t*)&localVariables[1]))) + 1;\n            strRef->info.utf8_info.bytes = (char*)hExtend((uint64_t)(strRef->info.utf8_info.bytes), stringLength, frame->machine->heap);\n            char* charRef = hGet((uint64_t)strRef->info.utf8_info.bytes, frame->machine->heap);\n            sprintf(charRef,\"%s%d\",charRef,*(int64_t*)&localVariables[1]);\n            strRef->info.utf8_info.length += stringLength;\n            DEBUG_PRINT((\"append test: %s\\n\", charRef));\n\n        }else if(isUtf8EqualsToString(desc_utf8,\"(Ljava/lang/String;)Ljava/lang/StringBuilder;\")){\n            cp_info* appendRef = (cp_info*)localVariables[1];\n            CONSTANT_Utf8_info appendStrRef;\n            if (appendRef->tag == CONSTANT_String){\n                appendStrRef = frame->classRef->constant_pool[appendRef->info.string_info.string_index-1].info.utf8_info;\n            }else{\n                appendStrRef = appendRef->info.utf8_info;\n            }\n            strRef->info.utf8_info.bytes = (char*)hExtend((uint64_t)(strRef->info.utf8_info.bytes), appendStrRef.length, frame->machine->heap);\n            char* charRef = hGet((uint64_t)strRef->info.utf8_info.bytes, frame->machine->heap);\n            strncat(charRef,appendStrRef.bytes,appendStrRef.length);\n            strRef->info.utf8_info.length += appendStrRef.length;\n            DEBUG_PRINT((\"append test: %s, strLen: %d, ldc: %.*s\\n\", charRef,frame->machine->heap->heap[(uint64_t)strRef->info.utf8_info.bytes].size, appendStrRef.length, appendStrRef.bytes));\n        }\n        pushStack(&localVariables[0], frame->operandStack);\n    }else if(isUtf8EqualsToString(name_utf8,\"toString\")){\n        cp_info* asString = malloc(sizeof(cp_info));\n        asString->tag = CONSTANT_Utf8;\n        asString->info.utf8_info.length = strRef->info.utf8_info.length;\n        asString->info.utf8_info.bytes = hGet((uint64_t)strRef->info.utf8_info.bytes, frame->machine->heap);\n        pushStack(&asString, frame->operandStack);\n    }\n}\n"
  },
  {
    "path": "test/Factorial.class.txt",
    "content": "a13294\n"
  },
  {
    "path": "test/Factorial.java",
    "content": "public class Factorial\n{\n\tpublic static void main(String[] args)\n\t{\n\t\tfinal int NUM_FACTS = 12;\n\t\tlong test=0;\n\t\tfor (long a=0; a<100; a++){\n\t\t\tfor(int i = 0; i < NUM_FACTS; i++){\n\t\t\t\ttest += a/factorial(i);\n\t\t\t}\n\t\t}\n\t\tSystem.out.println(\"a\"+test);\n\t}\n\t\n\tpublic static int factorial(int n)\n\t{\tint result = 1;\n\t\tfor(int i = 2; i <= n; i++)\n\t\t\tresult *= i;\n\t\treturn result;\n\t}\n}"
  },
  {
    "path": "test/HelloWorld.class.txt",
    "content": "Hello World!\n"
  },
  {
    "path": "test/HelloWorld.java",
    "content": "/* HelloWorld.java\r\n */\r\npublic class HelloWorld\r\n{\r\n\tpublic static void main(String[] args) {\r\n\t\tSystem.out.println(\"Hello World!\");\r\n\t}\r\n}"
  },
  {
    "path": "test/InstanceTest.class.txt",
    "content": "12345\n12345\n54321\n"
  },
  {
    "path": "test/InstanceTest.java",
    "content": "class InstanceTest {\n    public int num;\n\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"\"+test_single());\n\t\tSystem.out.println(\"\"+test_multiple_1());\n\t\tSystem.out.println(\"\"+test_multiple_2());\n\t}\n\n    public InstanceTest() {\n        num = 0;\n    }\n\n    public void set_num(int n) {\n        num = n;\n    }\n\n    public int get_num() {\n        return num;\n    }\n\n    public static int test_single() {\n        InstanceTest i = new InstanceTest();\n\n        i.set_num(12345);\n\n        return i.get_num();\n    }\n\n    public static int test_multiple_1() {\n        InstanceTest i1 = new InstanceTest();\n        InstanceTest i2 = new InstanceTest();\n\n        i1.set_num(12345);\n        i2.set_num(54321);\n\n        return i1.get_num();\n    }\n\n    public static int test_multiple_2() {\n        InstanceTest i1 = new InstanceTest();\n        InstanceTest i2 = new InstanceTest();\n\n        i1.set_num(12345);\n        i2.set_num(54321);\n\n        return i2.get_num();\n    }\n}\n"
  },
  {
    "path": "test/StringExample.class.txt",
    "content": "s1: Computer Science\ns2: Computer Science 307\ns4: is fun\ns5: Computer Science 307is fun\ns6: 8total\ns7: total 35\ns8:  35total\n"
  },
  {
    "path": "test/StringExample.java",
    "content": "public class StringExample\n{\tpublic static void main(String[] args)\n\t{\tString s1 = \"Computer Science\";\n\t\tint x = 307;\n\t\tString s2 = s1 + \" \" + x;\n\t\t//String s3 = s2.substring(10,17);\n\t\tString s4 = \"is fun\";\n\t\tString s5 = s2 + s4;\n\t\t\n\t\tSystem.out.println(\"s1: \" + s1);\n\t\tSystem.out.println(\"s2: \" + s2);\n\t\t//System.out.println(\"s3: \" + s3);\n\t\tSystem.out.println(\"s4: \" + s4);\n\t\tSystem.out.println(\"s5: \" + s5);\n\t\t\n\t\t//showing effect of precedence\n\t\t\n\t\tx = 3;\n\t\tint y = 5;\n\t\tString s6 = x + y + \"total\";\n\t\tString s7 = \"total \" + x + y;\n\t\tString s8 = \" \" + x + y + \"total\";\n\t\tSystem.out.println(\"s6: \" + s6);\n\t\tSystem.out.println(\"s7: \" + s7);\n\t\tSystem.out.println(\"s8: \" + s8);\n\t}\n}"
  },
  {
    "path": "test/returnTest.class.txt",
    "content": "75\n"
  },
  {
    "path": "test/returnTest.java",
    "content": "public class returnTest {\n\n    public static void main(String[] args) {\n        System.out.println(topla(11,4));\n    }\n\n    public static int topla(int a, int b){\n        int var = 0;\n        for (int i=0; i<5; i++){\n            var += a+b;\n        }\n        return var;\n    }\n}"
  },
  {
    "path": "test.sh",
    "content": "#!/bin/sh\ncd test\nrm *.class\nrm test/*.out\njavac *.java\ncd ..\n\nfor classFile in test/*.class; do\n    echo \"Running ${classFile}\"\n    ./bin/main \"${classFile%.class}\" > \"${classFile}.out\"\n    \n    if diff \"${classFile}.txt\" \"${classFile}.out\"; then\n        echo \"succeeded\"\n    else\n        echo \"${classFile} failed\"\n        exit 1\n    fi\n\ndone"
  }
]